@v-miniapp/locale
v1.0.2
Published
**@v-miniapp/locale** là bộ thư viện component React mạnh mẽ được thiết kế đặc biệt cho việc phát triển Router V-MiniApp.
Readme
@v-miniapp/locale
@v-miniapp/locale là bộ thư viện component React mạnh mẽ được thiết kế đặc biệt cho việc phát triển Router V-MiniApp.
Cài đặt
npm install @v-miniapp/locale
# hoặc
pnpm add @v-miniapp/locale
# hoặc
yarn add @v-miniapp/localeVí dụ bắt đầu sử dụng
import { LocalesProvider, type ILocalesConfig } from '@v-miniapp/ui-react'
const localesConfig: ILocalesConfig = {
defaultLanguage: 'vi',
resources: {
vi: {
'app.title': 'Ứng dụng của tôi',
},
en: {
'app.title': 'My Application',
},
},
}
function MyApp() {
return (
<>
<LocalesProvider config={localesConfig}>
{/* Your app content */}
</LocalesProvider>
</>
)
}Mở rộng với Custom Languages và Locales Keys
Bạn có thể thêm các ngôn ngữ tùy chỉnh ngoài vi và en, đồng thời định nghĩa custom locales keys với type safety thông qua module augmentation trong global.d.ts:
Bước 1: Tạo JSON files cho translations
locales/vi.json:
{
"app.title": "Ứng dụng của tôi",
"app.description": "Mô tả ứng dụng",
"user.greeting": "Xin chào {name}!",
"user.welcome": "Chào mừng bạn đến với {app}",
"button.submit": "Gửi",
"button.reset": "Đặt lại"
}locales/en.json:
{
"app.title": "My Application",
"app.description": "Application description",
"user.greeting": "Hello {name}!",
"user.welcome": "Welcome to {app}",
"button.submit": "Submit",
"button.reset": "Reset"
}locales/jp.json:
{
"app.title": "私のアプリケーション",
"app.description": "アプリケーションの説明",
"user.greeting": "こんにちは {name}!",
"user.welcome": "{app}へようこそ",
"button.submit": "送信",
"button.reset": "リセット"
}Bước 2: Declare module augmentation trong global.d.ts
Tạo hoặc update file global.d.ts (hoặc vite-env.d.ts) trong project của bạn:
import '@v-miniapp/ui-react'
import vi from './locales/vi.json'
declare module '@v-miniapp/ui-react' {
interface ICustomLocales {
resource: typeof vi
language: 'jp' | 'en' | 'vi'
}
}Lưu ý:
- Import từ JSON files và dùng
typeof viđể infer types tự động, đảm bảo type safety resourcelà type của locales keys (từ JSON file)languagelà union type của các language codes mà bạn muốn hỗ trợ
Bước 3: Sử dụng trong localesConfig
import vi from './locales/vi.json'
import en from './locales/en.json'
import jp from './locales/jp.json'
const localesConfig: ILocalesConfig = {
defaultLanguage: 'vi',
resources: {
vi,
en,
jp,
},
}
export function MiniApp() {
return <App config={appConfig} localesConfig={localesConfig} />
}Sau khi declare ICustomLocales, TypeScript sẽ tự động infer:
- Locales keys từ
typeof vi - Language codes từ
'jp' | 'en' | 'vi'
Tất cả các functions và hooks sẽ có type safety với các keys và languages đã declare.
Sử dụng Translation Functions
Standalone Functions
import { t, getLanguage, setLanguage } from '@v-miniapp/ui-react'
// Basic usage
const title = t('app.title')
// With template params
const greeting = t('user.greeting', { name: 'John' })
// Translation: "Xin chào {name}!" → "Xin chào John!"
// Get translation in specific language
const titleVi = t('app.title', undefined, 'vi')
const titleEn = t('app.title', undefined, 'en')
// Get current language
const currentLang = getLanguage() // 'vi' | 'en' | 'jp' (inferred từ ICustomLocales)
// Change language
setLanguage('en') // Type-safe, chỉ chấp nhận languages đã declare⚠️ Lưu ý về Reactivity:
Các standalone functions t không có reactivity. Khi ngôn ngữ thay đổi, component sử dụng các functions này sẽ không tự động re-render.
// ❌ Không reactive - Component không re-render khi language thay đổi
function MyComponent() {
const title = t('app.title')
const greeting = t('user.greeting', undefined, 'en')
return (
<div>
{title} - {greeting}
</div>
)
// Khi setLanguage() được gọi, component này sẽ KHÔNG re-render
}Giải pháp: Sử dụng React Hook useTranslate trong components để có reactivity.
React Hooks
Sử dụng hooks trong React components để có reactivity:
import { useTranslate, useLanguage } from '@v-miniapp/ui-react'
function MyComponent() {
// useTranslate hook - tự động infer keys từ ICustomLocales
const t = useTranslate()
// useLanguage hook - tự động infer languages từ ICustomLocales
const { language, setLanguage } = useLanguage()
return (
<div>
<h1>{t('app.title')}</h1>
<p>{t('user.greeting', { name: 'John' })}</p>
<p>Current language: {language}</p>
<button onClick={() => setLanguage('vi')}>Tiếng Việt</button>
<button onClick={() => setLanguage('en')}>English</button>
<button onClick={() => setLanguage('jp')}>日本語</button>
</div>
)
}✅ Reactivity:
React hook useTranslate có reactivity. Component sử dụng hook này sẽ tự động re-render khi ngôn ngữ thay đổi.
// ✅ Có reactive - Component tự động re-render khi language thay đổi
function MyComponent() {
const t = useTranslate()
return <div>{t('app.title')}</div>
// Khi setLanguage() được gọi, component này sẽ TỰ ĐỘNG re-render
}Template Parameters
Locales module hỗ trợ template parameters trong translation strings sử dụng cú pháp `{key}`:
// Locales definition (trong JSON files hoặc resources)
const resources = {
vi: {
'user.greeting': 'Xin chào {name}!',
'user.welcome': 'Chào mừng bạn đến với {app}',
'calendar.headerLabel': '{month} - {year}',
},
en: {
'user.greeting': 'Hello {name}!',
'user.welcome': 'Welcome to {app}',
'calendar.headerLabel': '{month} - {year}',
},
}
// Usage
t('user.greeting', { name: 'John' })
// → "Xin chào John!" (vi) hoặc "Hello John!" (en)
t('user.welcome', { app: 'MyApp' })
// → "Chào mừng bạn đến với MyApp" (vi) hoặc "Welcome to MyApp" (en)
t('calendar.headerLabel', { month: 'Tháng 1', year: '2024' })
// → "Tháng 1 - 2024"Type Inference và Type Safety
TypeScript tự động infer custom keys và custom languages từ module augmentation trong global.d.ts. Sau khi declare ICustomLocales:
// global.d.ts
declare module '@v-miniapp/ui-react' {
interface ICustomLocales {
resource: typeof vi // Infer keys từ vi.json
language: 'jp' | 'en' | 'vi' // Infer languages
}
}Tất cả các functions và hooks sẽ tự động có type safety:
// ✅ Type-safe: t() sẽ suggest keys từ ICustomLocales.resource
const title = t('app.title')
// ✅ Type-safe: setLanguage() chỉ chấp nhận 'jp' | 'en' | 'vi'
setLanguage('jp')
// ❌ Type error: 'ja' không có trong ICustomLocales.language
setLanguage('ja') // Error!
// ❌ Type error: Key không tồn tại trong ICustomLocales.resource
const invalid = t('app.invalidKey') // Error!Best Practices
1. Sử dụng hooks trong React components
Luôn sử dụng useTranslate trong React components để có reactivity. Chỉ sử dụng standalone functions t khi:
- Bạn gọi từ bên ngoài React components (utility functions, services, etc.)
- Bạn không cần component re-render khi ngôn ngữ thay đổi
// ✅ Good - Trong React component, dùng hooks
function MyComponent() {
const t = useTranslate()
return <div>{t('app.title')}</div>
}
// ✅ Good - Ngoài React component, dùng standalone function
export function getPageTitle() {
return t('app.title')
}
// ❌ Bad - Trong React component, dùng standalone function (không reactive)
function MyComponent() {
const title = t('app.title')
return <div>{title}</div> // Sẽ không re-render khi language thay đổi
}2. Đặt tên keys có cấu trúc
Sử dụng dot notation để nhóm keys theo module/feature:
// ✅ Good
'app.title'
'user.greeting'
'button.submit'
'form.validation.required'
// ❌ Bad
'appTitle'
'userGreeting'
'submitButton'3. Sử dụng module augmentation cho type safety
Declare ICustomLocales trong global.d.ts để có type safety cho cả keys và languages:
// ✅ Type-safe với module augmentation
declare module '@v-miniapp/ui-react' {
interface ICustomLocales {
resource: typeof vi
language: 'jp' | 'en' | 'vi'
}
}
// ❌ Không có type safety nếu không declare
const title = t('app.title') // key là string, không có autocomplete4. Override default translations
Bạn có thể override các translation keys mặc định:
const localesConfig: ILocalesConfig = {
resources: {
vi: {
// Override default pull-to-refresh text
'pullToRefresh.canReleaseText': 'Thả tay để làm mới',
'pullToRefresh.completeText': 'Hoàn tất',
// Add custom keys
'app.title': 'Ứng dụng của tôi',
},
},
}5. Import từ JSON files
Import translations từ JSON files và sử dụng typeof để infer types:
// ✅ Import từ JSON
import vi from './locales/vi.json'
declare module '@v-miniapp/ui-react' {
interface ICustomLocales {
resource: typeof vi // Auto-infer types
language: 'jp' | 'en' | 'vi'
}
}Reference
Types
ILocalesConfig
Cấu hình locales cho App component hoặc LocalesProvider.
type ILocalesConfig = {
defaultLanguage?: IAppLanguage
resources?: IOptinalResources
}Properties:
| Name | Type | Required | Description |
| :---------------- | :------------------ | :------- | :------------------------------------------------------------------------------------------------------- |
| defaultLanguage | IAppLanguage | No | Ngôn ngữ mặc định. Có thể là 'vi', 'en', hoặc 'system' (hoặc custom languages từ ICustomLocales) |
| resources | IOptinalResources | No | Object chứa các locales translations. Keys là language codes, values là resource maps |
ICustomLocales
Interface để declare custom locales thông qua module augmentation.
interface ICustomLocales {
resource: Record<string, string> // Type của locales keys (thường là typeof vi từ JSON)
language: string // Union type của language codes (e.g., 'vi' | 'en' | 'jp')
}Ví dụ:
// global.d.ts
declare module '@v-miniapp/ui-react' {
interface ICustomLocales {
resource: typeof vi // Infer từ vi.json
language: 'jp' | 'en' | 'vi' // Custom languages
}
}IAppLanguage
Union type của language codes bao gồm default và custom languages.
type IAppLanguage = ILang | 'system'ILang được infer từ IDefaultLocales['language'] (default: 'vi' | 'en') và ICustomLocales['language'] (nếu có).
Components
LocalesProvider
Component để khởi tạo locales module.
type LocalesProviderProps = {
config?: ILocalesConfig
}Usage:
<LocalesProvider config={localesConfig} />Lưu ý: Component này chỉ init một lần khi mount, nên cần đặt ở top-level.
Functions & Hooks
t(key, params?, lang?)
Standalone function để translate key.
- Parameters:
key:IResourceKey- Locales key (inferred từICustomLocales.resourcenếu có)params?:ITemplateParams- Template parameters objectlang?:ILang- Ngôn ngữ chỉ định
- Returns:
string- Translated text - Reactivity: ❌ Không có reactivity
useTranslate()
React hook để translate trong components.
- Returns: Function tương tự
t(key, params?) - Reactivity: ✅ Có reactivity
getLanguage()
Standalone function để lấy current language.
- Returns:
ILang- Current language
setLanguage(language)
Standalone function để thay đổi language.
- Parameters:
language:ILang- Language code (inferred từICustomLocales.languagenếu có)
useLanguage()
React hook để quản lý language.
- Returns:
{ language: ILang, setLanguage: (lang: ILang) => void }language: Current language (inferred từICustomLocales.languagenếu có)setLanguage: Function để thay đổi language (type-safe vớiICustomLocales.language)
