English-only localization system for React Native apps with i18n support. Built with Domain-Driven Design principles and TypeScript.
- English-Only Support: Optimized for English (en-US) language only
- Automatic Device Locale Detection: Maps all device locales to English (en-US)
- Persistent Language Preferences: Saves user's language choice using AsyncStorage
- Simple Translation Management: Easy-to-use translation files for English content
- Type-Safe: Full TypeScript support with type definitions
- Zero Configuration: Works out of the box with sensible defaults
- Production Ready: Battle-tested in production apps
- Lightweight: Minimal dependencies with tree-shakeable exports
- Domain-Driven Design: Follows DDD principles with clear separation of concerns
This package follows Domain-Driven Design principles:
๐ src/
โโโ domain/ # Business entities and interfaces
โโโ infrastructure/ # Storage, config, and external services
โโโ presentation/ # Hooks and components for UI
Package Translations (This Package):
- Core UI translations (buttons, alerts, navigation)
- Device-specific translations (camera, location, etc.)
- Generic business logic translations
Project Translations (Your App):
- App-specific translations
- Business domain translations
- Feature-specific content
Why This Separation?
- Package stays lightweight and reusable
- Projects maintain full control over their translations
- Easy updates without affecting project-specific content
- Clear separation of concerns
npm install @umituz/react-native-localization
# or
yarn add @umituz/react-native-localizationMake sure you have the following peer dependencies installed:
npm install zustand i18next react-i18next expo-localization @umituz/react-native-storageNote: @umituz/react-native-storage is required for persistent language preferences. It provides type-safe storage operations following Domain-Driven Design principles.
npm install @umituz/react-native-localizationCreate a localization domain in your project following DDD principles:
๐ src/domains/localization/
โโโ index.ts # Domain exports
โโโ infrastructure/
โ โโโ locales/
โ โ โโโ en-US/
โ โ โ โโโ index.ts # Auto-loader (uses filesystem package)
โ โ โ โโโ auth.json # Authentication translations
โ โ โ โโโ home.json # Home screen translations
โ โ โ โโโ settings.json # Settings translations
โ โ โ โโโ [feature].json # Feature-specific translations
โ โ โโโ [other-languages]/ # Future language support
โ โโโ config/
โ โโโ i18n.ts # Project i18n configuration
โโโ presentation/
โโโ hooks/
โโโ useLocalization.ts # Project-specific hooks (optional)
Example from Vivoim App:
๐ src/domains/localization/
โโโ index.ts
โโโ infrastructure/
โโโ locales/
โโโ en-US/
โโโ auth.json # Login, signup, password
โโโ chat.json # Chat messages, typing
โโโ common.json # Shared UI elements
โโโ community.json # Social features
โโโ creations.json # Content creation
โโโ editor.json # Image/video editing
โโโ home.json # Dashboard, navigation
โโโ index.ts # Auto-loader
โโโ navigation.json # App navigation
โโโ paywall.json # Subscription features
โโโ premium.json # Premium content
โโโ profile.json # User profiles
โโโ projects.json # Project management
โโโ settings.json # App settings
โโโ support.json # Help & support
โโโ templates.json # Content templates
โโโ text2image.json # AI image generation
โโโ wallet.json # Payments, credits
Why This Structure?
- Separation of Concerns: Package handles core UI, project handles business logic
- Scalability: Easy to add new features without touching core package
- Maintainability: Clear ownership of translations
- Reusability: Same package works across hundreds of apps
src/domains/localization/infrastructure/locales/en-US/index.ts:
import { loadJsonModules } from "@umituz/react-native-filesystem";
// Metro bundler require.context - auto-discover all .json files
// eslint-disable-next-line @typescript-eslint/no-require-imports
const translationContext = (require as any).context("./", false, /\.json$/);
// Load all JSON modules using filesystem package utilities
const translations = loadJsonModules(translationContext);
export default translations;src/domains/localization/infrastructure/locales/en-US/your-feature.json:
{
"title": "Your Feature Title",
"description": "Feature description",
"button": {
"save": "Save Changes",
"cancel": "Cancel"
}
}src/domains/localization/infrastructure/config/i18n.ts:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import { DEFAULT_LANGUAGE } from '@umituz/react-native-localization';
// Load project translations
const loadProjectTranslations = () => {
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
return require('../locales/en-US');
} catch {
return {};
}
};
const projectTranslations = loadProjectTranslations();
// Configure i18n with project translations
i18n
.use(initReactI18next)
.init({
resources: {
'en-US': {
translation: projectTranslations.default || projectTranslations
}
},
lng: DEFAULT_LANGUAGE,
fallbackLng: DEFAULT_LANGUAGE,
interpolation: {
escapeValue: false,
},
react: {
useSuspense: false,
},
});
export default i18n;import { LocalizationProvider } from '@umituz/react-native-localization';
import './domains/localization/infrastructure/config/i18n'; // Initialize project i18n
export default function App() {
return (
<LocalizationProvider>
<YourApp />
</LocalizationProvider>
);
}Option A: Use Package Localization (Recommended for UI components)
import { useLocalization } from '@umituz/react-native-localization';
function MyComponent() {
const { t } = useLocalization();
return (
<View>
<Text>{t('general.save')}</Text> {/* From package */}
<Text>{t('yourFeature.title')}</Text> {/* From your project */}
</View>
);
}Option B: Use Project Localization (For business logic)
import { useTranslation } from 'react-i18next';
function MyComponent() {
const { t } = useTranslation();
return (
<View>
<Text>{t('yourFeature.title')}</Text> {/* From your project */}
</View>
);
}For better integration, add your project translations to the package i18n instance:
import { addTranslationResources } from '@umituz/react-native-localization';
// In your project's i18n config
const projectTranslations = require('./locales/en-US');
addTranslationResources({
'en-US': {
translation: projectTranslations.default || projectTranslations,
},
// Add other languages as needed
});This ensures all translations work through the same i18n instance, preventing conflicts.
- Create JSON file in
src/domains/localization/infrastructure/locales/en-US/ - Add translations following flat or nested structure
- Auto-loading happens automatically via
index.ts
Flat Structure (Recommended for simple features):
// settings.json
{
"title": "Settings",
"language": "Language",
"theme": "Theme",
"notifications": "Notifications"
}Nested Structure (For complex features):
// auth.json
{
"login": {
"title": "Welcome Back",
"email": "Email Address",
"password": "Password",
"forgotPassword": "Forgot Password?",
"signIn": "Sign In"
},
"register": {
"title": "Create Account",
"confirmPassword": "Confirm Password",
"signUp": "Sign Up"
}
}// Flat structure
t('settings.title') // "Settings"
// Nested structure
t('auth.login.title') // "Welcome Back"
t('auth.register.signUp') // "Sign Up"import { useLocalization } from '@umituz/react-native-localization';
function MyComponent() {
const { t, currentLanguage, setLanguage } = useLocalization();
return (
<View>
<Text>{t('general.welcome')}</Text>
<Text>Current Language: {currentLanguage}</Text>
<Button title="Switch to Turkish" onPress={() => setLanguage('tr-TR')} />
</View>
);
}Main hook to access localization functionality.
Returns:
t: Translation functioncurrentLanguage: Current language code (e.g., 'en-US')currentLanguageObject: Full language object with metadataisRTL: Boolean indicating if current language is RTLisInitialized: Boolean indicating if localization is readysupportedLanguages: Array of all supported languagessetLanguage: Function to change languageinitialize: Function to manually initialize (auto-called by provider)
Component that initializes the localization system. Wrap your app with this component.
<LocalizationProvider>
<App />
</LocalizationProvider>Get language object by language code.
import { getLanguageByCode } from '@umituz/react-native-localization';
const language = getLanguageByCode('en-US');
// Returns: { code: 'en-US', name: 'English', nativeName: 'English', flag: '๐บ๐ธ', rtl: false }Get the default language object (English US).
import { getDefaultLanguage } from '@umituz/react-native-localization';
const defaultLang = getDefaultLanguage();Get device's locale and map it to a supported language.
import { getDeviceLocale } from '@umituz/react-native-localization';
const deviceLanguage = getDeviceLocale();The package comes with pre-configured support for 29 languages:
| Language | Code | RTL |
|---|---|---|
| English | en-US | No |
| Arabic | ar-SA | Yes |
| Bulgarian | bg-BG | No |
| Czech | cs-CZ | No |
| Danish | da-DK | No |
| German | de-DE | No |
| Spanish | es-ES | No |
| Finnish | fi-FI | No |
| French | fr-FR | No |
| Hindi | hi-IN | No |
| Hungarian | hu-HU | No |
| Indonesian | id-ID | No |
| Italian | it-IT | No |
| Japanese | ja-JP | No |
| Korean | ko-KR | No |
| Malay | ms-MY | No |
| Dutch | nl-NL | No |
| Norwegian | no-NO | No |
| Polish | pl-PL | No |
| Portuguese | pt-PT | No |
| Romanian | ro-RO | No |
| Russian | ru-RU | No |
| Swedish | sv-SE | No |
| Thai | th-TH | No |
| Filipino | tl-PH | No |
| Turkish | tr-TR | No |
| Ukrainian | uk-UA | No |
| Vietnamese | vi-VN | No |
| Chinese (Simplified) | zh-CN | No |
The package includes common translations organized by domain:
animation: Animation-related translationsaudio: Audio-related translationsdatetime: Date and time translationsemoji: Emoji-related translationserrors: Error messagesforms: Form labels and validationgeneral: General UI texticons: Icon labelslocation: Location-related translationsmedia: Media-related translationsnavigation: Navigation labelsonboarding: Onboarding flow textsettings: Settings screen texttoast: Toast notification messages
// Access nested translations
t('general.welcome')
t('errors.network.title')
t('settings.language.title')import { useLocalization, SUPPORTED_LANGUAGES } from '@umituz/react-native-localization';
import { FlatList, TouchableOpacity, Text } from 'react-native';
function LanguageSelector() {
const { currentLanguage, setLanguage } = useLocalization();
return (
<FlatList
data={SUPPORTED_LANGUAGES}
keyExtractor={(item) => item.code}
renderItem={({ item }) => (
<TouchableOpacity onPress={() => setLanguage(item.code)}>
<Text>
{item.flag} {item.nativeName}
{currentLanguage === item.code && ' โ'}
</Text>
</TouchableOpacity>
)}
/>
);
}import { useLocalization } from '@umituz/react-native-localization';
import { I18nManager } from 'react-native';
function MyComponent() {
const { isRTL } = useLocalization();
// Apply RTL layout
React.useEffect(() => {
I18nManager.forceRTL(isRTL);
}, [isRTL]);
return <View style={{ flexDirection: isRTL ? 'row-reverse' : 'row' }} />;
}<<<<<<< HEAD
=======
The package includes a script to automatically generate locale loader files (index.ts) for all language directories. This script scans all JSON translation files and creates proper TypeScript import statements.
Generate loaders for all languages:
npm run locales:generateGenerate loader for a specific language:
npm run locales:generate:lang en-US
npm run locales:generate:lang tr-TRThis will create an index.ts file in each locale directory that imports all JSON translation files. The generated files should not be edited manually.
5546c313bf9daab92c37ccf9b442a19a399a52c2
The package includes common translations. For project-specific translations:
-
Create your translation files in your project:
src/domains/localization/infrastructure/locales/ en-US/ myFeature.json auth.json tr-TR/ myFeature.json auth.json -
Load project translations in your app initialization:
import { i18n } from '@umituz/react-native-localization'; import myFeatureEnUS from './locales/en-US/myFeature.json'; import myFeatureTrTR from './locales/tr-TR/myFeature.json'; // Add project translations i18n.addResources('en-US', 'translation', myFeatureEnUS); i18n.addResources('tr-TR', 'translation', myFeatureTrTR);
-
Use in components:
const { t } = useLocalization(); console.log(t('myFeature.title')); // 'My Feature'
The package includes scripts for managing translations:
# Setup language directories (creates all language folders from en-US)
npm run i18n:setup
# Translate missing keys using Google Translate
npm run i18n:translate
# Check translation completeness
npm run i18n:check <language-code>
npm run i18n:check all # Check all languages
# Remove unused translation keys
npm run i18n:remove-unused <language-code>
npm run i18n:remove-unused --all # Remove from all languagesWorkflow:
- Add new keys to
en-US/*.jsonfiles - Run
npm run i18n:setupto create language directories - Run
npm run i18n:translateto auto-translate missing keys - Run
npm run i18n:check allto verify completeness - Review and refine translations manually if needed
The package is written in TypeScript and includes full type definitions.
import type { Language } from '@umituz/react-native-localization';
const language: Language = {
code: 'en-US',
name: 'English',
nativeName: 'English',
flag: '๐บ๐ธ',
rtl: false
};Built with Domain-Driven Design (DDD) principles:
- Domain Layer: Core business logic and interfaces
- Infrastructure Layer: Implementation details (storage, i18n config, locales)
- Presentation Layer: React components and hooks
Contributions are welcome! Please read the contributing guidelines before submitting PRs.
MIT
รmit UZ umit@umituz.com