i18n-keyless-react 1.9.6 → 1.10.1
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/dist/__tests__/store.test.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/package.json +1 -1
- package/dist/store.d.ts +7 -1
- package/dist/store.js +42 -7
- package/dist/utils.d.ts +0 -7
- package/dist/utils.js +0 -39
- package/package.json +1 -1
- package/dist/api.d.ts +0 -4
- package/dist/api.js +0 -16
- package/dist/my-pqueue.d.ts +0 -24
- package/dist/my-pqueue.js +0 -108
|
@@ -19,7 +19,7 @@ vi.mock("../store", async () => {
|
|
|
19
19
|
useCurrentLanguage: vi.fn(),
|
|
20
20
|
getTranslationCore: vi.fn(),
|
|
21
21
|
setCurrentLanguage: vi.fn(),
|
|
22
|
-
|
|
22
|
+
getAllTranslationsFromLanguage: vi.fn(),
|
|
23
23
|
clearI18nKeylessStorage: vi.fn(),
|
|
24
24
|
init: actual.init,
|
|
25
25
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { I18nKeylessText } from "./I18nKeylessText";
|
|
|
2
2
|
export { init, setCurrentLanguage, useCurrentLanguage, getTranslation } from "./store";
|
|
3
3
|
export { clearI18nKeylessStorage } from "./utils";
|
|
4
4
|
export type { I18nKeylessTextProps } from "./I18nKeylessText";
|
|
5
|
-
export { type I18nConfig, type Lang, type PrimaryLang, type Translations, type TranslationStore, type TranslationStoreState, type I18nKeylessRequestBody, type I18nKeylessResponse, type TranslationOptions,
|
|
5
|
+
export { type I18nConfig, type Lang, type PrimaryLang, type Translations, type TranslationStore, type TranslationStoreState, type I18nKeylessRequestBody, type I18nKeylessResponse, type TranslationOptions, getAllTranslationsFromLanguage, validateLanguage, queue, } from "i18n-keyless-core";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { I18nKeylessText } from "./I18nKeylessText";
|
|
2
2
|
export { init, setCurrentLanguage, useCurrentLanguage, getTranslation } from "./store";
|
|
3
3
|
export { clearI18nKeylessStorage } from "./utils";
|
|
4
|
-
export {
|
|
4
|
+
export { getAllTranslationsFromLanguage, validateLanguage, queue, } from "i18n-keyless-core";
|
package/dist/package.json
CHANGED
package/dist/store.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { type I18nConfig, type Lang, type TranslationStore, type TranslationOptions } from "i18n-keyless-core";
|
|
2
2
|
export declare const useI18nKeyless: import("zustand").UseBoundStore<import("zustand").StoreApi<TranslationStore>>;
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Initializes the i18n configuration with defaults and validation
|
|
5
|
+
* @param newConfig - The configuration object to initialize
|
|
6
|
+
* @returns The validated and completed configuration
|
|
7
|
+
* @throws Error if required configuration properties are missing
|
|
8
|
+
*/
|
|
9
|
+
export declare function init(newConfig: Omit<I18nConfig, "getAllTranslationsForAllLanguages">): Promise<void>;
|
|
4
10
|
export declare function useCurrentLanguage(): Lang | null;
|
|
5
11
|
export declare function getTranslation(key: string, options?: TranslationOptions): string;
|
|
6
12
|
export declare function setCurrentLanguage(lang: I18nConfig["languages"]["supported"][number]): void;
|
package/dist/store.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { queue,
|
|
1
|
+
import { queue, getAllTranslationsFromLanguage, validateLanguage, getTranslationCore, } from "i18n-keyless-core";
|
|
2
2
|
import { create } from "zustand";
|
|
3
|
-
import {
|
|
3
|
+
import { storeKeys, setItem, getItem, clearI18nKeylessStorage } from "./utils";
|
|
4
4
|
queue.on("empty", () => {
|
|
5
5
|
// when each word is translated, fetch the translations for the current language
|
|
6
6
|
const store = useI18nKeyless.getState();
|
|
7
|
-
|
|
7
|
+
getAllTranslationsFromLanguage(store.currentLanguage, store).then(store.setTranslations);
|
|
8
8
|
});
|
|
9
9
|
export const useI18nKeyless = create((set, get) => ({
|
|
10
10
|
uniqueId: null,
|
|
@@ -58,7 +58,7 @@ export const useI18nKeyless = create((set, get) => ({
|
|
|
58
58
|
}
|
|
59
59
|
// Only fetch translations if the new language is not the primary language
|
|
60
60
|
if (lang !== config.languages.primary) {
|
|
61
|
-
await
|
|
61
|
+
await getAllTranslationsFromLanguage(lang, get()).then(get().setTranslations);
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
}));
|
|
@@ -102,12 +102,47 @@ async function hydrate() {
|
|
|
102
102
|
useI18nKeyless.setState({ lastRefresh: lastRefresh });
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Initializes the i18n configuration with defaults and validation
|
|
107
|
+
* @param newConfig - The configuration object to initialize
|
|
108
|
+
* @returns The validated and completed configuration
|
|
109
|
+
* @throws Error if required configuration properties are missing
|
|
110
|
+
*/
|
|
105
111
|
export async function init(newConfig) {
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
if (!newConfig.languages) {
|
|
113
|
+
throw new Error("i18n-keyless: languages is required");
|
|
114
|
+
}
|
|
115
|
+
if (!newConfig.languages.primary) {
|
|
116
|
+
throw new Error("i18n-keyless: primary is required");
|
|
117
|
+
}
|
|
118
|
+
if (!newConfig.languages.initWithDefault) {
|
|
119
|
+
newConfig.languages.initWithDefault = newConfig.languages.primary;
|
|
120
|
+
}
|
|
121
|
+
if (!newConfig.languages.fallback) {
|
|
122
|
+
newConfig.languages.fallback = newConfig.languages.primary;
|
|
123
|
+
}
|
|
124
|
+
if (!newConfig.languages.supported.includes(newConfig.languages.initWithDefault)) {
|
|
125
|
+
newConfig.languages.supported.push(newConfig.languages.initWithDefault);
|
|
126
|
+
}
|
|
127
|
+
if (!newConfig.storage) {
|
|
128
|
+
console.log("storage is required", newConfig.storage);
|
|
129
|
+
throw new Error("i18n-keyless: storage is required. You can use react-native-mmkv, @react-native-async-storage/async-storage, or window.localStorage, or any storage that has a getItem, setItem, removeItem, or get, set, and remove method");
|
|
130
|
+
}
|
|
131
|
+
if (!newConfig.getAllTranslations || !newConfig.handleTranslate) {
|
|
132
|
+
if (!newConfig.API_KEY) {
|
|
133
|
+
if (!newConfig.API_URL) {
|
|
134
|
+
throw new Error("i18n-keyless: you didn't provide an API_KEY nor an API_URL nor a handleTranslate + getAllTranslations function. You need to provide one of them to make i18n-keyless work");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (newConfig.addMissingTranslations !== false) {
|
|
139
|
+
// default to true
|
|
140
|
+
newConfig.addMissingTranslations = true;
|
|
141
|
+
}
|
|
142
|
+
useI18nKeyless.setState({ config: newConfig });
|
|
108
143
|
await hydrate();
|
|
109
144
|
const currentLanguage = useI18nKeyless.getState().currentLanguage;
|
|
110
|
-
|
|
145
|
+
newConfig.onInit?.(currentLanguage);
|
|
111
146
|
}
|
|
112
147
|
export function useCurrentLanguage() {
|
|
113
148
|
const currentLanguage = useI18nKeyless((state) => state.currentLanguage);
|
package/dist/utils.d.ts
CHANGED
|
@@ -31,13 +31,6 @@ export declare function setItem(key: string, value: string, storage: I18nConfig[
|
|
|
31
31
|
* @throws Error if storage is not initialized
|
|
32
32
|
*/
|
|
33
33
|
export declare function deleteItem(key: string, storage: I18nConfig["storage"]): Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* Initializes the i18n configuration with defaults and validation
|
|
36
|
-
* @param newConfig - The configuration object to initialize
|
|
37
|
-
* @returns The validated and completed configuration
|
|
38
|
-
* @throws Error if required configuration properties are missing
|
|
39
|
-
*/
|
|
40
|
-
export declare function init(newConfig: I18nConfig): Promise<I18nConfig>;
|
|
41
34
|
/**
|
|
42
35
|
* Clears all i18n-keyless data from storage
|
|
43
36
|
* @param storage - The storage implementation to clear
|
package/dist/utils.js
CHANGED
|
@@ -90,45 +90,6 @@ export async function deleteItem(key, storage) {
|
|
|
90
90
|
console.error("i18n-keyless: Error deleting item:", error);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Initializes the i18n configuration with defaults and validation
|
|
95
|
-
* @param newConfig - The configuration object to initialize
|
|
96
|
-
* @returns The validated and completed configuration
|
|
97
|
-
* @throws Error if required configuration properties are missing
|
|
98
|
-
*/
|
|
99
|
-
export async function init(newConfig) {
|
|
100
|
-
if (!newConfig.languages) {
|
|
101
|
-
throw new Error("i18n-keyless: languages is required");
|
|
102
|
-
}
|
|
103
|
-
if (!newConfig.languages.primary) {
|
|
104
|
-
throw new Error("i18n-keyless: primary is required");
|
|
105
|
-
}
|
|
106
|
-
if (!newConfig.languages.initWithDefault) {
|
|
107
|
-
newConfig.languages.initWithDefault = newConfig.languages.primary;
|
|
108
|
-
}
|
|
109
|
-
if (!newConfig.languages.fallback) {
|
|
110
|
-
newConfig.languages.fallback = newConfig.languages.primary;
|
|
111
|
-
}
|
|
112
|
-
if (!newConfig.languages.supported.includes(newConfig.languages.initWithDefault)) {
|
|
113
|
-
newConfig.languages.supported.push(newConfig.languages.initWithDefault);
|
|
114
|
-
}
|
|
115
|
-
if (!newConfig.storage) {
|
|
116
|
-
console.log("storage is required", newConfig.storage);
|
|
117
|
-
throw new Error("i18n-keyless: storage is required. You can use react-native-mmkv, @react-native-async-storage/async-storage, or window.localStorage, or any storage that has a getItem, setItem, removeItem, or get, set, and remove method");
|
|
118
|
-
}
|
|
119
|
-
if (!newConfig.getAllTranslations || !newConfig.handleTranslate) {
|
|
120
|
-
if (!newConfig.API_KEY) {
|
|
121
|
-
if (!newConfig.API_URL) {
|
|
122
|
-
throw new Error("i18n-keyless: you didn't provide an API_KEY nor an API_URL nor a handleTranslate + getAllTranslations function. You need to provide one of them to make i18n-keyless work");
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
if (newConfig.addMissingTranslations !== false) {
|
|
127
|
-
// default to true
|
|
128
|
-
newConfig.addMissingTranslations = true;
|
|
129
|
-
}
|
|
130
|
-
return newConfig;
|
|
131
|
-
}
|
|
132
93
|
/**
|
|
133
94
|
* Clears all i18n-keyless data from storage
|
|
134
95
|
* @param storage - The storage implementation to clear
|
package/package.json
CHANGED
package/dist/api.d.ts
DELETED
package/dist/api.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export const api = {
|
|
2
|
-
fetchTranslations: async (url, options) => {
|
|
3
|
-
return fetch(url, options)
|
|
4
|
-
.then((res) => res.json())
|
|
5
|
-
.catch((err) => {
|
|
6
|
-
return { ok: false, error: err.message };
|
|
7
|
-
});
|
|
8
|
-
},
|
|
9
|
-
fetchTranslation: async (url, options) => {
|
|
10
|
-
return fetch(url, options)
|
|
11
|
-
.then((res) => res.json())
|
|
12
|
-
.catch((err) => {
|
|
13
|
-
return { ok: false, error: err.message };
|
|
14
|
-
});
|
|
15
|
-
},
|
|
16
|
-
};
|
package/dist/my-pqueue.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
type Task<T> = () => Promise<T>;
|
|
2
|
-
declare class EventEmitter {
|
|
3
|
-
private events;
|
|
4
|
-
on(event: string, callback: () => void): void;
|
|
5
|
-
off(event: string, callback: () => void): void;
|
|
6
|
-
emit(event: string): void;
|
|
7
|
-
}
|
|
8
|
-
export default class MyPQueue extends EventEmitter {
|
|
9
|
-
private queue;
|
|
10
|
-
private pending;
|
|
11
|
-
private readonly concurrency;
|
|
12
|
-
private processing;
|
|
13
|
-
constructor(options?: {
|
|
14
|
-
concurrency?: number;
|
|
15
|
-
});
|
|
16
|
-
add<T>(task: Task<T>, options?: {
|
|
17
|
-
priority?: number;
|
|
18
|
-
id?: string;
|
|
19
|
-
}): Promise<T>;
|
|
20
|
-
private processNext;
|
|
21
|
-
get size(): number;
|
|
22
|
-
get isPaused(): boolean;
|
|
23
|
-
}
|
|
24
|
-
export {};
|
package/dist/my-pqueue.js
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
// https://github.com/sindresorhus/p-queue/issues/145#issuecomment-882068004
|
|
2
|
-
// p-queu import is broken, so here is the smalle implementation of it
|
|
3
|
-
class EventEmitter {
|
|
4
|
-
constructor() {
|
|
5
|
-
Object.defineProperty(this, "events", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
configurable: true,
|
|
8
|
-
writable: true,
|
|
9
|
-
value: {}
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
on(event, callback) {
|
|
13
|
-
if (!this.events[event]) {
|
|
14
|
-
this.events[event] = [];
|
|
15
|
-
}
|
|
16
|
-
this.events[event].push(callback);
|
|
17
|
-
}
|
|
18
|
-
off(event, callback) {
|
|
19
|
-
if (!this.events[event])
|
|
20
|
-
return;
|
|
21
|
-
this.events[event] = this.events[event].filter((cb) => cb !== callback);
|
|
22
|
-
}
|
|
23
|
-
emit(event) {
|
|
24
|
-
if (!this.events[event])
|
|
25
|
-
return;
|
|
26
|
-
this.events[event].forEach((callback) => callback());
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export default class MyPQueue extends EventEmitter {
|
|
30
|
-
constructor(options = {}) {
|
|
31
|
-
super();
|
|
32
|
-
Object.defineProperty(this, "queue", {
|
|
33
|
-
enumerable: true,
|
|
34
|
-
configurable: true,
|
|
35
|
-
writable: true,
|
|
36
|
-
value: []
|
|
37
|
-
});
|
|
38
|
-
Object.defineProperty(this, "pending", {
|
|
39
|
-
enumerable: true,
|
|
40
|
-
configurable: true,
|
|
41
|
-
writable: true,
|
|
42
|
-
value: 0
|
|
43
|
-
});
|
|
44
|
-
Object.defineProperty(this, "concurrency", {
|
|
45
|
-
enumerable: true,
|
|
46
|
-
configurable: true,
|
|
47
|
-
writable: true,
|
|
48
|
-
value: void 0
|
|
49
|
-
});
|
|
50
|
-
Object.defineProperty(this, "processing", {
|
|
51
|
-
enumerable: true,
|
|
52
|
-
configurable: true,
|
|
53
|
-
writable: true,
|
|
54
|
-
value: false
|
|
55
|
-
});
|
|
56
|
-
this.concurrency = options.concurrency ?? Infinity;
|
|
57
|
-
}
|
|
58
|
-
add(task, options = {}) {
|
|
59
|
-
const { priority = 0, id = String(Date.now()) } = options;
|
|
60
|
-
// If task with same ID exists, return its promise
|
|
61
|
-
const existingTask = this.queue.find((item) => item.id === id);
|
|
62
|
-
if (existingTask) {
|
|
63
|
-
return existingTask.task();
|
|
64
|
-
}
|
|
65
|
-
return new Promise((resolve, reject) => {
|
|
66
|
-
const wrappedTask = async () => {
|
|
67
|
-
try {
|
|
68
|
-
const result = await task();
|
|
69
|
-
resolve(result);
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
reject(error);
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
this.pending--;
|
|
78
|
-
this.processNext();
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
this.queue.push({ task: wrappedTask, priority, id });
|
|
82
|
-
this.queue.sort((a, b) => b.priority - a.priority);
|
|
83
|
-
this.processNext();
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
async processNext() {
|
|
87
|
-
if (this.processing)
|
|
88
|
-
return;
|
|
89
|
-
this.processing = true;
|
|
90
|
-
while (this.queue.length > 0 && this.pending < this.concurrency) {
|
|
91
|
-
const task = this.queue.shift();
|
|
92
|
-
if (task) {
|
|
93
|
-
this.pending++;
|
|
94
|
-
task.task().catch(() => { });
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
this.processing = false;
|
|
98
|
-
if (this.queue.length === 0 && this.pending === 0) {
|
|
99
|
-
this.emit("empty");
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
get size() {
|
|
103
|
-
return this.queue.length;
|
|
104
|
-
}
|
|
105
|
-
get isPaused() {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
}
|