React
Translate locale files before the bundle is built, then read them with react-i18next exactly as you would any other locale file.
The shape that works
A browser must never hold an LLM key, so translation happens at build time and React only ever consumes finished JSON. There is no runtime dependency on Shipi18n at all.
1. Add the translate step
npm install -D @shipi18n/cli @anthropic-ai/sdk
{
"scripts": {
"i18n": "shipi18n translate src/locales/en.json -t es,fr,de --incremental",
"build": "npm run i18n && vite build"
}
}2. Load the generated files
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import en from './locales/en.json'
import es from './locales/es.json'
import fr from './locales/fr.json'
i18n.use(initReactI18next).init({
resources: {
en: { translation: en },
es: { translation: es },
fr: { translation: fr },
},
lng: 'en',
fallbackLng: 'en',
interpolation: { escapeValue: false },
})3. Use it
import { useTranslation } from 'react-i18next'
function Welcome({ name }) {
const { t } = useTranslation()
return <p>{t('greeting', { name })}</p>
}{{name}} survives translation, so the same interpolation works in every language.
Trans components
Inline markup is preserved too, so a string like "I agree to the <b>Terms</b>" keeps its tags and continues to work with <Trans>.
Tips
- Commit the generated locale files — deploys should never depend on a model being reachable.
- Keep
--incrementalon so untouched strings stay byte-identical between builds. - If a key renders as its own name, the translate step has not run since that key was added.