Documentation
Manual i18n Setup
Set up i18n by hand — install a library, create your source locale file, add translator descriptions, and replace hardcoded strings.
This guide is for manual setup only. If you have access to an AI coding agent (Cursor, Copilot, etc.), the Quick Start is much faster and handles the entire i18n integration automatically.
This guide walks you through setting up internationalization (i18n) manually, step by step. By the end, you will have a working source locale file that Localingos can translate with
localingos sync.Step 1: Install an i18n library
Choose the library that matches your framework:
React
npm install react-i18next i18nextNext.js (App Router)
npm install next-intlVue
npm install vue-i18nOther frameworks: use any i18n library that loads translations from JSON files.
Step 2: Create your source locale file
Create a JSON file for your source language. This is the file Localingos reads when you run
localingos sync. Use the path you configured during localingos init (default: src/i18n/en-US.json).Nested format (recommended for most projects):
// src/i18n/en-US.json
{
"common": {
"welcome": "Welcome back",
"logout": "Log out"
},
"cart": {
"title": "Your Cart",
"items": "You have {{count}} items",
"empty": "Your cart is empty",
"checkout": "Proceed to checkout"
},
"errors": {
"required": "This field is required",
"invalid_email": "Please enter a valid email"
}
}Flat format (if your project uses dot-separated keys):
// src/i18n/en-US.json
{
"common.welcome": "Welcome back",
"common.logout": "Log out",
"cart.title": "Your Cart",
"cart.items": "You have {{count}} items",
"cart.empty": "Your cart is empty",
"cart.checkout": "Proceed to checkout"
}Step 2b: Add a descriptions file (recommended)
Create a descriptions sidecar file at the same path as your source file, with a
.descriptions.json suffix (e.g. src/i18n/en-US.descriptions.json). This provides context to the AI translator and significantly improves translation quality.Use the same key structure as your source file, but with descriptions as values:
// src/i18n/en-US.descriptions.json
{
"common": {
"welcome": "Greeting shown on the dashboard after login",
"logout": "Button label in the user menu"
},
"cart": {
"title": "Page heading for the shopping cart",
"items": "Summary text below the title. {{count}} is the number of items in the cart",
"empty": "Message shown when the cart has no items",
"checkout": "Primary CTA button at the bottom of the cart"
}
}The descriptions file is only used during
localingos sync to give the AI translator context — it is NOT loaded by your app at runtime. Include where the text appears, what surrounds it, and what any placeholders represent.Step 3: Initialize the i18n library
Create a setup file that loads your locale JSON and configures the library.
React (react-i18next)
// src/i18n/index.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enUS from './en-US.json';
i18n.use(initReactI18next).init({
resources: { 'en-US': { translation: enUS } },
lng: 'en-US',
fallbackLng: 'en-US',
interpolation: { escapeValue: false },
});
export default i18n;Then import it in your app entry point:
// src/index.tsx or src/main.tsx
import './i18n';Step 4: Replace hardcoded strings
Go through your components and replace hardcoded text with translation function calls. This is the most time-consuming part, but it only needs to be done once.
Before:
function CartPage() {
return (
<div>
<h1>Your Cart</h1>
<p>You have {items.length} items</p>
<button>Proceed to checkout</button>
</div>
);
}After:
import { useTranslation } from 'react-i18next';
function CartPage() {
const { t } = useTranslation();
return (
<div>
<h1>{t('cart.title')}</h1>
<p>{t('cart.items', { count: items.length })}</p>
<button>{t('cart.checkout')}</button>
</div>
);
}Tip: work through one page at a time. Add each string to your
en-US.json as you go. Variables like {{count}} are preserved by Localingos during translation.Step 5: Load translated locale files
After running
localingos sync, translated files appear in your output directory (e.g. src/i18n/de-DE.json, src/i18n/fr-FR.json). Load them into your i18n config:// src/i18n/index.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enUS from './en-US.json';
import deDE from './de-DE.json';
import frFR from './fr-FR.json';
i18n.use(initReactI18next).init({
resources: {
'en-US': { translation: enUS },
'de-DE': { translation: deDE },
'fr-FR': { translation: frFR },
},
lng: 'en-US',
fallbackLng: 'en-US',
interpolation: { escapeValue: false },
});
export default i18n;For production apps, consider lazy-loading locales instead of bundling them all. See your i18n library's documentation for dynamic import patterns.
Step 6: Sync translations
Once your source locale file has all your strings, push them to Localingos and pull back translations:
localingos syncThis pushes your source strings, translates them into all target locales configured in your project, and writes the translated files to your output directory. Run it again whenever you add or change strings.