> ## 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)

> How to add multi-language support to your Shipnative app

# Internationalization (i18n)

Shipnative comes with a robust internationalization system built on [i18next](https://www.i18next.com/) and [react-i18next](https://react.i18next.com/). 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:

```tsx theme={null}
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:

```tsx theme={null}
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:

```typescript theme={null}
// 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:

```typescript theme={null}
// 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:

```typescript theme={null}
// 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

```tsx theme={null}
// 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:

```typescript theme={null}
// 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

```typescript theme={null}
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:

```tsx theme={null}
import { LanguageSelector } from "@/components"

<LanguageSelector
  visible={isVisible}
  onClose={() => setIsVisible(false)}
/>
```

### Get Current Language

```typescript theme={null}
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:

```typescript theme={null}
// 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:

```tsx theme={null}
// ✅ Valid - TypeScript knows this key exists
<Text tx="homeScreen:goodMorning" />

// ❌ Invalid - TypeScript error: key doesn't exist
<Text tx="homeScreen:invalidKey" />
```

## Best Practices

### DO

```tsx theme={null}
// ✅ 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

```tsx theme={null}
// ❌ 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

1. **Create the language file:**

```typescript theme={null}
// 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
```

2. **Register in i18n config:**

```typescript theme={null}
// app/i18n/index.ts
import de from "./de"

const resources = {
  en: { translation: en },
  es: { translation: es },
  de: { translation: de },  // Add new language
  // ...
}
```

3. **Add to language selector:**

```typescript theme={null}
// 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:

1. **Change language in Profile settings**
2. **Use the language selector component**
3. **Check for missing keys** (they'll display as the key path)

```bash theme={null}
# 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

## Related Resources

* [i18next Documentation](https://www.i18next.com/)
* [react-i18next Documentation](https://react.i18next.com/)
* [Styling Guide](/development/styling) - For RTL-aware styles
