import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/vi/functional-basic/Classes/GeoIntl - Quốc tế hóa (Intl)'/>

# Lớp GeoIntl

Lớp `GeoIntl` là một lớp bao đóng (wrapper) cao cấp, được tối ưu hóa dựa trên API `Intl` gốc của trình duyệt, được thiết kế đặc biệt để tích hợp mượt mà với các tính năng định vị địa lý của `Geo`. Nó cung cấp một giao diện thống nhất, nhận biết vùng locale để định dạng số, tiền tệ, đơn vị, ngày tháng, thời gian và tên địa lý, đồng thời tự động xử lý việc nhận diện locale và quản lý instance.

Lớp này triển khai mẫu **Per-locale Singleton (Singleton theo vùng locale)**, đảm bảo rằng chỉ có một instance được tạo và lưu vào bộ nhớ đệm cho mỗi mã locale duy nhất, giúp giảm đáng kể chi phí khởi tạo lặp lại các đối tượng `Intl`.

## Các tính năng chính

- **Bộ nhớ đệm Instance** — Tự động quản lý và tái sử dụng các instance dựa trên chuỗi locale chuẩn.
- **API định dạng thống nhất** — Đơn giản hóa các cấu hình `Intl` phức tạp thành các phương thức cấp cao, dễ sử dụng.
- **Định vị thích ứng** — Tự động lấy các giá trị mặc định từ trạng thái `Geo` toàn cầu nếu không có locale rõ ràng nào được cung cấp.
- **Nhận thức văn hóa** — Xử lý chính xác các quy ước đặt tên đa dạng, ngày bắt đầu của tuần trong lịch và các quy tắc số nhiều trên các nền văn hóa khác nhau.

## Khởi tạo

### `getInstance`

Truy xuất một instance từ bộ nhớ đệm hoặc tạo một instance mới cho mã locale được chỉ định.

**Tham số:**
- `code?: string` — Chuỗi locale chuẩn (ví dụ: `'vi-VN'`, `'en-US'`). Mặc định là `Geo.getLocation()`.

**Trả về:** `GeoIntl` — Instance singleton cho vùng locale được yêu cầu.

```javascript
import { GeoIntl } from '@dxtmisha/functional-basic'

const intl = GeoIntl.getInstance('vi-VN')
const currentIntl = new GeoIntl() // Cũng sử dụng bộ nhớ đệm singleton nội bộ
```

## Các phương thức Địa lý & Địa phương hóa

- `getLocation(): string` — Trả về chuỗi locale chuẩn đã chuẩn hóa (ví dụ: `'vi-VN'`).
- `getFirstDay(): string` — Trả về chỉ định ngày đầu tiên trong tuần của vùng locale (ví dụ: `'Mon'`, `'Sun'`).

## Tên & Vùng

### `display`

Cung cấp các bản dịch đã được địa phương hóa cho ngôn ngữ, vùng và chữ viết bằng công cụ `Intl.DisplayNames`.

**Tham số:**
- `value?: string` — Mã định danh (ví dụ: `'en'`, `'VN'`).
- `typeOptions?` — Một chuỗi đại diện cho kiểu hiển thị (`'language'`, `'region'`, `'script'`) hoặc một đối tượng `Intl.DisplayNamesOptions` đầy đủ.

**Trả về:** `string` — Tên hiển thị đã được địa phương hóa.

```javascript
intl.display('en', 'language') // 'Tiếng Anh'
intl.display('US', 'region')   // 'Hoa Kỳ'
```

### `languageName` / `countryName`

Các phương thức rút gọn để lấy tên ngôn ngữ và quốc gia đã được địa phương hóa.

**Tham số:**
- `value?: string` — Mã ngôn ngữ hoặc quốc gia.
- `style?` — Kiểu định dạng: `'long'`, `'short'`, hoặc `'narrow'`.

**Trả về:** `string`

### `fullName`

Định dạng họ tên đầy đủ của một người theo quy ước văn hóa của vùng locale hiện tại. Thứ tự các thành phần (Họ-Tên-Đệm hoặc Tên-Đệm-Họ) được xác định bởi `nameFormat` trong dữ liệu địa lý.

**Tham số:**
- `last: string` — Họ.
- `first: string` — Tên.
- `surname?: string` — Tên đệm hoặc tên phụ (tùy chọn).
- `short?: boolean` — Nếu là `true`, viết tắt các phần sau phần đầu tiên thành chữ cái đầu (ví dụ: `Nguyễn V. A.`).

**Trả về:** `string`

## Định dạng Số

### `number`

Định dạng một số bằng cách sử dụng các khả năng của `Intl.NumberFormat`.

**Tham số:**
- `value: NumberOrString` — Giá trị số cần định dạng.
- `options?: Intl.NumberFormatOptions` — Cấu hình cho phần thập phân, nhóm số, v.v.

**Trả về:** `string`

### `currency`

Trình định dạng tiền tệ chuyên dụng với vị trí ký hiệu tự động.

**Tham số:**
- `value: NumberOrString` — Số tiền. Cũng chấp nhận các chuỗi có hậu tố tiền tệ (ví dụ: `'100 USD'`).
- `currencyOptions?: string | Intl.NumberFormatOptions` — Mã tiền tệ (`'VND'`) hoặc các tùy chọn định dạng chi tiết.
- `numberOnly?: boolean` — Nếu là `true`, chỉ trả về các chữ số đã định dạng mà không có ký hiệu tiền tệ.

**Trả về:** `string`

```javascript
intl.currency(1500, 'VND') // '1.500 ₫'
intl.currency('1500 USD')  // '$1,500.00'
```

### `unit` / `sizeFile`

Định dạng các số với đơn vị đo lường. `sizeFile` cung cấp khả năng tự động điều chỉnh tỷ lệ cho các giá trị byte (tự động chuyển sang KB, MB, GB).

**Tham số (`sizeFile`):**
- `value: NumberOrString` — Kích thước tính bằng byte.
- `unitOptions?` — Đơn vị bắt đầu (mặc định là `'byte'`).

**Trả về:** `string`

### `plural`

Áp dụng các quy tắc số nhiều nhận biết locale.

**Tham số:**
- `value: NumberOrString` — Số lượng.
- `words: string` — Các dạng từ cách nhau bằng dấu `|`: `one|two|few|many|other|zero`.
- `options?` — `Intl.PluralRulesOptions`.

**Trả về:** `string` — Số đã định dạng kèm theo dạng từ chính xác.

## Ngày & Giờ

### `date` / `time`

Công cụ định dạng ngày chính cung cấp các biểu diễn địa phương hóa dựa trên các tùy chỉnh `GeoDate` định sẵn.

**Tham số:**
- `value: NumberOrStringOrDate` — Đầu vào ngày.
- `type?: GeoDate` — Mã định danh định sẵn: `'date'`, `'time'`, `'datetime'`, `'full'`, v.v.
- `styleOptions?` — Tùy chọn `Intl.DateTimeFormatOptions` tùy chỉnh hoặc chuỗi kiểu tháng.
- `hour24?: boolean` — Ép buộc biểu diễn thời gian 24 giờ.

**Trả về:** `string`

### `months` / `weekdays`

Trả về các mảng nhãn đã được địa phương hóa cho tháng hoặc các ngày trong tuần, lý tưởng để đưa vào các thành phần lựa chọn trên UI.

**Trả về:** `ItemValue<number>[]` — Mảng các đối tượng có trường `label` và `value`.

## Thời gian Tương đối

### `relative`

Tính toán và định dạng sự khác biệt thời gian tương đối so với một điểm tham chiếu (hiện tại), tự động chọn đơn vị thời gian phù hợp nhất.

**Tham số:**
- `value: NumberOrStringOrDate` — Ngày trong quá khứ hoặc tương lai.
- `styleOptions?` — Kiểu định dạng (ví dụ: `'long'`, `'short'`).
- `todayValue?: Date` — Điểm tham chiếu rõ ràng (mặc định là `new Date()`).

**Trả về:** `string` (ví dụ: `'2 giờ trước'`, `'sau 3 ngày'`)

### `relativeLimit`

Trình định dạng có điều kiện kết nối giữa thời gian tương đối và tuyệt đối. Nếu ngày nằm trong một `limit` ngày nhất định, nó sẽ trả về thời gian tương đối; nếu không, nó sẽ chuyển sang định dạng ngày tuyệt đối tiêu chuẩn.

**Trả về:** `string`

## Sắp xếp

### `sort`

Sắp xếp một mảng các phần tử bằng cách sử dụng so sánh nhận biết locale thông qua `Intl.Collator`.

**Tham số:**
- `data: T[]` — Mảng mục tiêu.
- `compareFn?` — Một hàm chuyển đổi tùy chọn để trích xuất các khóa sắp xếp từ các đối tượng phức tạp.

**Trả về:** `T[]` — Mảng đã sắp xếp.

```javascript
intl.sort(['chuối', 'táo', 'cam'])
// ['cam', 'chuối', 'táo']
```
