Documentation Index
Fetch the complete documentation index at: https://docs.shipnative.app/llms.txt
Use this file to discover all available pages before exploring further.
Internationalization (i18n)
Shipnative comes with a robust internationalization system built on i18next and react-i18next. The app supports 7 languages out of the box and makes it easy to add more.
Supported Languages
| Language | Code | RTL Support |
|---|
| English | en | No |
| Arabic | ar | Yes |
| Spanish | es | No |
| French | fr | No |
| Hindi | hi | No |
| Japanese | ja | No |
| Korean | ko | No |
Quick Start
Using Translations in Components
There are two main ways to use translations:
1. Using the tx Prop (Recommended for Static Text)
The Text component (and many other components) support a tx prop for translation keys:
import { Text } from "@/components"
// Simple translation
<Text tx="homeScreen:goodMorning" />
// With interpolation
<Text
tx="profileScreen:version"
txOptions={{ version: "1.0.0", build: "12" }}
/>
2. Using the useTranslation Hook (For Dynamic Text)
When you need more control or want to use translations in logic:
import { useTranslation } from "react-i18next"
function MyComponent() {
const { t } = useTranslation()
return (
<View>
<Text>{t("homeScreen:goodMorning")}</Text>
<Text>{t("profileScreen:version", { version: "1.0.0", build: "12" })}</Text>
</View>
)
}
Translation File Structure
Translation files are located in app/i18n/:
app/i18n/
├── index.ts # i18n configuration
├── en.ts # English (source of truth)
├── ar.ts # Arabic
├── es.ts # Spanish
├── fr.ts # French
├── hi.ts # Hindi
├── ja.ts # Japanese
├── ko.ts # Korean
├── translate.ts # Helper function
└── languageSwitcher.ts # Language switching utilities
Translation Key Structure
Translation keys are organized by screen/feature:
// en.ts
const en = {
common: {
ok: "OK!",
cancel: "Cancel",
back: "Back",
},
homeScreen: {
goodMorning: "Good morning,",
dailyChallenge: "Daily Challenge",
// ...
},
profileScreen: {
title: "Profile",
settingsTitle: "Settings",
version: "Version {{version}} (Build {{build}})",
// ...
},
// ... more screens
}
Adding New Translations
Step 1: Add Keys to English File
English (en.ts) is the source of truth. Always add new keys here first:
// app/i18n/en.ts
const en = {
// ... existing keys
myNewScreen: {
title: "My New Screen",
description: "This is a new feature",
button: "Get Started",
greeting: "Hello, {{name}}!", // With interpolation
},
}
Step 2: Update Other Language Files
Add the same keys to all other language files with translated values:
// app/i18n/es.ts
const es: Translations = {
// ... existing keys
myNewScreen: {
title: "Mi Nueva Pantalla",
description: "Esta es una nueva característica",
button: "Comenzar",
greeting: "¡Hola, {{name}}!",
},
}
Step 3: Use in Components
// Using tx prop
<Text tx="myNewScreen:title" />
<Button tx="myNewScreen:button" onPress={handlePress} />
// Using useTranslation hook
const { t } = useTranslation()
<Text>{t("myNewScreen:greeting", { name: userName })}</Text>
Component Support for tx Props
Many components support translation props directly:
| Component | Translation Props |
|---|
Text | tx, txOptions |
Button | tx, txOptions |
Badge | tx |
TextField | labelTx, placeholderTx, helperTx |
Card | headingTx, contentTx, footerTx |
Modal | titleTx, descriptionTx |
EmptyState | headingTx, contentTx, buttonTx |
Header | leftTx, rightTx |
AuthScreenLayout | titleTx, subtitleTx |
OnboardingScreenLayout | titleTx, subtitleTx |
Interpolation (Dynamic Values)
Use {{variable}} syntax for dynamic values:
// In en.ts
profileScreen: {
version: "Version {{version}} (Build {{build}})",
greeting: "Hello, {{name}}!",
itemCount: "You have {{count}} items",
}
// In component
<Text
tx="profileScreen:version"
txOptions={{ version: "1.0.0", build: "12" }}
/>
// Or with useTranslation
const { t } = useTranslation()
t("profileScreen:greeting", { name: "John" })
Language Switching
Programmatic Language Change
import { changeLanguage } from "@/i18n/languageSwitcher"
// Change language and persist the preference
await changeLanguage("es", true)
// Change without persisting
await changeLanguage("fr", false)
Built-in Language Selector
Shipnative includes a LanguageSelector component:
import { LanguageSelector } from "@/components"
<LanguageSelector
visible={isVisible}
onClose={() => setIsVisible(false)}
/>
Get Current Language
import { getCurrentLanguage, getPersistedLanguage } from "@/i18n/languageSwitcher"
const currentLang = getCurrentLanguage() // Currently active
const savedLang = getPersistedLanguage() // Saved preference
RTL (Right-to-Left) Support
Arabic is automatically detected and enables RTL layout:
// The system automatically:
// 1. Detects Arabic locale
// 2. Calls I18nManager.allowRTL(true)
// 3. Enables RTL layout for the entire app
Type Safety
The i18n system provides full TypeScript support. Invalid keys will cause TypeScript errors:
// ✅ Valid - TypeScript knows this key exists
<Text tx="homeScreen:goodMorning" />
// ❌ Invalid - TypeScript error: key doesn't exist
<Text tx="homeScreen:invalidKey" />
Best Practices
// ✅ Use tx prop for static text
<Text tx="homeScreen:title" />
// ✅ Use interpolation for dynamic values
<Text tx="profile:greeting" txOptions={{ name: userName }} />
// ✅ Organize keys by screen/feature
loginScreen: { title: "...", subtitle: "..." }
// ✅ Keep English file as source of truth
// Always add new keys to en.ts first
DON’T
// ❌ Don't hardcode strings
<Text>Welcome to the app</Text>
// ❌ Don't concatenate translations
<Text>{t("hello") + " " + name}</Text> // Use interpolation instead
// ❌ Don't use nested translation keys more than 2 levels deep
// Bad: screen.section.subsection.item.label
// Good: screenSection:itemLabel
Adding a New Language
- Create the language file:
// app/i18n/de.ts
import { Translations } from "./en"
const de: Translations = {
common: {
ok: "OK",
cancel: "Abbrechen",
back: "Zurück",
},
// ... translate all keys from en.ts
}
export default de
- Register in i18n config:
// app/i18n/index.ts
import de from "./de"
const resources = {
en: { translation: en },
es: { translation: es },
de: { translation: de }, // Add new language
// ...
}
- Add to language selector:
// app/i18n/languageSwitcher.ts
export const SUPPORTED_LANGUAGES = [
{ code: "en", name: "English", nativeName: "English", flag: "🇺🇸" },
{ code: "de", name: "German", nativeName: "Deutsch", flag: "🇩🇪" },
// ...
]
Testing Translations
To verify translations are working:
- Change language in Profile settings
- Use the language selector component
- Check for missing keys (they’ll display as the key path)
# Run the app and look for untranslated keys like:
# "myScreen:missingKey" instead of actual text
Troubleshooting
Translations Not Updating
- Ensure you’re importing from the correct i18n file
- Check that the key exists in the language file
- Verify the component supports the
tx prop
TypeScript Errors for Valid Keys
- Run
yarn typecheck to regenerate types
- Ensure
en.ts exports the Translations type
RTL Layout Issues
- Check that
I18nManager.allowRTL(true) is called
- Some custom styles may need
flexDirection: 'row-reverse' for RTL