react-native-i18njs 0.0.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,14 +4,17 @@
4
4
  [![License](https://img.shields.io/npm/l/react-native-i18njs.svg)](https://www.npmjs.com/package/react-native-i18njs)
5
5
  [![Platform](https://img.shields.io/badge/platform-react--native-blue.svg)](https://reactnative.dev)
6
6
  [![TypeScript](https://img.shields.io/badge/types-included-blue.svg)](https://www.typescriptlang.org)
7
+ [![gzip size](https://img.shields.io/badge/gzip-%7E3.3%20KB-brightgreen.svg)](https://www.npmjs.com/package/react-native-i18njs)
7
8
 
8
- 一个轻量级、类型安全、零心智负担的 React Native 国际化解决方案。
9
+ 一个**极致轻量**、类型安全、零心智负担的 React Native 国际化解决方案。
10
+ 构建产物经 minify + gzip 后约 **3.3 KB**,对包体积几乎无感。
9
11
 
10
- 专为 React Native 设计,集成了最佳实践,解决了常见的国际化痛点:繁琐的配置、类型缺失、复杂的 API 以及系统语言跟随问题。
12
+ 专为 React Native 设计,集成了最佳实践,解决繁琐配置、类型缺失、复杂 API 以及系统语言跟随等问题。
11
13
 
12
14
  ## ✨ 特性
13
15
 
14
- - **零配置启动**:内置智能默认值,安装即用。
16
+ - 📦 **极小体积**:ESM 构建 gzip 约 3.3 KB,CJS 约 3.5 KB;源码极致压缩,无冗余依赖。
17
+ - ✨ **零配置启动**:内置智能默认值,安装即用。
15
18
  - 🛡️ **极致类型安全**:完全 TypeScript 编写,提供从 Key 到插值参数的完整类型推导。
16
19
  - 📱 **自动跟随系统**:基于 `react-native-localize`,自动检测并响应设备语言变更。
17
20
  - ⚡ **高性能**:基于 `i18n-js` 核心,轻量高效,无多余运行时开销。
@@ -19,6 +22,15 @@
19
22
  - 📝 **富文本支持**:`Trans` 组件轻松处理嵌套样式和组件插值。
20
23
  - 🌍 **格式化内置**:开箱即用的数字、货币、日期格式化支持。
21
24
 
25
+ ## 📦 体积说明 (Bundle Size)
26
+
27
+ | 格式 | 未压缩 | gzip |
28
+ |------|--------|------|
29
+ | ESM (`.mjs`) | ~8.1 KB | **~3.3 KB** |
30
+ | CJS (`.js`) | ~8.9 KB | **~3.5 KB** |
31
+
32
+ 以上为单入口打包、开启 minify 后的体积;实际打进业务的增量取决于打包工具的 tree-shaking。推荐使用 ESM 以获得更优体积与 gzip 表现。
33
+
22
34
  ## 📦 安装
23
35
 
24
36
  ```bash
@@ -252,8 +264,31 @@ formatDate(new Date());
252
264
  | `onMissingKey` | `function` | - | 缺失 key 的回调 |
253
265
  | `onLocaleChange` | `function` | - | 语言变更回调 |
254
266
 
267
+ ## ✅ 生产就绪 (Production Ready)
268
+
269
+ 本库在功能与健壮性上已按生产标准实现,具备:
270
+
271
+ | 能力 | 说明 |
272
+ |------|------|
273
+ | **多场景使用** | 组件内(Hook / HOC)、组件外(全局 `t`、格式化、Redux/拦截器等)统一 API |
274
+ | **插值与复数** | `%{name}` 插值、`one`/`other` 等复数规则(透传 i18n-js),支持 `defaultValue` |
275
+ | **缺失策略** | `missingBehavior`:回退 key / 空串 / 抛错;`onMissingKey` 便于上报与兜底 |
276
+ | **语言链** | 当前 locale 自动降级(如 en-US → en)、自定义 `fallbackLocales`、可函数动态回退 |
277
+ | **系统语言** | 基于 `react-native-localize`,App 回到前台自动同步;`setLocale` 用户锁定、`resetToSystem` 恢复跟随 |
278
+ | **动态文案** | `loadTranslations` 合并新语种/命名空间,`subscribe` 通知 UI 更新 |
279
+ | **RTL** | 按语言/script 检测 RTL,调用 `I18nManager`(需重启生效,属 RN 限制) |
280
+ | **格式化** | 数字/货币/日期使用 `Intl` 并带缓存,无 Intl 环境有降级 |
281
+ | **富文本** | `Trans` 支持标签解析、组件映射、插值内嵌 React 节点 |
282
+ | **类型安全** | `Path<T>`、`useI18n<T>` 提供 key 补全与校验 |
283
+ | **环境兼容** | 无 `Intl` / 无 `react-native-localize` 时 try-catch 降级,不抛错 |
284
+
285
+ 使用前请在 App 入口**先调用 `initI18n`**,再使用 `t` / `useI18n` / `Trans` 等。
286
+
255
287
  ## 🧩 常见问题
256
288
 
289
+ ### 使用前必须先 init 吗?
290
+ 是的。在调用 `t`、`useI18n`、`Trans` 等之前,请在应用入口(如 `App.tsx`)执行一次 `initI18n(translations, options)`,否则会使用空翻译表。
291
+
257
292
  ### TypeScript 类型提示不工作?
258
293
  确保你在使用 `useI18n<MyTranslations>()` 时传入了你的翻译类型定义。
259
294
 
package/dist/index.d.mts CHANGED
@@ -2,100 +2,70 @@ import { Scope, TranslateOptions } from 'i18n-js';
2
2
  import React, { ReactNode } from 'react';
3
3
  import { TextProps } from 'react-native';
4
4
 
5
+ type Translations = Record<string, any>;
6
+ type Listener = (locale: string, change?: {
7
+ type: 'locale' | 'translations';
8
+ version: number;
9
+ }) => void;
5
10
  interface I18nOptions {
6
11
  defaultLocale?: string;
7
12
  enableFallback?: boolean;
8
13
  onLocaleChange?: (locale: string) => void;
9
14
  fallbackLocales?: string[] | ((locale: string) => string[]);
10
- /**
11
- * 是否跟随系统语言变化自动切换。
12
- * - 默认 true:初始化会使用系统语言;App 回到前台时会再次同步系统语言(直到用户手动 setLocale)。
13
- * - 设为 false:始终使用 defaultLocale / 手动 setLocale,不再自动同步系统语言。
14
- */
15
15
  followSystem?: boolean;
16
16
  missingBehavior?: 'key' | 'empty' | 'throw';
17
17
  onMissingKey?: (key: string, locale: string) => void;
18
18
  }
19
- type Translations = Record<string, any>;
20
- type Listener = (locale: string, change?: {
21
- type: 'locale' | 'translations';
22
- version: number;
23
- }) => void;
24
- /**
25
- * i18n 引擎接口,定义了任何翻译引擎必须实现的方法
26
- */
27
- interface I18nEngine {
28
- init(translations: Translations, options?: I18nOptions): void;
29
- loadTranslations(translations: Translations): void;
30
- setLocale(locale: string): void;
31
- getLocale(): string;
32
- t(scope: Scope, options?: TranslateOptions): string;
33
- formatNumber(n: number, options?: Intl.NumberFormatOptions): string;
34
- formatCurrency(n: number, currency: string, options?: Intl.NumberFormatOptions): string;
35
- formatDate(date: Date | number, options?: Intl.DateTimeFormatOptions): string;
36
- subscribe(listener: Listener): () => void;
37
- isRTL(): boolean;
38
- /** 重置为跟随系统语言,撤销 setLocale 的用户锁定 */
39
- resetToSystem(): void;
40
- ready(): Promise<void>;
41
- isReady(): boolean;
42
- }
43
- /**
44
- * 默认的 i18n-js 引擎实现
45
- */
46
- declare class DefaultI18nEngine implements I18nEngine {
47
- private i18n;
48
- private listeners;
49
- private onLocaleChange?;
50
- private fallbackLocales?;
51
- private missingBehavior;
52
- private onMissingKey?;
53
- private enableFallback;
54
- private followSystem;
55
- private localeSource;
56
- private initialized;
57
- private version;
58
- private readyPromise;
59
- private resolveReady?;
60
- /** Intl 格式化器缓存,key = locale + JSON(options) */
61
- private numberFormatCache;
62
- private dateFormatCache;
63
- /** locale chain 缓存,locale 或 fallbackLocales 变化时失效 */
64
- private localeChainCache;
19
+ declare class E {
20
+ private i;
21
+ private ls;
22
+ private cb?;
23
+ private fb?;
24
+ private mb;
25
+ private mk?;
26
+ private ef;
27
+ private fs;
28
+ private sr;
29
+ private ok;
30
+ private v;
31
+ private rp;
32
+ private rr?;
33
+ private nc;
34
+ private dc;
35
+ private lc;
65
36
  constructor();
66
- init(translations: Translations, options?: I18nOptions): void;
67
- loadTranslations(translations: Translations): void;
37
+ init(tr: Translations, o?: I18nOptions): void;
38
+ loadTranslations(tr: Translations): void;
68
39
  updateLocale(): void;
69
- setLocale(locale: string): void;
40
+ setLocale(l: string): void;
70
41
  getLocale(): string;
71
42
  resetToSystem(): void;
72
43
  t(scope: Scope, options?: TranslateOptions): string;
73
- formatNumber(n: number, options?: Intl.NumberFormatOptions): string;
74
- formatCurrency(n: number, currency: string, options?: Intl.NumberFormatOptions): string;
75
- formatDate(date: Date | number, options?: Intl.DateTimeFormatOptions): string;
76
- subscribe(listener: Listener): () => void;
44
+ formatNumber(n: number, o?: Intl.NumberFormatOptions): string;
45
+ formatCurrency(n: number, c: string, o?: Intl.NumberFormatOptions): string;
46
+ formatDate(d: Date | number, o?: Intl.DateTimeFormatOptions): string;
47
+ subscribe(l: Listener): () => void;
77
48
  isRTL(): boolean;
78
49
  ready(): Promise<void>;
79
50
  isReady(): boolean;
80
- private invalidateCaches;
81
- private getCachedNumberFormat;
82
- private getCachedDateFormat;
83
- private handleRTL;
84
- private notifyListeners;
85
- private setLocaleFromSystem;
86
- private applyLocale;
87
- private translateAtLocale;
88
- /** 将 locale 及其自动降级(如 en-US → en)追加到 chain 中 */
89
- private pushWithDegradation;
90
- private getLocaleChain;
91
- private hasTranslation;
92
- private normalizeTranslateResult;
93
- private normalizeLocaleTag;
94
- private normalizeTranslations;
95
- private isRTLLocale;
51
+ private cl;
52
+ private gn;
53
+ private gd;
54
+ private em;
55
+ private ap;
56
+ private hr;
57
+ private ta;
58
+ private dg;
59
+ private gc;
60
+ private ht;
61
+ private nr;
62
+ private nt;
96
63
  }
97
- declare const i18nService: DefaultI18nEngine;
64
+ declare const i18nService: E;
98
65
 
66
+ type Path<T> = T extends object ? {
67
+ [K in keyof T]: `${Exclude<K, symbol>}${"" | `.${Path<T[K]>}`}`;
68
+ }[keyof T] : never;
99
69
  interface I18nContextType {
100
70
  locale: string;
101
71
  setLocale: (locale: string) => void;
@@ -111,12 +81,6 @@ interface I18nProviderProps {
111
81
  fallback?: ReactNode;
112
82
  }
113
83
  declare const I18nProvider: React.FC<I18nProviderProps>;
114
- declare function withI18n<P extends object>(Component: React.ComponentType<P & I18nContextType>): React.FC<Omit<P, keyof I18nContextType>>;
115
-
116
- type Path<T> = T extends object ? {
117
- [K in keyof T]: `${Exclude<K, symbol>}${"" | `.${Path<T[K]>}`}`;
118
- }[keyof T] : never;
119
-
120
84
  type TFunction<T> = (scope: T extends Translations ? Path<T> : string, options?: TranslateOptions) => string;
121
85
  declare function useI18n<T = Translations>(): {
122
86
  t: TFunction<T>;
@@ -126,6 +90,7 @@ declare function useI18n<T = Translations>(): {
126
90
  formatCurrency: (n: number, currency: string, options?: Intl.NumberFormatOptions) => string;
127
91
  formatDate: (date: Date | number, options?: Intl.DateTimeFormatOptions) => string;
128
92
  };
93
+ declare function withI18n<P extends object>(C: React.ComponentType<P & I18nContextType>): React.FC<Omit<P, keyof I18nContextType>>;
129
94
 
130
95
  interface TransProps extends TextProps {
131
96
  i18nKey: string;
@@ -134,17 +99,16 @@ interface TransProps extends TextProps {
134
99
  }
135
100
  declare const Trans: React.FC<TransProps>;
136
101
 
137
- declare const initI18n: (translations: Translations, options?: I18nOptions) => void;
138
- declare const loadTranslations: (translations: Translations) => void;
139
- declare const setLocale: (locale: string) => void;
102
+ declare const initI18n: (t: Translations, o?: I18nOptions) => void;
103
+ declare const loadTranslations: (t: Translations) => void;
104
+ declare const setLocale: (l: string) => void;
140
105
  declare const getLocale: () => string;
141
- declare const t: (scope: Scope, options?: TranslateOptions) => string;
142
- declare const formatNumber: (n: number, options?: Intl.NumberFormatOptions) => string;
143
- declare const formatCurrency: (n: number, currency: string, options?: Intl.NumberFormatOptions) => string;
144
- declare const formatDate: (date: Date | number, options?: Intl.DateTimeFormatOptions) => string;
145
- declare const subscribe: (listener: Listener) => (() => void);
106
+ declare const t: (scope: Scope, o?: TranslateOptions) => string;
107
+ declare const formatNumber: (n: number, o?: Intl.NumberFormatOptions) => string;
108
+ declare const formatCurrency: (n: number, c: string, o?: Intl.NumberFormatOptions) => string;
109
+ declare const formatDate: (d: Date | number, o?: Intl.DateTimeFormatOptions) => string;
110
+ declare const subscribe: (l: Listener) => () => void;
146
111
  declare const isRTL: () => boolean;
147
- /** 重置为跟随系统语言,撤销 setLocale 的用户锁定 */
148
112
  declare const resetToSystem: () => void;
149
113
  declare const readyI18n: () => Promise<void>;
150
114
  declare const isI18nReady: () => boolean;
package/dist/index.d.ts CHANGED
@@ -2,100 +2,70 @@ import { Scope, TranslateOptions } from 'i18n-js';
2
2
  import React, { ReactNode } from 'react';
3
3
  import { TextProps } from 'react-native';
4
4
 
5
+ type Translations = Record<string, any>;
6
+ type Listener = (locale: string, change?: {
7
+ type: 'locale' | 'translations';
8
+ version: number;
9
+ }) => void;
5
10
  interface I18nOptions {
6
11
  defaultLocale?: string;
7
12
  enableFallback?: boolean;
8
13
  onLocaleChange?: (locale: string) => void;
9
14
  fallbackLocales?: string[] | ((locale: string) => string[]);
10
- /**
11
- * 是否跟随系统语言变化自动切换。
12
- * - 默认 true:初始化会使用系统语言;App 回到前台时会再次同步系统语言(直到用户手动 setLocale)。
13
- * - 设为 false:始终使用 defaultLocale / 手动 setLocale,不再自动同步系统语言。
14
- */
15
15
  followSystem?: boolean;
16
16
  missingBehavior?: 'key' | 'empty' | 'throw';
17
17
  onMissingKey?: (key: string, locale: string) => void;
18
18
  }
19
- type Translations = Record<string, any>;
20
- type Listener = (locale: string, change?: {
21
- type: 'locale' | 'translations';
22
- version: number;
23
- }) => void;
24
- /**
25
- * i18n 引擎接口,定义了任何翻译引擎必须实现的方法
26
- */
27
- interface I18nEngine {
28
- init(translations: Translations, options?: I18nOptions): void;
29
- loadTranslations(translations: Translations): void;
30
- setLocale(locale: string): void;
31
- getLocale(): string;
32
- t(scope: Scope, options?: TranslateOptions): string;
33
- formatNumber(n: number, options?: Intl.NumberFormatOptions): string;
34
- formatCurrency(n: number, currency: string, options?: Intl.NumberFormatOptions): string;
35
- formatDate(date: Date | number, options?: Intl.DateTimeFormatOptions): string;
36
- subscribe(listener: Listener): () => void;
37
- isRTL(): boolean;
38
- /** 重置为跟随系统语言,撤销 setLocale 的用户锁定 */
39
- resetToSystem(): void;
40
- ready(): Promise<void>;
41
- isReady(): boolean;
42
- }
43
- /**
44
- * 默认的 i18n-js 引擎实现
45
- */
46
- declare class DefaultI18nEngine implements I18nEngine {
47
- private i18n;
48
- private listeners;
49
- private onLocaleChange?;
50
- private fallbackLocales?;
51
- private missingBehavior;
52
- private onMissingKey?;
53
- private enableFallback;
54
- private followSystem;
55
- private localeSource;
56
- private initialized;
57
- private version;
58
- private readyPromise;
59
- private resolveReady?;
60
- /** Intl 格式化器缓存,key = locale + JSON(options) */
61
- private numberFormatCache;
62
- private dateFormatCache;
63
- /** locale chain 缓存,locale 或 fallbackLocales 变化时失效 */
64
- private localeChainCache;
19
+ declare class E {
20
+ private i;
21
+ private ls;
22
+ private cb?;
23
+ private fb?;
24
+ private mb;
25
+ private mk?;
26
+ private ef;
27
+ private fs;
28
+ private sr;
29
+ private ok;
30
+ private v;
31
+ private rp;
32
+ private rr?;
33
+ private nc;
34
+ private dc;
35
+ private lc;
65
36
  constructor();
66
- init(translations: Translations, options?: I18nOptions): void;
67
- loadTranslations(translations: Translations): void;
37
+ init(tr: Translations, o?: I18nOptions): void;
38
+ loadTranslations(tr: Translations): void;
68
39
  updateLocale(): void;
69
- setLocale(locale: string): void;
40
+ setLocale(l: string): void;
70
41
  getLocale(): string;
71
42
  resetToSystem(): void;
72
43
  t(scope: Scope, options?: TranslateOptions): string;
73
- formatNumber(n: number, options?: Intl.NumberFormatOptions): string;
74
- formatCurrency(n: number, currency: string, options?: Intl.NumberFormatOptions): string;
75
- formatDate(date: Date | number, options?: Intl.DateTimeFormatOptions): string;
76
- subscribe(listener: Listener): () => void;
44
+ formatNumber(n: number, o?: Intl.NumberFormatOptions): string;
45
+ formatCurrency(n: number, c: string, o?: Intl.NumberFormatOptions): string;
46
+ formatDate(d: Date | number, o?: Intl.DateTimeFormatOptions): string;
47
+ subscribe(l: Listener): () => void;
77
48
  isRTL(): boolean;
78
49
  ready(): Promise<void>;
79
50
  isReady(): boolean;
80
- private invalidateCaches;
81
- private getCachedNumberFormat;
82
- private getCachedDateFormat;
83
- private handleRTL;
84
- private notifyListeners;
85
- private setLocaleFromSystem;
86
- private applyLocale;
87
- private translateAtLocale;
88
- /** 将 locale 及其自动降级(如 en-US → en)追加到 chain 中 */
89
- private pushWithDegradation;
90
- private getLocaleChain;
91
- private hasTranslation;
92
- private normalizeTranslateResult;
93
- private normalizeLocaleTag;
94
- private normalizeTranslations;
95
- private isRTLLocale;
51
+ private cl;
52
+ private gn;
53
+ private gd;
54
+ private em;
55
+ private ap;
56
+ private hr;
57
+ private ta;
58
+ private dg;
59
+ private gc;
60
+ private ht;
61
+ private nr;
62
+ private nt;
96
63
  }
97
- declare const i18nService: DefaultI18nEngine;
64
+ declare const i18nService: E;
98
65
 
66
+ type Path<T> = T extends object ? {
67
+ [K in keyof T]: `${Exclude<K, symbol>}${"" | `.${Path<T[K]>}`}`;
68
+ }[keyof T] : never;
99
69
  interface I18nContextType {
100
70
  locale: string;
101
71
  setLocale: (locale: string) => void;
@@ -111,12 +81,6 @@ interface I18nProviderProps {
111
81
  fallback?: ReactNode;
112
82
  }
113
83
  declare const I18nProvider: React.FC<I18nProviderProps>;
114
- declare function withI18n<P extends object>(Component: React.ComponentType<P & I18nContextType>): React.FC<Omit<P, keyof I18nContextType>>;
115
-
116
- type Path<T> = T extends object ? {
117
- [K in keyof T]: `${Exclude<K, symbol>}${"" | `.${Path<T[K]>}`}`;
118
- }[keyof T] : never;
119
-
120
84
  type TFunction<T> = (scope: T extends Translations ? Path<T> : string, options?: TranslateOptions) => string;
121
85
  declare function useI18n<T = Translations>(): {
122
86
  t: TFunction<T>;
@@ -126,6 +90,7 @@ declare function useI18n<T = Translations>(): {
126
90
  formatCurrency: (n: number, currency: string, options?: Intl.NumberFormatOptions) => string;
127
91
  formatDate: (date: Date | number, options?: Intl.DateTimeFormatOptions) => string;
128
92
  };
93
+ declare function withI18n<P extends object>(C: React.ComponentType<P & I18nContextType>): React.FC<Omit<P, keyof I18nContextType>>;
129
94
 
130
95
  interface TransProps extends TextProps {
131
96
  i18nKey: string;
@@ -134,17 +99,16 @@ interface TransProps extends TextProps {
134
99
  }
135
100
  declare const Trans: React.FC<TransProps>;
136
101
 
137
- declare const initI18n: (translations: Translations, options?: I18nOptions) => void;
138
- declare const loadTranslations: (translations: Translations) => void;
139
- declare const setLocale: (locale: string) => void;
102
+ declare const initI18n: (t: Translations, o?: I18nOptions) => void;
103
+ declare const loadTranslations: (t: Translations) => void;
104
+ declare const setLocale: (l: string) => void;
140
105
  declare const getLocale: () => string;
141
- declare const t: (scope: Scope, options?: TranslateOptions) => string;
142
- declare const formatNumber: (n: number, options?: Intl.NumberFormatOptions) => string;
143
- declare const formatCurrency: (n: number, currency: string, options?: Intl.NumberFormatOptions) => string;
144
- declare const formatDate: (date: Date | number, options?: Intl.DateTimeFormatOptions) => string;
145
- declare const subscribe: (listener: Listener) => (() => void);
106
+ declare const t: (scope: Scope, o?: TranslateOptions) => string;
107
+ declare const formatNumber: (n: number, o?: Intl.NumberFormatOptions) => string;
108
+ declare const formatCurrency: (n: number, c: string, o?: Intl.NumberFormatOptions) => string;
109
+ declare const formatDate: (d: Date | number, o?: Intl.DateTimeFormatOptions) => string;
110
+ declare const subscribe: (l: Listener) => () => void;
146
111
  declare const isRTL: () => boolean;
147
- /** 重置为跟随系统语言,撤销 setLocale 的用户锁定 */
148
112
  declare const resetToSystem: () => void;
149
113
  declare const readyI18n: () => Promise<void>;
150
114
  declare const isI18nReady: () => boolean;