next-app-locale
v1.0.7
Published
A simple way to create pages made for different locales in Next (with App Directory)!
Downloads
2
Readme
A simple way to create pages made for different locales in Next (with App Directory)!
Summary
Installation
pnpm add next-app-locale
or
npm install next-app-locale
or
yarn add next-app-locale
Configuration
Create an instance of the Translator class in, for example services/Translator.ts
:
import { Translator } from "next-app-locale";
import { ptBr } from "../languages/pt-br"; //It can be .json, .tsx, .ts, etc.
import { enUs } from "../languages/en-us";
//The first location is the default locale!
export const translator = new Translator<typeof ptBr>({
"pt-br": ptBr, //But ptBr and enUs, for example, must be an object!
"en-us": enUs //Keep the locale object's keys in lower case! (ex: pt-br, fr, en)
});
Language schema
See an example file languages/en-us.json
:
{
"home": {
"main": {
"title": "Hello world!",
"paragraph": "EXAMPLE 01",
"date": "2023/07/16"
}
},
}
And languages/en-us.tsx
using dayjs
library:
import dayjs from "dayjs";
require("dayjs/locale/en");
dayjs.locale("en");
export const enUs = {
home: {
main: {
title: "Hello world!",
paragraph: <>
EXAMPLE <strong>01</strong>
</>,
date: `Today is: ${dayjs().format("MMMM D, YYYY - h A")}!`
}
}
};
Final settings
Out of any other folder like src
or app
create a middleware.ts
:
import { NextRequest, NextResponse } from 'next/server';
import { translator } from './services/Translator';
export async function middleware(request: NextRequest) {
const redirectURL = translator.middleware(request);
if(redirectURL) {
//Will redirect if needed to default locale
return NextResponse.redirect(redirectURL);
};
return NextResponse.next();
};
//Important!
export const config = {
matcher: [
'/((?!_next).*)'
]
};
Now, in app/[lang]/layout.tsx
:
import { translator } from '../../services/Translator';
//Important!
export async function generateStaticParams() {
return translator.getLocales().map((lng) => ({ lng }));
};
export default function RootLayout({
children,
params: {
lang
}
}: {
children: React.ReactNode;
params: {
lang: string;
};
}) {
//Will set the locale!
translator.setLocale(lang);
return (
<html lang={lang}>
<body>
{children}
</body>
</html>
)
};
This way, you can use it on your other pages inside app\[lang]
without passing any parameters. For example, in app\[lang]\page.tsx
:
import { translator } from '../../services/Translator';
export default function Home() {
const content = translator.getContent("home");
//The variable content is strongly typed!
return (
<main>
<h1>
{content.main.title}
</h1>
<p>{content.main.paragraph}</p>
<p>{content.main.date}</p>
</main>
)
}
Changing the locale
To change the locale, first create a component, components/LocaleSwitcher.tsx
, for example:
"use client"; //Important!
import Link from "next/link";
import { usePathname } from "next/navigation";
import { translator } from "@/services/Translator";
//You will only need to pass the "lang" parameter
//if you want to update this component's state after
//change the route!
export function LocaleSwitcher({
lang
}: {
lang?: string
}) {
//You have to retrieve the pathname!
const pathname = usePathname();
//is not a hook!
//const content = translator.getContent("header");
//const isPtBr = translator.isLocale("pt-br");
//can refresh!
//const isPtBr = lang === "pt-br";
return (
<ul>
<li>
<Link
href={translator.getNewLocaleURL(pathname, "pt-br")}
>
Português
</Link>
</li>
<li>
<Link
href={translator.getNewLocaleURL(pathname, "en-us")}
>
English
</Link>
</li>
</ul>
);
};
You can place this component in the app/[lang]/layout.tsx
itself:
import { LocaleSwitcher } from "../../components/LocaleSwitcher";
import { translator } from '../../services/Translator';
//Important!
export async function generateStaticParams() {
return translator.getLocales().map((lng) => ({ lng }));
};
export default function RootLayout({
children,
params: {
lang
}
}: {
children: React.ReactNode;
params: {
lang: string;
};
}) {
//Will set the locale!
translator.setLocale(lang);
return (
<html lang={lang}>
<header>
<LocaleSwitcher/>
</header>
<body>
{children}
</body>
</html>
)
};
Navigation
To recover any route maintaining locality, you can use the function getNewLocaleURL
with just one parameter:
<Link href={translator.getNewLocaleURL("/another-route")}>
Another route
</Link>
Demonstrations
See some demos: