i18n-keyless-node 1.11.0 → 1.11.2

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "i18n-keyless-node",
3
3
  "private": false,
4
- "version": "1.11.0",
4
+ "version": "1.11.2",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -1,5 +1,4 @@
1
- import { queue, getTranslationCore, } from "i18n-keyless-core";
2
- import { api } from "i18n-keyless-core/api";
1
+ import { queue, getTranslationCore, api, } from "i18n-keyless-core";
3
2
  import packageJson from "./package.json";
4
3
  const store = {
5
4
  translations: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "i18n-keyless-node",
3
3
  "private": false,
4
- "version": "1.11.0",
4
+ "version": "1.11.2",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -1,5 +0,0 @@
1
- export declare const api: {
2
- fetchTranslation: (url: string, options: RequestInit) => Promise<any>;
3
- fetchTranslationsForOneLanguage: (url: string, options: RequestInit) => Promise<any>;
4
- fetchAllTranslationsForAllLanguages: (url: string, options: RequestInit) => Promise<any>;
5
- };
package/dist/core/api.js DELETED
@@ -1,23 +0,0 @@
1
- export const api = {
2
- fetchTranslation: 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
- fetchTranslationsForOneLanguage: 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
- fetchAllTranslationsForAllLanguages: async (url, options) => {
17
- return fetch(url, options)
18
- .then((res) => res.json())
19
- .catch((err) => {
20
- return { ok: false, error: err.message };
21
- });
22
- },
23
- };
@@ -1,2 +0,0 @@
1
- export type { Lang, PrimaryLang, Translations, HandleTranslateFunction, GetAllTranslationsFunction, GetAllTranslationsForAllLanguagesFunction, LanguagesConfig, LastRefresh, UniqueId, I18nKeylessRequestBody, I18nKeylessResponse, I18nKeylessAllTranslationsResponse, FetchTranslationParams, TranslationOptions, } from "./types";
2
- export { getTranslationCore, getAllTranslationsFromLanguage, queue } from "./service";
@@ -1 +0,0 @@
1
- export { getTranslationCore, getAllTranslationsFromLanguage, queue } from "./service";
@@ -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 {};
@@ -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
- }
@@ -1,22 +0,0 @@
1
- {
2
- "name": "i18n-keyless-core",
3
- "private": false,
4
- "version": "1.11.0",
5
- "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "files": [
10
- "dist"
11
- ],
12
- "scripts": {
13
- "prepublishOnly": "rm -rf ./dist && tsc --project tsconfig.json && npm pack",
14
- "test": "echo 'no test for core'",
15
- "postpublish": "rm -rf ./dist && rm *.tgz"
16
- },
17
- "devDependencies": {
18
- "@types/node": "^22.5.5",
19
- "@types/react": "^19.0.8",
20
- "@types/react-dom": "^19.0.3"
21
- }
22
- }
@@ -1,27 +0,0 @@
1
- import type { Lang, TranslationOptions, I18nKeylessResponse, FetchTranslationParams } from "./types";
2
- import MyPQueue from "./my-pqueue";
3
- export declare const queue: MyPQueue;
4
- /**
5
- * Gets a translation for the specified key from the store
6
- * @param key - The translation key (text in primary language)
7
- * @param store - The translation store containing translations and config
8
- * @param options - Optional parameters for translation retrieval
9
- * @returns The translated text or the original key if not found
10
- * @throws Error if config is not initialized
11
- */
12
- export declare function getTranslationCore(key: string, store: FetchTranslationParams, options?: TranslationOptions): string;
13
- /**
14
- * Queues a key for translation if not already translated
15
- * @param key - The text to translate
16
- * @param store - The translation store
17
- * @param options - Optional parameters for the translation process
18
- * @throws Error if config is not initialized
19
- */
20
- export declare function translateKey(key: string, store: FetchTranslationParams, options?: TranslationOptions): void;
21
- /**
22
- * Fetches all translations for a target language
23
- * @param targetLanguage - The language code to fetch translations for
24
- * @param store - The translation store
25
- * @returns Promise resolving to the translation response or void if failed
26
- */
27
- export declare function getAllTranslationsFromLanguage(targetLanguage: Lang, store: FetchTranslationParams): Promise<I18nKeylessResponse | void>;
@@ -1,163 +0,0 @@
1
- import MyPQueue from "./my-pqueue";
2
- import packageJson from "./package.json";
3
- import { api } from "./api";
4
- export const queue = new MyPQueue({ concurrency: 5 });
5
- /**
6
- * Gets a translation for the specified key from the store
7
- * @param key - The translation key (text in primary language)
8
- * @param store - The translation store containing translations and config
9
- * @param options - Optional parameters for translation retrieval
10
- * @returns The translated text or the original key if not found
11
- * @throws Error if config is not initialized
12
- */
13
- export function getTranslationCore(key, store, options) {
14
- const currentLanguage = store.currentLanguage;
15
- const config = store.config;
16
- const translations = store.translations;
17
- if (!config.API_KEY) {
18
- throw new Error("i18n-keyless: config is not initialized");
19
- }
20
- if (currentLanguage === config.languages.primary) {
21
- return key;
22
- }
23
- if (options?.forceTemporary?.[currentLanguage]) {
24
- translateKey(key, store, options);
25
- }
26
- const context = options?.context;
27
- const translation = context ? translations[`${key}__${context}`] : translations[key];
28
- if (!translation) {
29
- translateKey(key, store, options);
30
- }
31
- return translation || key;
32
- }
33
- const translating = {};
34
- /**
35
- * Queues a key for translation if not already translated
36
- * @param key - The text to translate
37
- * @param store - The translation store
38
- * @param options - Optional parameters for the translation process
39
- * @throws Error if config is not initialized
40
- */
41
- export function translateKey(key, store, options) {
42
- const currentLanguage = store.currentLanguage;
43
- const config = store.config;
44
- const translations = store.translations;
45
- const uniqueId = store.uniqueId;
46
- if (!config.API_KEY) {
47
- throw new Error("i18n-keyless: config is not initialized");
48
- }
49
- const context = options?.context;
50
- const debug = options?.debug;
51
- // if (key.length > 280) {
52
- // console.error("i18n-keyless: Key length exceeds 280 characters limit:", key);
53
- // return;
54
- // }
55
- if (!key) {
56
- return;
57
- }
58
- if (debug) {
59
- console.log("translateKey", key, context, debug);
60
- }
61
- const forceTemporaryLang = options?.forceTemporary?.[currentLanguage];
62
- const translation = context ? translations[`${key}__${context}`] : translations[key];
63
- if (translation && !forceTemporaryLang) {
64
- if (debug) {
65
- console.log("translation exists", `${key}__${context}`);
66
- }
67
- return;
68
- }
69
- queue.add(async () => {
70
- try {
71
- if (translating[key]) {
72
- return;
73
- }
74
- else {
75
- translating[key] = true;
76
- }
77
- if (config.handleTranslate) {
78
- await config.handleTranslate?.(key);
79
- }
80
- else {
81
- const body = {
82
- key,
83
- context,
84
- forceTemporary: options?.forceTemporary,
85
- languages: config.languages.supported,
86
- primaryLanguage: config.languages.primary,
87
- };
88
- const apiUrl = config.API_URL || "https://api.i18n-keyless.com";
89
- const url = `${apiUrl}/translate`;
90
- if (debug) {
91
- console.log("fetching translation", url, body);
92
- }
93
- const response = await api
94
- .fetchTranslation(url, {
95
- method: "POST",
96
- headers: {
97
- "Content-Type": "application/json",
98
- Authorization: `Bearer ${config.API_KEY}`,
99
- unique_id: uniqueId || "",
100
- Version: packageJson.version,
101
- },
102
- body: JSON.stringify(body),
103
- })
104
- .then((res) => res);
105
- if (debug) {
106
- console.log("response", response);
107
- }
108
- if (response.message) {
109
- console.warn("i18n-keyless: ", response.message);
110
- }
111
- }
112
- translating[key] = false;
113
- return;
114
- }
115
- catch (error) {
116
- console.error("i18n-keyless: Error translating key:", error);
117
- translating[key] = false;
118
- }
119
- }, { priority: 1, id: key });
120
- }
121
- /**
122
- * Fetches all translations for a target language
123
- * @param targetLanguage - The language code to fetch translations for
124
- * @param store - The translation store
125
- * @returns Promise resolving to the translation response or void if failed
126
- */
127
- export async function getAllTranslationsFromLanguage(targetLanguage, store) {
128
- const config = store.config;
129
- const lastRefresh = store.lastRefresh;
130
- const uniqueId = store.uniqueId;
131
- if (!config.API_KEY) {
132
- console.error("i18n-keyless: No config found");
133
- return;
134
- }
135
- // if (config.languages.primary === targetLanguage) {
136
- // return;
137
- // }
138
- try {
139
- const response = config.getAllTranslations
140
- ? await config.getAllTranslations()
141
- : await api
142
- .fetchTranslationsForOneLanguage(`${config.API_URL || "https://api.i18n-keyless.com"}/translate/${targetLanguage}?last_refresh=${lastRefresh}`, {
143
- method: "GET",
144
- headers: {
145
- "Content-Type": "application/json",
146
- Authorization: `Bearer ${config.API_KEY}`,
147
- Version: packageJson.version,
148
- unique_id: uniqueId || "",
149
- },
150
- })
151
- .then((res) => res);
152
- if (!response.ok) {
153
- throw new Error(response.error);
154
- }
155
- if (response.message) {
156
- console.warn("i18n-keyless: ", response.message);
157
- }
158
- return response;
159
- }
160
- catch (error) {
161
- console.error("i18n-keyless: fetch all translations error:", error);
162
- }
163
- }
@@ -1,94 +0,0 @@
1
- export type PrimaryLang = "fr" | "en";
2
- export type Lang = "fr" | "en" | "nl" | "it" | "de" | "es" | "pl" | "pt" | "ro" | "sv" | "tr" | "ja" | "cn" | "ru" | "ko" | "ar";
3
- export type Translations = Record<string, string>;
4
- export type HandleTranslateFunction = (key: string) => Promise<{
5
- ok: boolean;
6
- message: string;
7
- }>;
8
- export type GetAllTranslationsFunction = () => Promise<I18nKeylessResponse>;
9
- export type GetAllTranslationsForAllLanguagesFunction = () => Promise<I18nKeylessAllTranslationsResponse>;
10
- export type LastRefresh = string | null;
11
- export type UniqueId = string | null;
12
- export type LanguagesConfig = {
13
- /**
14
- * the language used by the developer
15
- */
16
- primary: PrimaryLang;
17
- /**
18
- * the languages supported for the user.
19
- * For now we support:
20
- * fr, nl, it, de, es, pl, pt, ro, sv, tr, ja, cn, ru, ko, ar
21
- *
22
- * If you need more, please reach out to @ambroselli_io on X/Twitter or by mail at arnaud.ambroselli.io@gmail.com
23
- */
24
- supported: Lang[];
25
- /**
26
- * if the user's langauge is not supported, the fallback language will be used
27
- */
28
- fallback?: Lang;
29
- /**
30
- * the language to use when the app is initialized
31
- */
32
- initWithDefault?: Lang;
33
- };
34
- export type TranslationOptions = {
35
- /**
36
- * The context of the translation.
37
- * Useful for ambiguous translations, like "8 heures" in French could be "8 AM" or "8 hours".
38
- * You'll find it useful when it occurs to you, don't worry :)
39
- */
40
- context?: string;
41
- /**
42
- * Could be helpful if something weird happens with this particular key.
43
- */
44
- debug?: boolean;
45
- /**
46
- * If the proposed translation from AI is not satisfactory,
47
- * you can use this field to setup your own translation.
48
- * You can leave it there forever, or remove it once your translation is saved.
49
- */
50
- forceTemporary?: Partial<Record<Lang, string>>;
51
- };
52
- export interface I18nKeylessRequestBody {
53
- key: string;
54
- context?: string;
55
- forceTemporary?: TranslationOptions["forceTemporary"];
56
- languages: LanguagesConfig["supported"];
57
- primaryLanguage: LanguagesConfig["primary"];
58
- }
59
- export interface I18nKeylessResponse {
60
- ok: boolean;
61
- data: {
62
- translations: Translations;
63
- uniqueId: UniqueId;
64
- lastRefresh: LastRefresh;
65
- };
66
- error: string;
67
- message: string;
68
- }
69
- export interface I18nKeylessAllTranslationsResponse {
70
- ok: boolean;
71
- data: {
72
- translations: Record<Lang, Translations>;
73
- uniqueId: UniqueId;
74
- lastRefresh: LastRefresh;
75
- };
76
- error: string;
77
- message: string;
78
- }
79
- export type FetchTranslationParams = {
80
- uniqueId: UniqueId;
81
- lastRefresh: LastRefresh;
82
- currentLanguage: Lang;
83
- config: {
84
- API_KEY: string;
85
- API_URL?: string;
86
- languages: LanguagesConfig;
87
- addMissingTranslations?: boolean;
88
- debug?: boolean;
89
- handleTranslate?: HandleTranslateFunction;
90
- getAllTranslations?: GetAllTranslationsFunction;
91
- getAllTranslationsForAllLanguages?: GetAllTranslationsForAllLanguagesFunction;
92
- };
93
- translations: Translations;
94
- };
@@ -1 +0,0 @@
1
- export {};
File without changes
File without changes
File without changes
File without changes
File without changes