@pyreon/i18n 0.9.0 → 0.11.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/lib/analysis/core.js.html +5406 -0
- package/lib/analysis/index.js.html +1 -1
- package/lib/core.js +249 -0
- package/lib/core.js.map +1 -0
- package/lib/devtools.js.map +1 -1
- package/lib/index.js +29 -53
- package/lib/index.js.map +1 -1
- package/lib/types/core.d.ts +142 -0
- package/lib/types/core.d.ts.map +1 -0
- package/lib/types/devtools.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +19 -7
- package/src/context.ts +5 -7
- package/src/core.ts +22 -0
- package/src/create-i18n.ts +59 -67
- package/src/devtools.ts +6 -8
- package/src/index.ts +8 -8
- package/src/interpolation.ts +4 -9
- package/src/pluralization.ts +3 -3
- package/src/tests/devtools.test.ts +57 -59
- package/src/tests/i18n.test.tsx +356 -342
- package/src/tests/setup.ts +1 -1
- package/src/trans.tsx +4 -4
- package/src/types.ts +3 -11
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createI18n } from
|
|
1
|
+
import { createI18n } from "../create-i18n"
|
|
2
2
|
import {
|
|
3
3
|
_resetDevtools,
|
|
4
4
|
getActiveI18nInstances,
|
|
@@ -7,64 +7,62 @@ import {
|
|
|
7
7
|
onI18nChange,
|
|
8
8
|
registerI18n,
|
|
9
9
|
unregisterI18n,
|
|
10
|
-
} from
|
|
10
|
+
} from "../devtools"
|
|
11
11
|
|
|
12
12
|
afterEach(() => _resetDevtools())
|
|
13
13
|
|
|
14
|
-
describe(
|
|
15
|
-
test(
|
|
14
|
+
describe("i18n devtools", () => {
|
|
15
|
+
test("getActiveI18nInstances returns empty initially", () => {
|
|
16
16
|
expect(getActiveI18nInstances()).toEqual([])
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
test(
|
|
20
|
-
const i18n = createI18n({ locale:
|
|
21
|
-
registerI18n(
|
|
22
|
-
expect(getActiveI18nInstances()).toEqual([
|
|
19
|
+
test("registerI18n makes instance visible", () => {
|
|
20
|
+
const i18n = createI18n({ locale: "en", messages: { en: { hi: "Hello" } } })
|
|
21
|
+
registerI18n("app", i18n)
|
|
22
|
+
expect(getActiveI18nInstances()).toEqual(["app"])
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
test(
|
|
26
|
-
const i18n = createI18n({ locale:
|
|
27
|
-
registerI18n(
|
|
28
|
-
expect(getI18nInstance(
|
|
25
|
+
test("getI18nInstance returns the registered instance", () => {
|
|
26
|
+
const i18n = createI18n({ locale: "en", messages: { en: { hi: "Hello" } } })
|
|
27
|
+
registerI18n("app", i18n)
|
|
28
|
+
expect(getI18nInstance("app")).toBe(i18n)
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
test(
|
|
32
|
-
expect(getI18nInstance(
|
|
31
|
+
test("getI18nInstance returns undefined for unregistered name", () => {
|
|
32
|
+
expect(getI18nInstance("nope")).toBeUndefined()
|
|
33
33
|
})
|
|
34
34
|
|
|
35
|
-
test(
|
|
36
|
-
const i18n = createI18n({ locale:
|
|
37
|
-
registerI18n(
|
|
38
|
-
unregisterI18n(
|
|
35
|
+
test("unregisterI18n removes the instance", () => {
|
|
36
|
+
const i18n = createI18n({ locale: "en" })
|
|
37
|
+
registerI18n("app", i18n)
|
|
38
|
+
unregisterI18n("app")
|
|
39
39
|
expect(getActiveI18nInstances()).toEqual([])
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
test(
|
|
42
|
+
test("getI18nSnapshot returns current state", () => {
|
|
43
43
|
const i18n = createI18n({
|
|
44
|
-
locale:
|
|
45
|
-
messages: { en: { hi:
|
|
44
|
+
locale: "en",
|
|
45
|
+
messages: { en: { hi: "Hello" }, de: { hi: "Hallo" } },
|
|
46
46
|
})
|
|
47
|
-
registerI18n(
|
|
48
|
-
const snapshot = getI18nSnapshot(
|
|
47
|
+
registerI18n("app", i18n)
|
|
48
|
+
const snapshot = getI18nSnapshot("app")
|
|
49
49
|
expect(snapshot).toBeDefined()
|
|
50
|
-
expect(snapshot!.locale).toBe(
|
|
51
|
-
expect(snapshot!.availableLocales).toEqual(
|
|
52
|
-
expect.arrayContaining(['en', 'de']),
|
|
53
|
-
)
|
|
50
|
+
expect(snapshot!.locale).toBe("en")
|
|
51
|
+
expect(snapshot!.availableLocales).toEqual(expect.arrayContaining(["en", "de"]))
|
|
54
52
|
expect(snapshot!.isLoading).toBe(false)
|
|
55
53
|
})
|
|
56
54
|
|
|
57
|
-
test(
|
|
55
|
+
test("getI18nSnapshot handles instance with non-function properties", () => {
|
|
58
56
|
// Register a plain object where properties are NOT functions
|
|
59
57
|
// This covers the false branches of typeof checks in getI18nSnapshot
|
|
60
58
|
const plainInstance = {
|
|
61
|
-
locale:
|
|
59
|
+
locale: "not-a-function",
|
|
62
60
|
availableLocales: 42,
|
|
63
61
|
loadedNamespaces: null,
|
|
64
62
|
isLoading: undefined,
|
|
65
63
|
}
|
|
66
|
-
registerI18n(
|
|
67
|
-
const snapshot = getI18nSnapshot(
|
|
64
|
+
registerI18n("plain", plainInstance)
|
|
65
|
+
const snapshot = getI18nSnapshot("plain")
|
|
68
66
|
expect(snapshot).toBeDefined()
|
|
69
67
|
expect(snapshot!.locale).toBeUndefined()
|
|
70
68
|
expect(snapshot!.availableLocales).toEqual([])
|
|
@@ -72,56 +70,56 @@ describe('i18n devtools', () => {
|
|
|
72
70
|
expect(snapshot!.isLoading).toBe(false)
|
|
73
71
|
})
|
|
74
72
|
|
|
75
|
-
test(
|
|
76
|
-
const i18n = createI18n({ locale:
|
|
77
|
-
registerI18n(
|
|
78
|
-
i18n.locale.set(
|
|
79
|
-
const snapshot = getI18nSnapshot(
|
|
80
|
-
expect(snapshot!.locale).toBe(
|
|
73
|
+
test("getI18nSnapshot reflects locale change", () => {
|
|
74
|
+
const i18n = createI18n({ locale: "en", messages: { en: {}, de: {} } })
|
|
75
|
+
registerI18n("app", i18n)
|
|
76
|
+
i18n.locale.set("de")
|
|
77
|
+
const snapshot = getI18nSnapshot("app")
|
|
78
|
+
expect(snapshot!.locale).toBe("de")
|
|
81
79
|
})
|
|
82
80
|
|
|
83
|
-
test(
|
|
84
|
-
expect(getI18nSnapshot(
|
|
81
|
+
test("getI18nSnapshot returns undefined for unregistered name", () => {
|
|
82
|
+
expect(getI18nSnapshot("nope")).toBeUndefined()
|
|
85
83
|
})
|
|
86
84
|
|
|
87
|
-
test(
|
|
85
|
+
test("onI18nChange fires on register", () => {
|
|
88
86
|
const calls: number[] = []
|
|
89
87
|
const unsub = onI18nChange(() => calls.push(1))
|
|
90
88
|
|
|
91
|
-
registerI18n(
|
|
89
|
+
registerI18n("app", createI18n({ locale: "en" }))
|
|
92
90
|
expect(calls.length).toBe(1)
|
|
93
91
|
|
|
94
92
|
unsub()
|
|
95
93
|
})
|
|
96
94
|
|
|
97
|
-
test(
|
|
98
|
-
registerI18n(
|
|
95
|
+
test("onI18nChange fires on unregister", () => {
|
|
96
|
+
registerI18n("app", createI18n({ locale: "en" }))
|
|
99
97
|
|
|
100
98
|
const calls: number[] = []
|
|
101
99
|
const unsub = onI18nChange(() => calls.push(1))
|
|
102
|
-
unregisterI18n(
|
|
100
|
+
unregisterI18n("app")
|
|
103
101
|
expect(calls.length).toBe(1)
|
|
104
102
|
|
|
105
103
|
unsub()
|
|
106
104
|
})
|
|
107
105
|
|
|
108
|
-
test(
|
|
106
|
+
test("onI18nChange unsubscribe stops notifications", () => {
|
|
109
107
|
const calls: number[] = []
|
|
110
108
|
const unsub = onI18nChange(() => calls.push(1))
|
|
111
109
|
unsub()
|
|
112
110
|
|
|
113
|
-
registerI18n(
|
|
111
|
+
registerI18n("app", createI18n({ locale: "en" }))
|
|
114
112
|
expect(calls.length).toBe(0)
|
|
115
113
|
})
|
|
116
114
|
|
|
117
|
-
test(
|
|
118
|
-
registerI18n(
|
|
119
|
-
registerI18n(
|
|
120
|
-
expect(getActiveI18nInstances().sort()).toEqual([
|
|
115
|
+
test("multiple instances are tracked", () => {
|
|
116
|
+
registerI18n("app", createI18n({ locale: "en" }))
|
|
117
|
+
registerI18n("admin", createI18n({ locale: "en" }))
|
|
118
|
+
expect(getActiveI18nInstances().sort()).toEqual(["admin", "app"])
|
|
121
119
|
})
|
|
122
120
|
|
|
123
|
-
test(
|
|
124
|
-
const instance = createI18n({ locale:
|
|
121
|
+
test("getI18nInstance cleans up and returns undefined when WeakRef is dead", () => {
|
|
122
|
+
const instance = createI18n({ locale: "en" })
|
|
125
123
|
const originalWeakRef = globalThis.WeakRef
|
|
126
124
|
let mockDerefResult: object | undefined = instance
|
|
127
125
|
const MockWeakRef = class {
|
|
@@ -132,18 +130,18 @@ describe('i18n devtools', () => {
|
|
|
132
130
|
globalThis.WeakRef = MockWeakRef as any
|
|
133
131
|
|
|
134
132
|
_resetDevtools()
|
|
135
|
-
registerI18n(
|
|
136
|
-
expect(getI18nInstance(
|
|
133
|
+
registerI18n("mock-instance", instance)
|
|
134
|
+
expect(getI18nInstance("mock-instance")).toBe(instance)
|
|
137
135
|
|
|
138
136
|
// Simulate GC
|
|
139
137
|
mockDerefResult = undefined
|
|
140
|
-
expect(getI18nInstance(
|
|
138
|
+
expect(getI18nInstance("mock-instance")).toBeUndefined()
|
|
141
139
|
|
|
142
140
|
globalThis.WeakRef = originalWeakRef
|
|
143
141
|
})
|
|
144
142
|
|
|
145
|
-
test(
|
|
146
|
-
const instance = createI18n({ locale:
|
|
143
|
+
test("getActiveI18nInstances cleans up garbage-collected WeakRefs", () => {
|
|
144
|
+
const instance = createI18n({ locale: "en" })
|
|
147
145
|
const originalWeakRef = globalThis.WeakRef
|
|
148
146
|
let mockDerefResult: object | undefined = instance
|
|
149
147
|
const MockWeakRef = class {
|
|
@@ -154,8 +152,8 @@ describe('i18n devtools', () => {
|
|
|
154
152
|
globalThis.WeakRef = MockWeakRef as any
|
|
155
153
|
|
|
156
154
|
_resetDevtools()
|
|
157
|
-
registerI18n(
|
|
158
|
-
expect(getActiveI18nInstances()).toEqual([
|
|
155
|
+
registerI18n("gc-instance", instance)
|
|
156
|
+
expect(getActiveI18nInstances()).toEqual(["gc-instance"])
|
|
159
157
|
|
|
160
158
|
// Simulate GC
|
|
161
159
|
mockDerefResult = undefined
|