react-intl / next-intl
react-intl (FormatJS) dan next-intl adalah library populer untuk i18n di React dan Next.js. Keduanya menggunakan ICU Message Format standar industri.
Setup react-intl
npm install react-intl
// messages/id.json
{
"greeting": "Halo, {name}!",
"items_count": "{count, plural, =0 {Kosong} one {# item} other {# items}}"
}
// messages/en.json
{
"greeting": "Hello, {name}!",
"items_count": "{count, plural, =0 {Empty} one {# item} other {# items}}"
}
Provider Setup
import { IntlProvider } from "react-intl";
import idMessages from "./messages/id.json";
import enMessages from "./messages/en.json";
const messages = { id: idMessages, en: enMessages };
function App() {
const [locale, setLocale] = useState("id");
return (
<IntlProvider locale={locale} messages={messages[locale]}>
<MainApp />
</IntlProvider>
);
}
FormattedMessage Component
import { FormattedMessage, FormattedNumber, FormattedDate } from "react-intl";
function Welcome({ user }) {
return (
<div>
<h1>
<FormattedMessage id="greeting" values={{ name: user.name }} />
</h1>
<p>
<FormattedNumber value={user.balance} style="currency" currency="IDR" />
</p>
<p>
Bergabung: <FormattedDate value={user.joinDate} year="numeric" month="long" />
</p>
</div>
);
}
useIntl Hook
import { useIntl } from "react-intl";
function SearchBox() {
const intl = useIntl();
return (
<input
placeholder={intl.formatMessage({ id: "search.placeholder" })}
aria-label={intl.formatMessage({ id: "search.label" })}
/>
);
}
next-intl untuk Next.js
npm install next-intl
// next.config.js
const withNextIntl = require("next-intl/plugin")();
module.exports = withNextIntl({ /* next config */ });
// i18n/request.ts
import { getRequestConfig } from "next-intl/server";
export default getRequestConfig(async ({ locale }) => ({
messages: (await import(`../messages/${locale}.json`)).default
}));
// app/[locale]/page.tsx
import { useTranslations } from "next-intl";
export default function Home() {
const t = useTranslations("HomePage");
return <h1>{t("title")}</h1>;
}