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 +119 -81
- package/dist/index.cjs +205 -155
- package/dist/index.d.cts +339 -221
- package/dist/index.d.ts +339 -221
- package/dist/index.js +204 -154
- package/package.json +19 -10
package/README.md
CHANGED
|
@@ -1,28 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">Intor Translator</h1>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
+
[](https://www.npmjs.com/package/intor-translator)
|
|
12
|
+
[](https://bundlephobia.com/package/intor-translator)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
[](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
|
-
- π
|
|
18
|
-
- π¨ Rich replacement
|
|
19
|
-
- π Graceful loading
|
|
20
|
-
- π§ Configurable handlers for fallback, loading, and
|
|
21
|
-
- π§© Scoped
|
|
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 {
|
|
53
|
+
import { Translator } from "intor-translator";
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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"); //
|
|
57
|
-
translator.t("greeting", { name: "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 =
|
|
77
|
+
const translator = new Translator({
|
|
68
78
|
locale: "en",
|
|
69
79
|
messages: {
|
|
70
80
|
en: {
|
|
71
|
-
|
|
81
|
+
welcome: "Welcome back, {name}",
|
|
72
82
|
},
|
|
73
83
|
zh: {
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
welcome: "ζ‘θΏεδΎοΌ{name}",
|
|
85
|
+
notification: "δ½ ζ {count} εζ°ιη₯",
|
|
76
86
|
},
|
|
77
87
|
},
|
|
78
|
-
fallbackLocales: { en: ["zh"] }, //
|
|
79
|
-
placeholder: "
|
|
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
|
-
|
|
82
|
-
|
|
91
|
+
formatMessage: ({ locale, message }) =>
|
|
92
|
+
locale === "zh" ? `${message}γ` : `${message}.`, // Auto punctuation per locale
|
|
83
93
|
},
|
|
84
94
|
});
|
|
85
95
|
|
|
86
|
-
|
|
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
|
|
93
|
-
import {
|
|
109
|
+
import { Translator, FormatMessage } from "intor-translator";
|
|
110
|
+
import { IntlMessageFormat } from "intl-messageformat";
|
|
94
111
|
|
|
95
|
-
|
|
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
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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 }); //
|
|
114
|
-
translator.t("notification", { name: "John", count: 5 }); //
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
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.
|
|
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
|
-
```
|