Skip to Content
Conventionsi18n Rules

i18n Rules

Every user-facing string in RNCopilot goes through the internationalization system. The project ships with English and Arabic (with full RTL support). This page covers the rules for translation keys, locale files, and RTL handling.

The Core Rule

No hardcoded strings in JSX or component logic. This is a hard rule with no exceptions.

// CORRECT const { t } = useTranslation(); <Text>{t('home.welcome')}</Text> // WRONG <Text>Welcome to the app!</Text>

Translation Hook

Use the useTranslation() hook from react-i18next in every component that renders text:

import { useTranslation } from 'react-i18next'; export function MyComponent() { const { t } = useTranslation(); return ( <View> <Text>{t('myFeature.title')}</Text> <Button title={t('actions.submit')} onPress={handleSubmit} /> </View> ); }

Locale Files

Both locale files must be updated together. When you add a key to English, add the corresponding key to Arabic in the same commit.

FileLanguageDirection
src/i18n/locales/en.jsonEnglish (primary)LTR
src/i18n/locales/ar.jsonArabicRTL

Key Naming

Keys use dot notation and semantic naming. Group keys by feature or purpose:

{ "home": { "welcome": "Welcome", "subtitle": "Get started below" }, "auth": { "login": "Sign In", "logout": "Sign Out", "email": "Email address", "password": "Password" }, "actions": { "submit": "Submit", "cancel": "Cancel", "save": "Save", "delete": "Delete" }, "validation": { "required": "This field is required", "emailInvalid": "Enter a valid email address", "passwordMin": "Password must be at least 8 characters" }, "errors": { "generic": "Something went wrong. Please try again.", "network": "Network error. Check your connection." } }

Zod Validation Messages

Zod schema error messages are i18n keys, not raw text. The form system resolves them through the translation function:

import { z } from 'zod/v4'; export const loginSchema = z.object({ email: z.email('validation.emailInvalid'), password: z.string().min(8, 'validation.passwordMin'), });

Validation messages in Zod schemas are translation keys (e.g., 'validation.required'), not the final user-visible strings.

RTL Support

RTL layout mirroring is handled globally at the app level in app/_layout.tsx. You do not need to manually flip layouts in individual components.

  • Use flexDirection values normally — the RTL system mirrors them automatically.
  • Do not conditionally swap paddingLeft/paddingRight based on language.
  • Do not use I18nManager.forceRTL() in component code — it is managed in the root layout.

Adding a New Language

To add a new locale:

  1. Create a new JSON file in src/i18n/locales/ (e.g., fr.json).
  2. Copy the structure from en.json and translate all values.
  3. Register the new locale in the i18n configuration at src/i18n/.
  4. If the language is RTL, add it to the RTL language list in the configuration.
Last updated on