@mango.dev/react
v0.1.1
Published
React bindings for `@mango.dev/core` — provides a context provider and hook to read and switch languages in your React app.
Readme
@mango.dev/react
React bindings for @mango.dev/core — provides a context provider and hook to read and switch languages in your React app.
Features
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
Installation
# 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
Usage
1. Wrap your app with MangoProvider
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>
);
}2. Render translated fields with useMango() — t()
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>
);
}3. Switch languages with useMango() — setLang
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>
);
}4. How t() works
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.
Configuration
MangoProviderProps
| 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 |
useMango return value
| 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.
