kotori 6.1.2 → 6.1.4
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 +18 -7
- package/dist/index.cjs +5 -7
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +5 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,10 +8,13 @@
|
|
|
8
8
|
<img src="https://img.shields.io/badge/bundle%20size-0.28kB-emerald" alt="Bundle Size">
|
|
9
9
|
<a href="https://github.com/tylim88/Kotori/blob/main/LICENSE"><img src="https://img.shields.io/github/license/tylim88/Kotori?color=blue" alt="License"></a>
|
|
10
10
|
<img src="https://img.shields.io/badge/dependencies-0-success" alt="Dependencies">
|
|
11
|
+
<a href="https://snyk.io/test/github/tylim88/Kotori">
|
|
12
|
+
<img src="https://snyk.io/test/github/tylim88/Kotori/badge.svg" alt="Snyk Vulnerabilities for npm package">
|
|
13
|
+
</a>
|
|
11
14
|
</p>
|
|
12
15
|
|
|
13
16
|
<p align="center">
|
|
14
|
-
🕊️ Kotori is a zero-config, fully type-safe, and modular internationalization library for React that compiles down to just 0.
|
|
17
|
+
🕊️ Kotori is a zero-config, fully type-safe, and modular internationalization library for React that compiles down to just 0.28kB. No JSON, no external CLI tools, no codegen—just live type inference from your strings.
|
|
15
18
|
</p>
|
|
16
19
|
|
|
17
20
|
```ts
|
|
@@ -55,13 +58,13 @@ const Component = () => {
|
|
|
55
58
|
- No JSON
|
|
56
59
|
- No dependencies
|
|
57
60
|
- No build step
|
|
58
|
-
- 0.
|
|
61
|
+
- 0.28kB minified and gzipped
|
|
59
62
|
- Modular and tree-shakeable
|
|
60
63
|
- Language change in one page rerenders all pages
|
|
61
64
|
- Variables typed and inferred from string literals — no more string typos
|
|
62
65
|
- Maximum type safety with minimum types
|
|
63
66
|
|
|
64
|
-
Demo: <https://
|
|
67
|
+
Demo: <https://github.com/tylim88/kotori-demo>
|
|
65
68
|
|
|
66
69
|
## Installation
|
|
67
70
|
|
|
@@ -81,7 +84,7 @@ export const { useT, d, setLanguage } = kotori({
|
|
|
81
84
|
secondaries: ['zh', 'ja', 'ms'],
|
|
82
85
|
})
|
|
83
86
|
|
|
84
|
-
// you can define your dicts in the same file or separate them by component, it's up to you
|
|
87
|
+
// you can define your dicts in the same file/folder or separate them by component, it's up to you
|
|
85
88
|
export const intro = d({
|
|
86
89
|
en: 'my name is {{name}}, I am {{age}} years old.',
|
|
87
90
|
zh: '我叫{{name}},我今年{{age}}岁了。',
|
|
@@ -163,7 +166,7 @@ export const Page2 = () => {
|
|
|
163
166
|
|
|
164
167
|

|
|
165
168
|
|
|
166
|
-
### `kotori(options)` (0.
|
|
169
|
+
### `kotori(options)` (0.28kB)
|
|
167
170
|
|
|
168
171
|
Creates a scoped i18n instance.
|
|
169
172
|
|
|
@@ -248,9 +251,16 @@ Detects the user's preferred language from browser settings and sets it on the k
|
|
|
248
251
|
|
|
249
252
|
```ts
|
|
250
253
|
import { detectLanguage } from 'kotori'
|
|
251
|
-
import {
|
|
254
|
+
import { kotori } from 'kotori'
|
|
255
|
+
|
|
256
|
+
const i18n = kotori({
|
|
257
|
+
primary: 'en',
|
|
258
|
+
secondaries: ['zh', 'ja', 'ms'],
|
|
259
|
+
})
|
|
252
260
|
|
|
253
261
|
detectLanguage(i18n)
|
|
262
|
+
|
|
263
|
+
export const { useT, d, setLanguage } = i18n
|
|
254
264
|
```
|
|
255
265
|
|
|
256
266
|
| option | type | default | description |
|
|
@@ -289,7 +299,8 @@ kotori({ primary: 'klingon', secondaries: ['zh'] }) // ❌ compile error
|
|
|
289
299
|
## Tips
|
|
290
300
|
|
|
291
301
|
- If you plan to add new languages frequently, consider colocating all your dicts in a single file or multiple files in one folder. It is easier to copy the entire files and hand it to an AI to translate.
|
|
292
|
-
- If your supported languages are fixed, consider splitting dicts by page or component.
|
|
302
|
+
- If your supported languages are fixed, consider splitting dicts by page or component. This keeps translations close to the code that uses them and makes them easier to maintain.
|
|
303
|
+
- For large or rarely used components, you can also reduce your bundle size by dynamically importing them only when they are needed on the page.
|
|
293
304
|
|
|
294
305
|
## Roadmap
|
|
295
306
|
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,8 @@ let react = require("react");
|
|
|
35
35
|
*
|
|
36
36
|
* detectLanguage(i18n, { fallbackToSubtag: false })
|
|
37
37
|
* // browser: ['zh-CN'] → no exact match → no-op, stays 'en'
|
|
38
|
+
*
|
|
39
|
+
* export const { useT, d, setLanguage } = i18n
|
|
38
40
|
* ```
|
|
39
41
|
*
|
|
40
42
|
* @example
|
|
@@ -110,7 +112,7 @@ const kotori = (config) => {
|
|
|
110
112
|
* )
|
|
111
113
|
* }
|
|
112
114
|
*/
|
|
113
|
-
const t = (dictionary, ...args) => (dictionary().d[snapshot.language]
|
|
115
|
+
const t = (dictionary, ...args) => (dictionary().d[snapshot.language] + "").replace(/\{\{\s*([\w-]+)\s*\}\}/g, (_, key) => args[0]?.[key] + "");
|
|
114
116
|
let snapshot = {
|
|
115
117
|
language: config.primary,
|
|
116
118
|
t
|
|
@@ -145,15 +147,11 @@ const kotori = (config) => {
|
|
|
145
147
|
language,
|
|
146
148
|
t: (...args) => t(...args)
|
|
147
149
|
};
|
|
148
|
-
listeners.forEach((listener) =>
|
|
149
|
-
listener();
|
|
150
|
-
});
|
|
150
|
+
listeners.forEach((listener) => listener());
|
|
151
151
|
};
|
|
152
152
|
const subscribe = (listener) => {
|
|
153
153
|
listeners.add(listener);
|
|
154
|
-
return () =>
|
|
155
|
-
listeners.delete(listener);
|
|
156
|
-
};
|
|
154
|
+
return () => listeners.delete(listener);
|
|
157
155
|
};
|
|
158
156
|
return {
|
|
159
157
|
config,
|
package/dist/index.d.cts
CHANGED
|
@@ -208,6 +208,8 @@ declare const kotori: <const Primary extends BCP47LanguageTagNameWithSubTag, con
|
|
|
208
208
|
*
|
|
209
209
|
* detectLanguage(i18n, { fallbackToSubtag: false })
|
|
210
210
|
* // browser: ['zh-CN'] → no exact match → no-op, stays 'en'
|
|
211
|
+
*
|
|
212
|
+
* export const { useT, d, setLanguage } = i18n
|
|
211
213
|
* ```
|
|
212
214
|
*
|
|
213
215
|
* @example
|
package/dist/index.d.mts
CHANGED
|
@@ -208,6 +208,8 @@ declare const kotori: <const Primary extends BCP47LanguageTagNameWithSubTag, con
|
|
|
208
208
|
*
|
|
209
209
|
* detectLanguage(i18n, { fallbackToSubtag: false })
|
|
210
210
|
* // browser: ['zh-CN'] → no exact match → no-op, stays 'en'
|
|
211
|
+
*
|
|
212
|
+
* export const { useT, d, setLanguage } = i18n
|
|
211
213
|
* ```
|
|
212
214
|
*
|
|
213
215
|
* @example
|
package/dist/index.mjs
CHANGED
|
@@ -34,6 +34,8 @@ import { useSyncExternalStore } from "react";
|
|
|
34
34
|
*
|
|
35
35
|
* detectLanguage(i18n, { fallbackToSubtag: false })
|
|
36
36
|
* // browser: ['zh-CN'] → no exact match → no-op, stays 'en'
|
|
37
|
+
*
|
|
38
|
+
* export const { useT, d, setLanguage } = i18n
|
|
37
39
|
* ```
|
|
38
40
|
*
|
|
39
41
|
* @example
|
|
@@ -109,7 +111,7 @@ const kotori = (config) => {
|
|
|
109
111
|
* )
|
|
110
112
|
* }
|
|
111
113
|
*/
|
|
112
|
-
const t = (dictionary, ...args) => (dictionary().d[snapshot.language]
|
|
114
|
+
const t = (dictionary, ...args) => (dictionary().d[snapshot.language] + "").replace(/\{\{\s*([\w-]+)\s*\}\}/g, (_, key) => args[0]?.[key] + "");
|
|
113
115
|
let snapshot = {
|
|
114
116
|
language: config.primary,
|
|
115
117
|
t
|
|
@@ -144,15 +146,11 @@ const kotori = (config) => {
|
|
|
144
146
|
language,
|
|
145
147
|
t: (...args) => t(...args)
|
|
146
148
|
};
|
|
147
|
-
listeners.forEach((listener) =>
|
|
148
|
-
listener();
|
|
149
|
-
});
|
|
149
|
+
listeners.forEach((listener) => listener());
|
|
150
150
|
};
|
|
151
151
|
const subscribe = (listener) => {
|
|
152
152
|
listeners.add(listener);
|
|
153
|
-
return () =>
|
|
154
|
-
listeners.delete(listener);
|
|
155
|
-
};
|
|
153
|
+
return () => listeners.delete(listener);
|
|
156
154
|
};
|
|
157
155
|
return {
|
|
158
156
|
config,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kotori",
|
|
3
3
|
"description": "0.29kB Strongly-typed and tree-shakeable internationalization library for React",
|
|
4
|
-
"version": "6.1.
|
|
4
|
+
"version": "6.1.4",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"setup": "rm -rf node_modules && npm i && git init && husky",
|
|
7
7
|
"prepublishOnly": "npm i && npx tsc && npm run build",
|