feat: add and configure next-international with middleware and rewrite default locale

main
RaviAnand Mohabir 3 months ago
parent c68f2934da
commit afcf58be2d

4542
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -22,6 +22,7 @@
"graphql": "^16.9.0", "graphql": "^16.9.0",
"lucide-react": "^0.436.0", "lucide-react": "^0.436.0",
"next": "15.0.0-canary.132", "next": "15.0.0-canary.132",
"next-international": "^1.2.4",
"payload": "^3.0.0-beta.94", "payload": "^3.0.0-beta.94",
"react": "19.0.0-rc-eb3ad065-20240822", "react": "19.0.0-rc-eb3ad065-20240822",
"react-dom": "19.0.0-rc-eb3ad065-20240822", "react-dom": "19.0.0-rc-eb3ad065-20240822",

@ -1,14 +1,17 @@
import "../globals.css";
import { I18nProviderClient } from "@/i18n/client";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Params } from "./params";
import localFont from "next/font/local"; import localFont from "next/font/local";
import "./globals.css";
const geistSans = localFont({ const geistSans = localFont({
src: "./fonts/GeistVF.woff", src: "../fonts/GeistVF.woff",
variable: "--font-geist-sans", variable: "--font-geist-sans",
weight: "100 900", weight: "100 900",
}); });
const geistMono = localFont({ const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff", src: "../fonts/GeistMonoVF.woff",
variable: "--font-geist-mono", variable: "--font-geist-mono",
weight: "100 900", weight: "100 900",
}); });
@ -19,14 +22,16 @@ export const metadata: Metadata = {
}; };
export default function RootLayout({ export default function RootLayout({
params: { locale },
children, children,
}: Readonly<{ }: Readonly<{
children: React.ReactNode; children: React.ReactNode;
params: Params;
}>) { }>) {
return ( return (
<html lang="en"> <html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable}`}> <body className={`${geistSans.variable} ${geistMono.variable}`}>
{children} <I18nProviderClient locale={locale}>{children}</I18nProviderClient>
</body> </body>
</html> </html>
); );

@ -1,7 +1,10 @@
import Image from "next/image"; import Image from "next/image";
import { getI18n } from "@/i18n/server";
import styles from "./page.module.css"; import styles from "./page.module.css";
export default function Home() { export default async function Home() {
const t = await getI18n();
return ( return (
<div className={styles.page}> <div className={styles.page}>
<main className={styles.main}> <main className={styles.main}>
@ -15,7 +18,7 @@ export default function Home() {
/> />
<ol> <ol>
<li> <li>
Get started by editing <code>src/app/page.tsx</code>. {t("general.getStarted")} <code>src/app/page.tsx</code>.
</li> </li>
<li>Save and see your changes instantly.</li> <li>Save and see your changes instantly.</li>
</ol> </ol>

@ -0,0 +1,3 @@
import { Locale } from "@/i18n/locales";
export type Params = { locale: Locale };

@ -0,0 +1,12 @@
"use client";
import { createI18nClient } from "next-international/client";
import { importedLocales } from "./locales";
export const {
useI18n,
useScopedI18n,
I18nProviderClient,
useChangeLocale,
useCurrentLocale,
} = createI18nClient(importedLocales);

@ -0,0 +1,6 @@
export default {
general: {
home: "Startseite",
getStarted: "Um zu starten bearbeiten Sie",
},
} as const;

@ -0,0 +1,6 @@
export default {
general: {
home: "Home",
getStarted: "Get started by editing",
},
} as const;

@ -0,0 +1,29 @@
export const locales = [
{
label: {
de: "Deutsch",
en: "German",
fr: "Allemand",
it: "Tedesco",
},
code: "de",
},
{
label: {
de: "Englisch",
en: "English",
it: "Inglese",
fr: "Anglais",
},
code: "en",
},
] as const;
export type Locale = (typeof locales)[number]["code"];
export const defaultLocale: Locale = "de";
export const importedLocales = {
de: () => import("./de"),
en: () => import("./en"),
} as const;

@ -0,0 +1,16 @@
import { Locale, importedLocales } from "./locales";
import {
createI18nServer,
setStaticParamsLocale,
} from "next-international/server";
export const { getI18n, getScopedI18n, getStaticParams, getCurrentLocale } =
createI18nServer(importedLocales);
export const getLocalizedI18n = async (locale: Locale) => {
const prevLocale = getCurrentLocale();
setStaticParamsLocale(locale);
return [await getI18n(), () => setStaticParamsLocale(prevLocale)] as const;
};

@ -0,0 +1,18 @@
import { defaultLocale, locales } from "@/i18n/locales";
import { NextRequest } from "next/server";
import { createI18nMiddleware } from "next-international/middleware";
const I18nMiddleware = createI18nMiddleware({
locales: locales.map(({ code }) => code),
defaultLocale,
urlMappingStrategy: "rewriteDefault",
});
export function middleware(request: NextRequest) {
return I18nMiddleware(request);
}
export const config = {
matcher: ["/((?!api|admin|static|.*\\..*|_next|favicon.ico|robots.txt).*)"],
};

@ -1,7 +1,11 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2017", "target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"], "lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@ -19,12 +23,25 @@
} }
], ],
"paths": { "paths": {
"@/*": ["./src/*"], "@/*": [
"./src/*"
],
"styled-system/*": [
"./styled-system/*"
],
"@payload-config": [ "@payload-config": [
"./payload.config.ts" "./payload.config.ts"
] ]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "next.config.mts"], "include": [
"exclude": ["node_modules"] "next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"next.config.mts"
],
"exclude": [
"node_modules"
]
} }

@ -4369,7 +4369,7 @@ cli-color@^2.0.2:
memoizee "^0.4.15" memoizee "^0.4.15"
timers-ext "^0.1.7" timers-ext "^0.1.7"
client-only@0.0.1: client-only@0.0.1, client-only@^0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
@ -5670,6 +5670,11 @@ internal-slot@^1.0.4, internal-slot@^1.0.7:
hasown "^2.0.0" hasown "^2.0.0"
side-channel "^1.0.4" side-channel "^1.0.4"
international-types@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/international-types/-/international-types-0.8.1.tgz#c0e593d9911c1a23f64bbd6eb1abb2941fe2353f"
integrity sha512-tajBCAHo4I0LIFlmQ9ZWfjMWVyRffzuvfbXCd6ssFt5u1Zw15DN0UBpVTItXdNa1ls+cpQt3Yw8+TxsfGF8JcA==
ip-address@^9.0.5: ip-address@^9.0.5:
version "9.0.5" version "9.0.5"
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a"
@ -6416,6 +6421,15 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
next-international@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/next-international/-/next-international-1.2.4.tgz#abe50b2aa3ba7ecf92d41f87537796a4b2dd0ba3"
integrity sha512-JQvp+h2iSgA/t8hu5S/Lwow1ZErJutQRdpnplxjv4VTlCiND8T95fYih8BjkHcVhQbtM+Wu9Mb1CM32wD9hlWQ==
dependencies:
client-only "^0.0.1"
international-types "^0.8.1"
server-only "^0.0.1"
next-tick@^1.1.0: next-tick@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
@ -7266,6 +7280,11 @@ semver@^7.3.8, semver@^7.6.0, semver@^7.6.3:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
server-only@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e"
integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==
set-function-length@^1.2.1: set-function-length@^1.2.1:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"

Loading…
Cancel
Save