React bindings for @mango.dev/core — provides a context provider and hook to read and switch languages in your React app.
MangoProvider— wraps your app and supplies language context to all child componentsuseMangohook — access the current language, switch languages, and resolve multilingual fieldst()helper — resolves any translated field (or plain primitive) to a displayable string for the active language- Type-safe language switching —
setLangonly accepts languages defined in the provider - Fallback support — if a translation is missing for the active language, falls back to the first language in the list
- React 18+ compatible, built for client components
# npm
npm install @mango.dev/react @mango.dev/core
# pnpm
pnpm add @mango.dev/react @mango.dev/core
# yarn
yarn add @mango.dev/react @mango.dev/corePeer dependencies: react >= 18, react-dom >= 18
The langs array must match exactly what you passed to new Mango({ langs }) in your backend/server code.
import { MangoProvider } from "@mango.dev/react";
const LANGS = ["en", "es", "fr"] as const;
export default function App() {
return (
<MangoProvider langs={LANGS} defaultLang="en">
<YourApp />
</MangoProvider>
);
}Type your component props with Translated<T> from @mango.dev/core to get full autocomplete on t() calls.
import { useMango } from "@mango.dev/react";
import type { Translated } from "@mango.dev/core";
type Post = { title: string; body: string; slug: string };
type TranslatedPost = Translated<Post, "slug", "en" | "es" | "fr">;
// → { title: Record<"en"|"es"|"fr", string>; body: Record<...>; slug: string }
export function PostCard({ post }: { post: TranslatedPost }) {
const { t } = useMango();
return (
<div>
<h1>{t(post.title)}</h1>
<p>{t(post.body)}</p>
<p>{t(post.slug)}</p>
</div>
);
}import { useMango } from "@mango.dev/react";
export function LanguageSwitcher() {
const { lang, setLang, langs } = useMango();
return (
<div>
{langs.map((l) => (
<button key={l} onClick={() => setLang(l)} disabled={l === lang}>
{l}
</button>
))}
</div>
);
}t() resolves any field — translated or plain — to a displayable value for the active language.
// Translated field (from @mango.dev/core output)
t(post.title) // { en: "Hello", es: "Hola", fr: "Bonjour" } → "Hello" (if lang is "en")
// Primitive field — returned as-is
t(post.id) // 42 → 42
t(post.slug) // "my-post" → "my-post"If the active language has no translation, t() falls back to the first language in the langs list.
| Prop | Type | Required | Description |
|---|---|---|---|
langs |
string[] |
✅ | All supported languages — must match @mango.dev/core config |
defaultLang |
string |
✅ | Active language on first render |
children |
React.ReactNode |
✅ | Child components |
| Property | Type | Description |
|---|---|---|
lang |
string |
Currently active language |
setLang |
(lang: string) => void |
Switch the active language |
t |
(field) => string | number | boolean |
Resolve a multilingual field to the active language |
langs |
string[] |
All available languages |
useMango()must be called inside a<MangoProvider>— it throws a descriptive error otherwise.