packages: add next-intl

This commit is contained in:
vchikalkin 2024-12-08 18:24:23 +03:00
parent 5e7c8a8ff4
commit 8ab2205821
7 changed files with 125 additions and 21 deletions

View File

@ -1,22 +1,22 @@
import { type Metadata } from 'next';
import { NextIntlClientProvider } from 'next-intl';
import { getLocale, getMessages } from 'next-intl/server';
import { Inter } from 'next/font/google';
import './globals.css';
const inter = Inter({ subsets: ['latin', 'cyrillic'] });
export const metadata: Metadata = {
description: 'Generated by create next app',
title: 'Create Next App',
};
export default async function RootLayout({ children }: { readonly children: React.ReactNode }) {
const locale = await getLocale();
// Providing all messages to the client
// side is the easiest way to get started
const messages = await getMessages();
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<html lang={locale}>
<body className={inter.className}>
<NextIntlClientProvider messages={messages}>{children}</NextIntlClientProvider>
</body>
</html>
);
}

View File

@ -1,9 +1,10 @@
export default function Home() {
import { useTranslations } from 'next-intl';
export default function HomePage() {
const t = useTranslations('HomePage');
return (
<div>
<main>
<h1 className="text-4xl font-semibold tracking-tight ">Hello</h1>
</main>
<h1 className="text-4xl font-semibold tracking-tight ">{t('title')}</h1>
</div>
);
}

12
i18n/request.ts Normal file
View File

@ -0,0 +1,12 @@
import { getRequestConfig } from 'next-intl/server';
export default getRequestConfig(async () => {
// Provide a static locale, fetch a user setting,
// read from `cookies()`, `headers()`, etc.
const locale = 'ru';
return {
locale,
messages: (await import(`../messages/${locale}.json`)).default,
};
});

5
messages/ru.json Normal file
View File

@ -0,0 +1,5 @@
{
"HomePage": {
"title": "Привет!"
}
}

View File

@ -1,7 +1,8 @@
import type { NextConfig } from "next";
import { type NextConfig } from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
const nextConfig: NextConfig = {
/* config options here */
};
const withNextIntl = createNextIntlPlugin();
export default nextConfig;
const nextConfig: NextConfig = {};
export default withNextIntl(nextConfig);

View File

@ -13,6 +13,7 @@
"clsx": "^2.1.1",
"lucide-react": "^0.468.0",
"next": "15.0.4",
"next-intl": "^3.26.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^2.5.5",

84
pnpm-lock.yaml generated
View File

@ -20,6 +20,9 @@ importers:
next:
specifier: 15.0.4
version: 15.0.4(@babel/core@7.25.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
next-intl:
specifier: ^3.26.0
version: 3.26.0(next@15.0.4(@babel/core@7.25.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
react:
specifier: ^19.0.0
version: 19.0.0
@ -754,6 +757,21 @@ packages:
resolution: {integrity: sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@formatjs/ecma402-abstract@2.2.5':
resolution: {integrity: sha512-ep/5vGkyZvMSi6s8nQG8k7vTcKjuXs402fgGIWixj0AWRgKbeaZeLuYc32NIPXexgBjWepMeZGgHLuZXkuD2Gg==}
'@formatjs/fast-memoize@2.2.4':
resolution: {integrity: sha512-8SzI0cBADgbLOYsoQW/IqVHljCH964CrOdESFQ07wMkRLP90+MfV7k6gZPiGD88ubqET9igJV5c292rT28B7xQ==}
'@formatjs/icu-messageformat-parser@2.9.5':
resolution: {integrity: sha512-mHauC9wuVXtnshAIoAYjlNrh6+OFOT6cC4fpK+AG+DHkVWwIPFVQE28hLQ/KptuvQ8VMfG/zYx6rRjtaeFPkSQ==}
'@formatjs/icu-skeleton-parser@1.8.9':
resolution: {integrity: sha512-1KSSlU7ywsU5E5v7xr6VTlBzLGszMi3GOu7EVINjkfA501GN5OkeNSbd5q6ie1wIknZJGBlqkvXPYYdp3YXjpw==}
'@formatjs/intl-localematcher@0.5.8':
resolution: {integrity: sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==}
'@graphql-eslint/eslint-plugin@3.20.1':
resolution: {integrity: sha512-RbwVlz1gcYG62sECR1u0XqMh8w5e5XMCCZoMvPQ3nJzEBCTfXLGX727GBoRmSvY1x4gJmqNZ1lsOX7lZY14RIw==}
engines: {node: '>=12'}
@ -2303,6 +2321,9 @@ packages:
resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
engines: {node: '>= 0.4'}
intl-messageformat@10.7.8:
resolution: {integrity: sha512-XnFFzJnTfdaDqeiF/ZAUjpkoKEM8UKwHijQXuqpLiM42kuJCawytP/rYAMDYNNaWww/PTaI0rIoG4oUjRrRlnA==}
is-arguments@1.1.1:
resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==}
engines: {node: '>= 0.4'}
@ -2652,6 +2673,16 @@ packages:
resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==}
engines: {node: '>=18'}
negotiator@1.0.0:
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
engines: {node: '>= 0.6'}
next-intl@3.26.0:
resolution: {integrity: sha512-gkamnHIANQzeW8xpTGRxd0xiOCztQhY8GDp79fgdlw0GioqrjTEfSWLhHkgaAtvHRbuh/ByJdwiEY5eNK9bUSQ==}
peerDependencies:
next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
next@15.0.4:
resolution: {integrity: sha512-nuy8FH6M1FG0lktGotamQDCXhh5hZ19Vo0ht1AOIQWrYJLP598TIUagKtvJrfJ5AGwB/WmDqkKaKhMpVifvGPA==}
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
@ -3366,6 +3397,11 @@ packages:
urlpattern-polyfill@8.0.2:
resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==}
use-intl@3.26.0:
resolution: {integrity: sha512-HGXmpjGlbEv1uFZPfm557LK8p/hv0pKF9UwnrJeHUTxQx6bUGzMgpmPRLCVY3zkr7hfjy4LPwQJfk4Fhnn+dIg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
@ -4353,6 +4389,31 @@ snapshots:
dependencies:
levn: 0.4.1
'@formatjs/ecma402-abstract@2.2.5':
dependencies:
'@formatjs/fast-memoize': 2.2.4
'@formatjs/intl-localematcher': 0.5.8
tslib: 2.8.1
'@formatjs/fast-memoize@2.2.4':
dependencies:
tslib: 2.8.1
'@formatjs/icu-messageformat-parser@2.9.5':
dependencies:
'@formatjs/ecma402-abstract': 2.2.5
'@formatjs/icu-skeleton-parser': 1.8.9
tslib: 2.8.1
'@formatjs/icu-skeleton-parser@1.8.9':
dependencies:
'@formatjs/ecma402-abstract': 2.2.5
tslib: 2.8.1
'@formatjs/intl-localematcher@0.5.8':
dependencies:
tslib: 2.8.1
'@graphql-eslint/eslint-plugin@3.20.1(@babel/core@7.25.2)(@types/node@20.17.9)(graphql@16.9.0)':
dependencies:
'@babel/code-frame': 7.26.2
@ -6394,6 +6455,13 @@ snapshots:
hasown: 2.0.2
side-channel: 1.0.6
intl-messageformat@10.7.8:
dependencies:
'@formatjs/ecma402-abstract': 2.2.5
'@formatjs/fast-memoize': 2.2.4
'@formatjs/icu-messageformat-parser': 2.9.5
tslib: 2.8.1
is-arguments@1.1.1:
dependencies:
call-bind: 1.0.8
@ -6715,6 +6783,16 @@ snapshots:
natural-orderby@5.0.0: {}
negotiator@1.0.0: {}
next-intl@3.26.0(next@15.0.4(@babel/core@7.25.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0):
dependencies:
'@formatjs/intl-localematcher': 0.5.8
negotiator: 1.0.0
next: 15.0.4(@babel/core@7.25.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
react: 19.0.0
use-intl: 3.26.0(react@19.0.0)
next@15.0.4(@babel/core@7.25.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
dependencies:
'@next/env': 15.0.4
@ -7486,6 +7564,12 @@ snapshots:
urlpattern-polyfill@8.0.2: {}
use-intl@3.26.0(react@19.0.0):
dependencies:
'@formatjs/fast-memoize': 2.2.4
intl-messageformat: 10.7.8
react: 19.0.0
util-deprecate@1.0.2: {}
validate-npm-package-license@3.0.4: