mirror of
https://github.com/resend/react-email.git
synced 2026-09-14 14:18:02 +08:00
feat(docs): guide for i18n with react-intl (#2775)
Co-authored-by: Chris Pennington <cpenn368@gmail.com>
This commit is contained in:
@@ -46,6 +46,16 @@
|
||||
"getting-started/updating-react-email"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Guides",
|
||||
"pages": [
|
||||
{
|
||||
"group": "Internationalization",
|
||||
"icon": "earth-americas",
|
||||
"pages": ["guides/internationalization/react-intl"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Components",
|
||||
"pages": [
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
---
|
||||
title: 'React Intl'
|
||||
sidebarTitle: 'React Intl'
|
||||
description: 'Integrating React Email with React Intl'
|
||||
'og:image': 'https://react.email/static/covers/react-email.png'
|
||||
---
|
||||
|
||||
React Email supports [React Intl](https://formatjs.github.io/react-intl/) for internationalization.
|
||||
|
||||
This guide shows how to convert an English React Email template to support multiple locales.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To get the most out of this guide, you’ll need to:
|
||||
|
||||
- [Set up React Email](/getting-started/automatic-setup)
|
||||
- [Install React Intl](https://formatjs.github.io/docs/getting-started/installation)
|
||||
|
||||
<CodeGroup>
|
||||
```bash npm
|
||||
npm i -S react-intl
|
||||
```
|
||||
|
||||
```bash bun
|
||||
bun add react-intl
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn add react-intl
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm add react-intl
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
This guide will use the following email template as a base.
|
||||
|
||||
```tsx emails/welcome/index.tsx
|
||||
interface WelcomeEmailProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
function WelcomeEmail({
|
||||
name,
|
||||
}: WelcomeEmailProps) {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Preview>Welcome to Acme</Preview>
|
||||
<Tailwind>
|
||||
<Body className="bg-gray-100 font-sans">
|
||||
<Container className="mx-auto py-10 px-5">
|
||||
<Section className="bg-white rounded-lg p-8">
|
||||
<Heading className="text-2xl font-bold text-gray-900 m-0 mb-6">
|
||||
Welcome to Acme
|
||||
</Heading>
|
||||
<Text className="text-base leading-6 text-gray-600 m-0 mb-4">
|
||||
Hi {name}
|
||||
</Text>
|
||||
<Text className="text-base leading-6 text-gray-600 m-0 mb-4">
|
||||
Thanks for signing up! We're excited to have you on board.
|
||||
</Text>
|
||||
<Button
|
||||
href="https://example.com/dashboard"
|
||||
className="bg-indigo-600 rounded-md text-white text-base font-semibold no-underline text-center block py-3 px-6 my-6"
|
||||
>
|
||||
Get Started
|
||||
</Button>
|
||||
<Hr className="border-gray-200 my-6" />
|
||||
<Text className="text-sm text-gray-400 m-0">
|
||||
If you have any questions, reply to this email. We're here to help!
|
||||
</Text>
|
||||
</Section>
|
||||
</Container>
|
||||
</Body>
|
||||
</Tailwind>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
|
||||
WelcomeEmail.PreviewProps = {
|
||||
name: 'John Lennon',
|
||||
};
|
||||
```
|
||||
|
||||
## Internationalization with React Intl
|
||||
|
||||
React Intl is a library for internationalization and localization that provides a way to format messages in different languages.
|
||||
|
||||
### 1. Create messages for each locale
|
||||
|
||||
For each locale, create a new JSON file containing the content of the email in that locale.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```json emails/welcome/en.json
|
||||
{
|
||||
"header": "Welcome to Acme",
|
||||
"hi": "Hi",
|
||||
"thanks": "Thanks for signing up! We're excited to have you on board.",
|
||||
"get-started": "Get Started",
|
||||
"questions": "If you have any questions, reply to this email. We're here to help!"
|
||||
}
|
||||
```
|
||||
|
||||
```json emails/welcome/es.json
|
||||
{
|
||||
"header": "Bienvenido a Acme",
|
||||
"hi": "Hola",
|
||||
"thanks": "Gracias por registrarte! Estamos emocionados de tenerte en la plataforma.",
|
||||
"get-started": "Comenzar",
|
||||
"questions": "Si tienes alguna pregunta, responde a este correo electrónico. Estamos aquí para ayudarte!"
|
||||
}
|
||||
```
|
||||
|
||||
```json emails/welcome/pt.json
|
||||
{
|
||||
"header": "Bem-vindo ao Acme",
|
||||
"hi": "Olá",
|
||||
"thanks": "Obrigado por se inscrever! Estamos ansiosos para te receber na plataforma.",
|
||||
"get-started": "Começar",
|
||||
"questions": "Se você tiver alguma dúvida, responda a este e-mail. Estamos aqui para ajudar!"
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Alternatively, you can add locale-specific messages in the email file.
|
||||
|
||||
<Expandable title="Example">
|
||||
|
||||
```tsx
|
||||
const messages = {
|
||||
en: {
|
||||
header: 'Welcome to Acme',
|
||||
hi: 'Hi',
|
||||
thanks: 'Thanks for signing up! We\'re excited to have you on board.',
|
||||
'get-started': 'Get Started',
|
||||
questions: 'If you have any questions, reply to this email. We\'re here to help!',
|
||||
},
|
||||
es: {
|
||||
header: 'Bienvenido a Acme',
|
||||
hi: 'Hola',
|
||||
thanks: 'Gracias por registrarte! Estamos emocionados de tenerte en la plataforma.',
|
||||
'get-started': 'Comenzar',
|
||||
questions: 'Si tienes alguna pregunta, responde a este correo electrónico. Estamos aquí para ayudarte!',
|
||||
},
|
||||
pt: {
|
||||
header: 'Bem-vindo ao Acme',
|
||||
hi: 'Olá',
|
||||
thanks: 'Obrigado por se inscrever! Estamos ansiosos para te receber na plataforma.',
|
||||
'get-started': 'Começar',
|
||||
questions: 'Se você tiver alguma dúvida, responda a este e-mail. Estamos aqui para ajudar!',
|
||||
},
|
||||
};
|
||||
```
|
||||
</Expandable>
|
||||
|
||||
|
||||
### 2. Update the email props
|
||||
|
||||
Add the `locale` prop to the email template, interface, and test data.
|
||||
|
||||
```tsx
|
||||
interface WelcomeEmailProps {
|
||||
name: string;
|
||||
// [!code ++]
|
||||
locale: 'en' | 'es' | 'pt';
|
||||
}
|
||||
|
||||
function WelcomeEmail({
|
||||
name,
|
||||
// [!code ++]
|
||||
locale,
|
||||
}: WelcomeEmailProps) {
|
||||
return (
|
||||
...
|
||||
);
|
||||
}
|
||||
|
||||
WelcomeEmail.PreviewProps = {
|
||||
name: 'John Lennon',
|
||||
// [!code ++]
|
||||
locale: 'en',
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### 3. Update the email template
|
||||
|
||||
In the email template, remove the hardcoded content and use `createIntl` to format the email message strings.
|
||||
|
||||
```tsx
|
||||
// [!code ++]
|
||||
import { createIntl } from 'react-intl';
|
||||
|
||||
interface WelcomeEmailProps {
|
||||
name: string;
|
||||
locale: 'en' | 'es' | 'pt';
|
||||
}
|
||||
|
||||
// [!code --]
|
||||
function WelcomeEmail({
|
||||
// [!code ++]
|
||||
async function WelcomeEmail({
|
||||
name,
|
||||
locale,
|
||||
}: WelcomeEmailProps) {
|
||||
// [!code ++:4]
|
||||
const { formatMessage } = createIntl({
|
||||
messages: await import(`emails/welcome/${locale}.json`), // if using locale-specific files
|
||||
locale,
|
||||
});
|
||||
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
// [!code --]
|
||||
<Preview>Welcome to Acme</Preview>
|
||||
// [!code ++]
|
||||
<Preview>{formatMessage({ id: 'header' })}</Preview>
|
||||
<Tailwind>
|
||||
<Body className="bg-gray-100 font-sans">
|
||||
<Container className="mx-auto py-10 px-5">
|
||||
<Section className="bg-white rounded-lg p-8">
|
||||
<Heading className="text-2xl font-bold text-gray-900 m-0 mb-6">
|
||||
// [!code --]
|
||||
Welcome to Acme
|
||||
// [!code ++]
|
||||
{formatMessage({ id: 'header' })}
|
||||
</Heading>
|
||||
<Text className="text-base leading-6 text-gray-600 m-0 mb-4">
|
||||
// [!code --]
|
||||
Hi {name}
|
||||
// [!code ++]
|
||||
{formatMessage({ id: 'hi' })} {name}
|
||||
</Text>
|
||||
<Text className="text-base leading-6 text-gray-600 m-0 mb-4">
|
||||
// [!code --]
|
||||
Thanks for signing up! We're excited to have you on board.
|
||||
// [!code ++]
|
||||
{formatMessage({ id: 'thanks' })}
|
||||
</Text>
|
||||
<Button
|
||||
href="https://example.com/dashboard"
|
||||
className="bg-indigo-600 rounded-md text-white text-base font-semibold no-underline text-center block py-3 px-6 my-6"
|
||||
>
|
||||
// [!code --]
|
||||
Get Started
|
||||
// [!code ++]
|
||||
{formatMessage({ id: 'get-started' })}
|
||||
</Button>
|
||||
<Hr className="border-gray-200 my-6" />
|
||||
<Text className="text-sm text-gray-400 m-0">
|
||||
// [!code --]
|
||||
If you have any questions, reply to this email. We're here to help!
|
||||
// [!code ++]
|
||||
{formatMessage({ id: 'questions' })}
|
||||
</Text>
|
||||
</Section>
|
||||
</Container>
|
||||
</Body>
|
||||
</Tailwind>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
|
||||
WelcomeEmail.PreviewProps = {
|
||||
name: 'John Lennon',
|
||||
locale: 'en',
|
||||
};
|
||||
```
|
||||
|
||||
### 4. Update any email calls
|
||||
|
||||
When calling the email template, pass the `locale` prop to the email component.
|
||||
|
||||
## Try it yourself
|
||||
|
||||
<CardGroup>
|
||||
<Card
|
||||
title="React Email with React Intl example"
|
||||
icon='arrow-up-right-from-square'
|
||||
iconType="duotone"
|
||||
href="https://github.com/resend/react-email-react-intl-example"
|
||||
>
|
||||
See the full source code.
|
||||
</Card>
|
||||
<Card
|
||||
title="Resend with React Intl example"
|
||||
icon='arrow-up-right-from-square'
|
||||
iconType="duotone"
|
||||
href="https://github.com/resend/resend-react-intl-example"
|
||||
>
|
||||
See the full source code.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Reference in New Issue
Block a user