# react-native-i18n-auto

A powerful internationalization (i18n) tool for React Native with full TypeScript support and automatic translation capabilities.

[![npm version](https://badge.fury.io/js/react-native-i18n-auto.svg)](https://badge.fury.io/js/react-native-i18n-auto)
[![TypeScript](https://badges.frapsoft.com/typescript/code/typescript.svg?v=101)](https://github.com/ellerbrock/typescript-badges/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## ✨ Features

- 🚀 **Full TypeScript Support** - Complete type safety with proper type definitions and interfaces
- 📦 **Automatic Key Extraction** - Seamless extraction through custom Babel plugin
- 🌐 **Multiple Language Support** - Support for 16 major languages out of the box
- 📱 **React Native Optimized** - Built specifically for React Native applications
- ⚡️ **High Performance** - Efficient caching system and memory optimization
- 🔄 **Event System** - Language change event listeners for real-time updates
- 🛠 **Easy Configuration** - Simple setup and intuitive API
- 🎯 **Proxy Support** - Convenient dot notation access for translations
- 💾 **Smart Caching** - Automatic cache management with configurable duration

## 📥 Installation

```bash
# Using npm
npm install --save-dev react-native-i18n-auto
npm install @react-native-async-storage/async-storage

# Using yarn
yarn add -D react-native-i18n-auto
yarn add @react-native-async-storage/async-storage
```

## 🛠 Setup

### 1. Configure TypeScript

Add the following to your `tsconfig.json`:

```json
{
    "compilerOptions": {
        "resolveJsonModule": true
    }
}
```

Create an `i18n-auto.config.json` file in your project root:

```json
{
    "defaultLanguage": "en",
    "supportedLanguages": ["en", "ko", "ja"],
    "localeDir": "locales",
    "sourceDir": ["app", "src"],
    "ignore": [
        "node_modules/**",
        "dist/**",
        "build/**",
        ".git/**",
        "tests/**",
        "**/*.test.*",
        "**/*.spec.*"
    ]
}
```

## 🚀 Quick Start Guide

### 1. Initialize Translation System

Run the following command in your project root:

```bash
npx react-native-i18n-auto run
```

### 2. Automatic Code Generation

The system will automatically transform your code and generate necessary translation files.

#### Before:

```typescript
import { Text } from 'react-native';

export default function App() {
  return <Text>Hello</Text>;
}
```

#### After:

```typescript
import { i18n } from 'react-native-i18n-auto'; //auto generate i18n instance
import { Text } from 'react-native';

export default function App() {
  return <Text>{i18n.t('HELLO')}</Text>;
}
```

#### Generated Translation File

A translation file (`en.json`) will be automatically created:

```json
{
    "HELLO": "Hello"
}
```

> 💡 **Tip**: You can use AI tools like ChatGPT to help translate these keys into different languages.

### 3. Configure Languages

Set up your languages in your app's entry point (`_layout.tsx` or `App.tsx`):

```typescript
import { i18n } from 'react-native-i18n-auto';
import en from './locales/en.json';
import ko from './locales/ko.json';
import ja from './locales/ja.json';
// Import other language files as needed

i18n.setLocales({
    en,
    ko,
    ja,
    // Add other languages as needed
});
```

### 4. Using Translations

There are multiple ways to use translations in your code:

```typescript
// 1. Function call
i18n.t('HELLO'); // Returns: "Hello"

// 2. Proxy notation (recommended)
i18n.t.HELLO; // Returns: "Hello"

// 3. Nested keys
i18n.t('GREETINGS.HELLO'); // Returns: "Hello" from nested structure
```

### 5. Language Management

#### Setting Up Language State

To properly manage language changes across your app, you should set up a global state management solution:

```typescript
import React, { createContext, useContext, useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { i18n, LanguageCode } from 'react-native-i18n-auto';

type LanguageContextType = {
    currentLanguage: LanguageCode;
    changeLanguage: (lang: LanguageCode) => void;
};

const LanguageContext = createContext<LanguageContextType | undefined>(undefined);

const STORAGE_KEY = 'USER_LANGUAGE';

export const LanguageProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const [currentLanguage, setCurrentLanguage] = useState<LanguageCode>(i18n.getLanguage());

    useEffect(() => {
        AsyncStorage.getItem(STORAGE_KEY).then((savedLang) => {
            if (savedLang && i18n.setLanguage(savedLang as LanguageCode)) {
                setCurrentLanguage(savedLang as LanguageCode);
            }
        });
    }, []);

    const changeLanguage = (lang: LanguageCode) => {
        if (i18n.setLanguage(lang)) {
            setCurrentLanguage(lang);
            AsyncStorage.setItem(STORAGE_KEY, lang);
        }
    };

    return <LanguageContext.Provider value={{ currentLanguage, changeLanguage }}>{children}</LanguageContext.Provider>;
};

export const useLanguage = () => {
    const context = useContext(LanguageContext);
    if (!context) {
        throw new Error('useLanguage must be used within a LanguageProvider');
    }
    return context;
};
```

Wrap your app with the `LanguageProvider`:

```typescript
// App.tsx or equivalent
import { LanguageProvider } from './languageContext';

export default function App() {
    return (
        <LanguageProvider>
            <YourAppContent />
        </LanguageProvider>
    );
}
```

#### Using the Language Hook

Now you can change languages anywhere in your app using the `useLanguage` hook:

```typescript
import { useLanguage } from './languageContext';

function LanguageSelector() {
    const { currentLanguage, changeLanguage } = useLanguage();

    return (
        <View>
            <Button
                title="English"
                onPress={() => changeLanguage('en')}
                disabled={currentLanguage === 'en'}
            />
            <Button
                title="한국어"
                onPress={() => changeLanguage('ko')}
                disabled={currentLanguage === 'ko'}
            />
            <Button
                title="日本語"
                onPress={() => changeLanguage('ja')}
                disabled={currentLanguage === 'ja'}
            />
        </View>
    );
}
```

## 🤝 Contributing

Contributions are welcome! Feel free to submit issues and pull requests.

## 📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

## 📚 Additional Features

### Event System

You can subscribe to language changes:

```typescript
// Subscribe to language changes
const unsubscribe = i18n.onLanguageChange(() => {
    console.log('Current language:', i18n.getLanguage());
});

// Cleanup when component unmounts
useEffect(() => {
    return () => unsubscribe();
}, []);
```

### Performance Optimization

The library includes built-in performance optimization features:

```typescript
// Clear translation cache
i18n.clearCache();

// Optimize memory usage
i18n.optimize();
```

### Language Utilities

Additional utility functions for language management:

```typescript
// Get all supported languages
const supported = i18n.getSupportedLanguages();

// Get languages that have translations loaded
const available = i18n.getAvailableLanguages();
```

### Type Safety Features

The library provides strong TypeScript support with proper type definitions:

```typescript
import { i18n, LanguageCode, I18nType } from 'react-native-i18n-auto';

// Type-safe language codes
const setKorean = () => i18n.setLanguage('ko' as LanguageCode);

// Type-safe translation keys (when using with TypeScript)
type TranslationKeys = keyof typeof import('./locales/en.json');
const translate = (key: TranslationKeys) => i18n.t(key);
```

> 💡 **Tip**: You can also integrate this with your backend to sync user language preferences across devices.
