intor-translator 1.0.0 β†’ 1.0.3

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
@@ -1,28 +1,39 @@
1
- # IntorTranslator
1
+ <h1 align="center">Intor Translator</h1>
2
2
 
3
- A highly flexible and type-safe i18n translation engine for modern applications β€” supporting fallback locales, async loading states, scoped namespaces, and both simple and rich formatting.
3
+ <div align="center">
4
4
 
5
- [![NPM version](https://img.shields.io/npm/v/intor-translator)](https://www.npmjs.com/package/intor-translator)
6
- [![Bundle size](https://img.shields.io/bundlephobia/minzip/intor-translator)](https://bundlephobia.com/package/intor-translator)
7
- [![License](https://img.shields.io/npm/l/intor-translator)](LICENSE)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-%E2%9C%94-blue)](https://www.typescriptlang.org/)
5
+ A type safe translator that knows what to say and how to handle the rest.
6
+
7
+ </div>
8
+
9
+ <div align="center">
10
+
11
+ [![NPM version](https://img.shields.io/npm/v/intor-translator?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/intor-translator)
12
+ [![Bundle size](https://img.shields.io/bundlephobia/minzip/intor-translator?style=flat&colorA=000000&colorB=000000)](https://bundlephobia.com/package/intor-translator)
13
+ [![License](https://img.shields.io/npm/l/intor-translator?style=flat&colorA=000000&colorB=000000)](LICENSE)
14
+ [![TypeScript](https://img.shields.io/badge/TypeScript-%E2%9C%94-blue?style=flat&colorA=000000&colorB=000000)](https://www.typescriptlang.org/)
15
+
16
+ </div>
17
+
18
+ > Translate with confidence.
19
+ > A type-safe i18n engine with fallback, scoped namespaces, and graceful loading.
9
20
 
10
21
  ---
11
22
 
12
23
  ## Features
13
24
 
14
- - 🌍 Fallback locale support
15
- - ⚑ Reactive translation logic
16
- - 🧠 Type-safe nested key paths
17
- - πŸ” Replacement support
18
- - 🎨 Rich replacement formatting
19
- - πŸŒ€ Graceful loading state handling
20
- - πŸ”§ Configurable handlers for fallback, loading, and placeholder cases
21
- - 🧩 Scoped translator for modules or namespaces
25
+ - 🌍 Fallback locale support for smooth language switching
26
+ - ⚑ Reactive translation logic that updates on the fly
27
+ - 🧠 Type-safe nested key paths with full autocomplete
28
+ - πŸ” Flexible replacement and interpolation support
29
+ - 🎨 Rich formatting for complex replacement content
30
+ - πŸŒ€ Graceful handling of loading and async states
31
+ - πŸ”§ Configurable handlers for fallback, loading, and missing keys
32
+ - 🧩 Scoped translators for modules and namespaces
22
33
 
23
34
  ---
24
35
 
25
- ## Installation
36
+ ## <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Symbols/Triangular%20Flag.png" alt="Triangular Flag" width="16" height="16" /> Installation
26
37
 
27
38
  ```bash
28
39
  npm install intor-translator
@@ -36,98 +47,142 @@ yarn add intor-translator
36
47
 
37
48
  ---
38
49
 
39
- ## Quick Start
50
+ ## <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Travel%20and%20places/Rocket.png" alt="Rocket" width="25" height="25" /> Quick Start
40
51
 
41
52
  ```typescript
42
- import { createTranslator } from "intor-translator";
53
+ import { Translator } from "intor-translator";
43
54
 
44
- // Create a translator instance
45
- const translator = createTranslator({
46
- locale: "en",
47
- messages: {
48
- en: {
49
- hello: "Hello World",
50
- greeting: "Hello, {name}!", // Use curly braces for replacements
51
- },
55
+ const messages = {
56
+ en: {
57
+ hello: "Hello World",
58
+ greeting: "Hello, {name}!", // Use curly braces for replacements
52
59
  },
53
- });
60
+ };
61
+
62
+ // Create a translator instance
63
+ const translator = new Translator({ messages, locale: "en" });
54
64
 
55
65
  // Use the translator
56
- translator.t("hello"); // > Hello World
57
- translator.t("greeting", { name: "John doe" }); // > Hello, John doe!
66
+ translator.t("hello"); // -> Hello World
67
+ translator.t("greeting", { name: "John doe" }); // -> Hello, John doe!
58
68
  ```
59
69
 
60
70
  ---
61
71
 
62
- ## Advanced Features
72
+ ## <img src="https://raw.githubusercontent.com/Tarikul-Islam-Anik/Animated-Fluent-Emojis/master/Emojis/Activities/Sparkles.png" alt="Sparkles" width="25" height="25" /> Advanced Features
63
73
 
64
74
  - Fallback Locales, Placeholder & Custom Handlers
65
75
 
66
76
  ```typescript
67
- const translator = createTranslator({
77
+ const translator = new Translator({
68
78
  locale: "en",
69
79
  messages: {
70
80
  en: {
71
- greeting: "Hello, {name}!",
81
+ welcome: "Welcome back, {name}",
72
82
  },
73
83
  zh: {
74
- greeting: "ε“ˆε›‰, {name}!",
75
- "only-in-zh": "This message is not exist in en",
84
+ welcome: "ζ­‘θΏŽε›žδΎ†οΌŒ{name}",
85
+ notification: "δ½ ζœ‰ {count} ε‰‡ζ–°ι€šηŸ₯",
76
86
  },
77
87
  },
78
- fallbackLocales: { en: ["zh"] }, // Falls back to zh if message is missing in en
79
- placeholder: "MESSAGE NOT FOUND", // Default text shown when a key is not found in any locale
88
+ fallbackLocales: { en: ["zh"] }, // Use zh if message not found in en
89
+ placeholder: "Content unavailable", // Shown if key is missing in all locales
80
90
  handlers: {
81
- messageFormatter: ({ locale, message }) =>
82
- `${message}${locale === "en" ? "." : "。"}`, // Custom message formatter
91
+ formatMessage: ({ locale, message }) =>
92
+ locale === "zh" ? `${message}。` : `${message}.`, // Auto punctuation per locale
83
93
  },
84
94
  });
85
95
 
86
- translator.t("only-in-zh"); // > This message is not exist in en.
96
+ // en has 'welcome'
97
+ console.log(translator.t("welcome", { name: "John" })); // -> Welcome back, John.
98
+
99
+ // en does not have 'notification', fallback to zh
100
+ console.log(translator.t("notification", { count: 3 })); // -> δ½ ζœ‰ 3 ε‰‡ζ–°ι€šηŸ₯。
101
+
102
+ // message does not exist in any locale
103
+ console.log(translator.t("unknown.key")); // -> Content unavailable
87
104
  ```
88
105
 
89
106
  - With Custom ICU Formatter
90
107
 
91
108
  ```typescript
92
- import IntlMessageFormat from "intl-messageformat";
93
- import { MessageFormatter } from "intor-translator";
109
+ import { Translator, FormatMessage } from "intor-translator";
110
+ import { IntlMessageFormat } from "intl-messageformat";
94
111
 
95
- const formatter: MessageFormatter = ({ message, locale, replacements }) => {
112
+ // Create a custom handler
113
+ const formatMessage: FormatMessage = ({ message, locale, replacements }) => {
96
114
  const formatter = new IntlMessageFormat(message, locale);
97
115
  return formatter.format(replacements);
98
116
  };
99
117
 
100
- const translator = createTranslator({
101
- locale: "en",
102
- messages: {
103
- en: {
104
- notification:
105
- "{name} has {count, plural, =0 {no messages} one {1 message} other {# messages}}.",
106
- },
107
- },
108
- handlers: {
109
- messageFormatter: formatter,
118
+ const messages = {
119
+ en: {
120
+ notification:
121
+ "{name} has {count, plural, =0 {no messages} one {1 message} other {# messages}}.",
110
122
  },
123
+ };
124
+
125
+ // Create a translator instance
126
+ const translator = new Translator({
127
+ locale: "en",
128
+ messages,
129
+ handlers: { formatMessage },
111
130
  });
112
131
 
113
- translator.t("notification", { name: "John", count: 0 }); // > John has no messages.
114
- translator.t("notification", { name: "John", count: 5 }); // > John has 5 messages.
132
+ translator.t("notification", { name: "John", count: 0 }); // -> John has no messages.
133
+ translator.t("notification", { name: "John", count: 5 }); // -> John has 5 messages.
115
134
  ```
116
135
 
117
136
  ---
118
137
 
119
138
  ## API Reference
120
139
 
121
- | Option | Type | Description |
122
- | ----------------- | -------------------------------- | ------------------------------------------------------------------------- |
123
- | `messages` | `Record<Locale, Messages>` | Translation messages, structured by locale |
124
- | `locale` | `string` | The active locale |
125
- | `fallbackLocales` | `Record<Locale, Locale[]>` (opt) | Fallback locales used when a message is missing in the active locale |
126
- | `placeholder` | `string`(optοΌ‰ | Default message to display when a key is missing |
127
- | `isLoading` | `boolean`(optοΌ‰ | Indicates if the translator is in a loading state |
128
- | `loadingMessage` | `string`(optοΌ‰ | Message to show when inLoading is true. |
129
- | `handlers` | `TranslatorHandlers`(optοΌ‰ | Custom handler functions for formatting, loading, or placeholder messages |
130
- | |
140
+ ### Translator Parameters
141
+
142
+ | Option | Type | Description |
143
+ | ----------------- | ------------------------------------- | ------------------------------------------------------------------------ |
144
+ | `messages` | `Readonly<LocaleNamespaceMessages>` | Translation messages grouped by locale and namespace |
145
+ | `locale` | `string` | Active locale key |
146
+ | `fallbackLocales` | `Record<Locale, Locale[]>` (optional) | Locales to fallback to when a key is missing |
147
+ | `placeholder` | `string` (optional) | Message to display when a key is missing in all locales |
148
+ | `loadingMessage` | `string` (optional) | Message to display during loading or async state |
149
+ | `handlers` | `TranslateHandlers` (optional) | Custom functions for formatting, loading state, and missing key handling |
150
+
151
+ **TranslateHandlers :**
152
+
153
+ ```ts
154
+ type TranslateHandlers = {
155
+ formatMessage?: (ctx: TranslateContext & { message: string }) => unknown;
156
+ onLoading?: (ctx: TranslateContext) => unknown;
157
+ onMissing?: (ctx: TranslateContext) => unknown;
158
+ };
159
+ ```
160
+
161
+ > Use handlers to control how messages are formatted, what to show during loading, and how to respond to missing keys.
162
+ > Each handler receives a full translation context, including the current locale, key, and replacement values.
163
+
164
+ ---
165
+
166
+ ### Instance Properties
167
+
168
+ | Property | Type | Description |
169
+ | ----------- | -------------- | ------------------------------------------ |
170
+ | `messages` | `M` | Current messages object |
171
+ | `locale` | `LocaleKey<M>` | Currently active locale |
172
+ | `isLoading` | `boolean` | Whether the translator is in loading state |
173
+
174
+ ---
175
+
176
+ ### Instance Methods
177
+
178
+ | Method | Signature | Description |
179
+ | ------------- | ------------------------------------------------- | ------------------------------------------------------------------- |
180
+ | `setMessages` | `(messages: M) => void` | Replaces the current message set |
181
+ | `setLocale` | `(locale: LocaleKey<M>) => boolean` | Sets a new locale and returns whether it changed |
182
+ | `setLoading` | `(state: boolean) => void` | Sets the loading state manually |
183
+ | `hasKey` | `(key, targetLocale?) => boolean` | Checks whether the given key exists in the target or current locale |
184
+ | `t` | `<Result = string>(key, replacements?) => Result` | Translates a key with optional replacements |
185
+ | `scoped` | `(preKey: string) => { hasKey(), t() }` | Creates a scoped translator with a namespace prefix |
131
186
 
132
187
  **translator.t(key, replacements?)**
133
188
 
@@ -135,26 +190,9 @@ translator.t("notification", { name: "John", count: 5 }); // > John has 5 messag
135
190
  - Supports nested keys
136
191
  - Supports both string and rich replacements
137
192
 
138
- **translator.scope(preKey)**
193
+ **translator.scoped(preKey)**
139
194
 
140
195
  - Returns a scoped translator instance based on a message subtree
141
196
  - Useful for organizing large sets of translations with shared prefixes
142
197
 
143
198
  ---
144
-
145
- ## Project Structure
146
-
147
- ```bash
148
- src/
149
- β”œβ”€β”€ index.ts # Main entry point and API
150
- β”œβ”€β”€ create-translator.ts # Translator factory function
151
- β”œβ”€β”€ methods/ # Helper methods for locale, messages, keys, etc.
152
- β”‚ β”œβ”€β”€ get-locale/
153
- β”‚ β”œβ”€β”€ set-locale/
154
- β”‚ β”œβ”€β”€ get-messages/
155
- β”‚ └── translate/
156
- β”‚ β”œβ”€β”€ has-key/
157
- β”‚ β”œβ”€β”€ scoped/
158
- β”œβ”€β”€ types/ # Type definitions
159
- └── utils/ # Utility functions
160
- ```