# AkiLocale

### <mark style="color:red;">Installation</mark>

```bash
pnpm add @akinon/akilocale
```

### <mark style="color:red;">Basic Usage</mark>

```tsx
import { Akilocale } from '@akinon/akilocale';

// Create a locale instance with translations
const locale = Akilocale.createInstance({
  fallbackLng: 'en',
  translations: {
    en: {
      greeting: 'Hello',
      welcome: 'Welcome, {{name}}!'
    },
    tr: {
      greeting: 'Merhaba',
      welcome: 'Hoş geldin, {{name}}!'
    }
  }
});

// Use the translation function
locale.t('greeting'); // "Hello" or "Merhaba" based on current language
locale.t('welcome', { name: 'John' }); // "Welcome, John!"

// Get current language
console.log(locale.lng); // "en"
```

### <mark style="color:red;">API Reference</mark>

#### Akilocale.createInstance

Creates a new locale instance with the provided translations.

```tsx
const locale = Akilocale.createInstance({
  debug: false,
  fallbackLng: 'en',
  initialLanguage: 'tr',
  translations: {
    en: enTranslations,
    tr: trTranslations
  }
});
```

**Options**

| Option            | Type                           | Default     | Description                                   |
| ----------------- | ------------------------------ | ----------- | --------------------------------------------- |
| `translations`    | `Record<string, Translations>` | -           | Translation objects keyed by language code    |
| `fallbackLng`     | `string`                       | `'en'`      | Fallback language when translation is missing |
| `initialLanguage` | `string`                       | `undefined` | Initial language (overrides localStorage)     |
| `debug`           | `boolean`                      | `false`     | Enable debug logging                          |

**Returns: AkilocaleInstance**

| Property | Type                                          | Description           |
| -------- | --------------------------------------------- | --------------------- |
| `t`      | `(key: string, options?: TOptions) => string` | Translation function  |
| `lng`    | `string`                                      | Current language code |

***

#### Akilocale.setLanguage

Persists the selected language to localStorage. Requires page reload to take effect.

```tsx
Akilocale.setLanguage('tr');
```

**Parameters**

| Parameter | Type     | Description          |
| --------- | -------- | -------------------- |
| `lng`     | `string` | Language code to set |

***

#### Translation Function (t)

The `t` function translates keys with optional interpolation.

```tsx
const { t } = Akilocale.createInstance({ ... });

// Simple translation
t('greeting'); // "Hello"

// With interpolation
t('welcome', { name: 'John' }); // "Welcome, John!"

// Nested keys
t('nested.part1'); // Access nested translations

// Dot notation in keys
t('hello.world'); // Keys can contain dots
```

***

### <mark style="color:red;">Translation Structure</mark>

Translations can be flat or nested objects:

```tsx
const translations = {
  en: {
    // Flat keys
    greeting: 'Hello',
    farewell: 'Goodbye',
    
    // Interpolation with {{variable}}
    welcome: 'Welcome, {{name}}!',
    items: 'You have {{count}} items',
    
    // Dot notation keys (not nested)
    'button.submit': 'Submit',
    'button.cancel': 'Cancel',
    
    // Nested structure
    errors: {
      required: 'This field is required',
      minLength: 'Minimum {{min}} characters'
    }
  }
};
```

### <mark style="color:red;">React Integration</mark>

For React applications, use the `/react` export which provides react-i18next integration:

```tsx
import { i18n, Trans, useTranslation } from '@akinon/akilocale/react';

const MyComponent = () => {
  const { t } = useTranslation();
  
  return (
    <div>
      <h1>{t('title')}</h1>
      <Trans i18nKey="description">
        Welcome to <strong>our app</strong>
      </Trans>
    </div>
  );
};
```

***

### <mark style="color:red;">Language Persistence</mark>

Akilocale automatically persists language selection to localStorage:

```tsx
// Storage key used: 'locale'
import { AKILOCALE_STORAGE_KEY } from '@akinon/akilocale';

// Set language (persists to localStorage)
Akilocale.setLanguage('tr');

// On next createInstance call, language is read from localStorage
const locale = Akilocale.createInstance({
  fallbackLng: 'en',
  translations
});

console.log(locale.lng); // 'tr' (from localStorage)
```

#### Language Priority

1. `initialLanguage` option (if provided)
2. localStorage value (if exists)
3. `fallbackLng` option

***

### <mark style="color:red;">Common Use Cases</mark>

#### App Initialization

```tsx
import { Akilocale } from '@akinon/akilocale';

import en from './locales/en.json';
import tr from './locales/tr.json';

// Create global locale instance
export const locale = Akilocale.createInstance({
  fallbackLng: 'en',
  translations: { en, tr }
});

// Export for use throughout the app
export const { t } = locale;
```

#### Language Switcher

```tsx
import { Akilocale } from '@akinon/akilocale';

const LanguageSwitcher = () => {
  const handleLanguageChange = (lng: string) => {
    Akilocale.setLanguage(lng);
    window.location.reload(); // Reload to apply new language
  };

  return (
    <div>
      <button onClick={() => handleLanguageChange('en')}>English</button>
      <button onClick={() => handleLanguageChange('tr')}>Türkçe</button>
    </div>
  );
};
```

#### Integration with Akidate

Keep Akidate in sync with Akilocale for consistent date formatting:

```tsx
import { Akilocale } from '@akinon/akilocale';
import { akidate } from '@akinon/akidate';

import en from './locales/en.json';
import tr from './locales/tr.json';

const locale = Akilocale.createInstance({
  fallbackLng: 'en',
  translations: { en, tr }
});

// Sync Akidate with current language
akidate.setLocale(locale.lng);

export const { t } = locale;
```

#### With Intl APIs

Use `locale.lng` for native JavaScript internationalization:

```tsx
import { Akilocale } from '@akinon/akilocale';

const locale = Akilocale.createInstance({ ... });

// Currency formatting
const formatPrice = (value: number) => {
  return new Intl.NumberFormat(locale.lng, {
    style: 'currency',
    currency: 'USD'
  }).format(value);
};

// Date formatting (prefer Akidate for consistency)
const formatDate = (date: Date) => {
  return new Intl.DateTimeFormat(locale.lng, {
    dateStyle: 'long'
  }).format(date);
};

// Number formatting
const formatNumber = (value: number) => {
  return new Intl.NumberFormat(locale.lng).format(value);
};
```

#### Table with Translations

```tsx
import type { AkitableColumn } from '@akinon/akitable';

import { t } from './locale';

const columns: AkitableColumn<Product>[] = [
  {
    title: t('table.name'),
    dataIndex: 'name'
  },
  {
    title: t('table.status'),
    dataIndex: 'status',
    render: (status) => t(`status.${status}`)
  }
];
```

***

### <mark style="color:red;">Translation File Organization</mark>

#### JSON Files (Recommended)

```json
// locales/en.json
{
  "common": {
    "save": "Save",
    "cancel": "Cancel",
    "delete": "Delete"
  },
  "errors": {
    "required": "This field is required",
    "invalid": "Invalid value"
  }
}
```

#### TypeScript Files

```tsx
// locales/en.ts
export default {
  common: {
    save: 'Save',
    cancel: 'Cancel'
  }
} as const;
```

***

### <mark style="color:red;">Best Practices</mark>

1. **Create a single instance** - Initialize locale once at app startup and export `t`
2. **Use JSON files** - Store translations in JSON for easy editing and tooling support
3. **Consistent key naming** - Use dot notation or nested structure, but be consistent
4. **Sync with Akidate** - Call `akidate.setLocale(locale.lng)` after initialization
5. **Handle missing translations** - Missing keys return the key itself, useful for development
6. **Reload on language change** - Call `window.location.reload()` after `setLanguage` for full effect

### Related

* [Akidate](/akinon-ui/ui-kit/utilities/akidate.md) - Date formatting with locale support


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akinon.com/akinon-ui/ui-kit/utilities/akilocale.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
