Skip to content

Commit

Permalink
feat: add internationalization package
Browse files Browse the repository at this point in the history
  • Loading branch information
alcercu committed Nov 25, 2024
1 parent 9027c7c commit 13a88fa
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 9 deletions.
6 changes: 6 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"HomePage": {
"title": "Hello world!",
"about": "Go to the about page"
}
}
6 changes: 6 additions & 0 deletions messages/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"HomePage": {
"title": "Hola Mundo!",
"about": "Saber más"
}
}
6 changes: 5 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import createNextIntlPlugin from "next-intl/plugin";

const withNextIntl = createNextIntlPlugin();

/** @type {import('next').NextConfig} */
const nextConfig = {};

export default nextConfig;
export default withNextIntl(nextConfig);
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"clsx": "^2.1.1",
"next": "14.2.8",
"next-intl": "^3.25.1",
"react": "^18",
"react-dom": "^18"
},
Expand Down
23 changes: 16 additions & 7 deletions src/app/layout.tsx → src/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import "../globals.css";

const geistSans = localFont({
src: "./fonts/GeistVF.woff",
src: "../fonts/GeistVF.woff",
variable: "--font-geist-sans",
weight: "100 900",
});
const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
src: "../fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
weight: "100 900",
});
Expand All @@ -18,18 +20,25 @@ export const metadata: Metadata = {
description: "Generated by create next app",
};

export default function RootLayout({
export default async function RootLayout({
children,
params: { locale },
}: Readonly<{
children: React.ReactNode;
params: { locale: string };
}>) {

const messages = await getMessages({ locale });

return (
<html lang="en">
<html lang={locale}>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
<NextIntlClientProvider {...{ messages }}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}
};
4 changes: 4 additions & 0 deletions src/app/page.tsx → src/app/[locale]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import clsx from "clsx";
import Image from "next/image";
import { useTranslations } from "next-intl";

export default function Home() {
const t = useTranslations("HomePage");

return (
<div
className={clsx(
Expand Down Expand Up @@ -40,6 +43,7 @@ export default function Home() {
.
</li>
<li>Save and see your changes instantly.</li>
<li>{t("title")}</li>
</ol>

<div className="flex gap-4 items-center flex-col sm:flex-row">
Expand Down
18 changes: 18 additions & 0 deletions src/i18n/request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { getRequestConfig } from 'next-intl/server';

import { routing } from './routing';

export default getRequestConfig(async ({ requestLocale }) => {
// This typically corresponds to the `[locale]` segment
let locale = await requestLocale;

// Ensure that a valid locale is used
if (!locale || !routing.locales.includes(locale)) {
locale = routing.defaultLocale;
}

return {
locale,
messages: (await import(`../../messages/${locale}.json`)).default
};
});
17 changes: 17 additions & 0 deletions src/i18n/routing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createNavigation } from "next-intl/navigation";
import { defineRouting } from "next-intl/routing";

const locales = ["en", "es"];

export const routing = defineRouting({
// A list of all locales that are supported
locales,

// Used when no locale matches
defaultLocale: "en",
});

// Lightweight wrappers around Next.js' navigation APIs
// that will consider the routing configuration
export const {Link, redirect, usePathname, useRouter, getPathname} =
createNavigation(routing);
10 changes: 10 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import createMiddleware from "next-intl/middleware";

import { routing } from "@/i18n/routing";

export default createMiddleware(routing);

export const config = {
// Match only internationalized pathnames
matcher: ["/", `/(en|es)/:path*`]
};
98 changes: 97 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,56 @@ __metadata:
languageName: node
linkType: hard

"@formatjs/ecma402-abstract@npm:2.2.4":
version: 2.2.4
resolution: "@formatjs/ecma402-abstract@npm:2.2.4"
dependencies:
"@formatjs/fast-memoize": "npm:2.2.3"
"@formatjs/intl-localematcher": "npm:0.5.8"
tslib: "npm:2"
checksum: 10c0/3f262533fa704ea7a1a7a8107deee2609774a242c621f8cb5dd4bf4c97abf2fc12f5aeda3f4ce85be18147c484a0ca87303dca6abef53290717e685c55eabd2d
languageName: node
linkType: hard

"@formatjs/fast-memoize@npm:2.2.3, @formatjs/fast-memoize@npm:^2.2.0":
version: 2.2.3
resolution: "@formatjs/fast-memoize@npm:2.2.3"
dependencies:
tslib: "npm:2"
checksum: 10c0/f1004c3b280de7e362bd37c5f48ff34c2ba1d6271d4a7b695fed561d1201a3379397824d8bffbf15fecee344d1e70398393bbb04297f242692310a305f12e75b
languageName: node
linkType: hard

"@formatjs/icu-messageformat-parser@npm:2.9.4":
version: 2.9.4
resolution: "@formatjs/icu-messageformat-parser@npm:2.9.4"
dependencies:
"@formatjs/ecma402-abstract": "npm:2.2.4"
"@formatjs/icu-skeleton-parser": "npm:1.8.8"
tslib: "npm:2"
checksum: 10c0/f1ed14ece7ef0abc9fb62e323b78c994fc772d346801ad5aaa9555e1a7d5c0fda791345f4f2e53a3223f0b82c1a4eaf9a83544c1c20cb39349d1a39bedcf1648
languageName: node
linkType: hard

"@formatjs/icu-skeleton-parser@npm:1.8.8":
version: 1.8.8
resolution: "@formatjs/icu-skeleton-parser@npm:1.8.8"
dependencies:
"@formatjs/ecma402-abstract": "npm:2.2.4"
tslib: "npm:2"
checksum: 10c0/5ad78a5682e83b973e6fed4fca68660b944c41d1e941f0c84d69ff3d10ae835330062dc0a2cf0d237d2675ad3463405061a3963c14c2b9d8d1c1911f892b1a8d
languageName: node
linkType: hard

"@formatjs/intl-localematcher@npm:0.5.8, @formatjs/intl-localematcher@npm:^0.5.4":
version: 0.5.8
resolution: "@formatjs/intl-localematcher@npm:0.5.8"
dependencies:
tslib: "npm:2"
checksum: 10c0/7a660263986326b662d4cb537e8386331c34fda61fb830b105e6c62d49be58ace40728dae614883b27a41cec7b1df8b44f72f79e16e6028bfca65d398dc04f3b
languageName: node
linkType: hard

"@humanwhocodes/config-array@npm:^0.13.0":
version: 0.13.0
resolution: "@humanwhocodes/config-array@npm:0.13.0"
Expand Down Expand Up @@ -2030,6 +2080,18 @@ __metadata:
languageName: node
linkType: hard

"intl-messageformat@npm:^10.5.14":
version: 10.7.7
resolution: "intl-messageformat@npm:10.7.7"
dependencies:
"@formatjs/ecma402-abstract": "npm:2.2.4"
"@formatjs/fast-memoize": "npm:2.2.3"
"@formatjs/icu-messageformat-parser": "npm:2.9.4"
tslib: "npm:2"
checksum: 10c0/691895fb6a73a2feb2569658706e0d452861441de184dd1c9201e458a39fb80fc80080dd40d3d370400a52663f87de7a6d5a263c94245492f7265dd760441a95
languageName: node
linkType: hard

"ip-address@npm:^9.0.5":
version: 9.0.5
resolution: "ip-address@npm:9.0.5"
Expand Down Expand Up @@ -2705,6 +2767,27 @@ __metadata:
languageName: node
linkType: hard

"negotiator@npm:^1.0.0":
version: 1.0.0
resolution: "negotiator@npm:1.0.0"
checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b
languageName: node
linkType: hard

"next-intl@npm:^3.25.1":
version: 3.25.1
resolution: "next-intl@npm:3.25.1"
dependencies:
"@formatjs/intl-localematcher": "npm:^0.5.4"
negotiator: "npm:^1.0.0"
use-intl: "npm:^3.25.1"
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
checksum: 10c0/7d78503b7d6826db0aa5be8ff109e5b81c410621f370a383ad67ed2eccc472729821c499dd8dfd91219a922bf91ba829410e5e0340b20e76d501002db0c75f3c
languageName: node
linkType: hard

"next@npm:14.2.8":
version: 14.2.8
resolution: "next@npm:14.2.8"
Expand Down Expand Up @@ -3810,7 +3893,7 @@ __metadata:
languageName: node
linkType: hard

"tslib@npm:^2.4.0":
"tslib@npm:2, tslib@npm:^2.4.0":
version: 2.8.1
resolution: "tslib@npm:2.8.1"
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
Expand Down Expand Up @@ -3951,6 +4034,18 @@ __metadata:
languageName: node
linkType: hard

"use-intl@npm:^3.25.1":
version: 3.25.1
resolution: "use-intl@npm:3.25.1"
dependencies:
"@formatjs/fast-memoize": "npm:^2.2.0"
intl-messageformat: "npm:^10.5.14"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0
checksum: 10c0/daeedebc0780f2ab377e18021df197783dde1378910c5913bf68ab05388dd2a6c079f1569253d06b14a695ea29626de6d1f05ae1c9329b547e26bbd76289cc68
languageName: node
linkType: hard

"util-deprecate@npm:^1.0.2":
version: 1.0.2
resolution: "util-deprecate@npm:1.0.2"
Expand All @@ -3970,6 +4065,7 @@ __metadata:
eslint-config-next: "npm:^15.0.3"
husky: "npm:^9.1.7"
next: "npm:14.2.8"
next-intl: "npm:^3.25.1"
postcss: "npm:^8"
react: "npm:^18"
react-dom: "npm:^18"
Expand Down

0 comments on commit 13a88fa

Please sign in to comment.