i18n-keyless-react 1.13.0 → 1.14.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.
@@ -10,6 +10,7 @@ export const store = {
10
10
  },
11
11
  currentLanguage: "fr",
12
12
  translations: {},
13
+ lastUsedTranslation: {},
13
14
  uniqueId: null,
14
15
  lastRefresh: null,
15
16
  setTranslations: vi.fn(),
@@ -17,6 +18,7 @@ export const store = {
17
18
  const validated = validateLanguage(lang, store.config);
18
19
  store.currentLanguage = validated;
19
20
  }),
21
+ sendTranslationsUsage: vi.fn(),
20
22
  };
21
23
  // Create a function that supports the selector pattern
22
24
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
package/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "i18n-keyless-react",
3
3
  "private": false,
4
- "version": "1.13.0",
4
+ "version": "1.14.2",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "postpublish": "rm -rf ./dist && rm *.tgz"
18
18
  },
19
19
  "dependencies": {
20
- "i18n-keyless-core": "1.13.0",
20
+ "i18n-keyless-core": "1.14.2",
21
21
  "zustand": "^5.0.3"
22
22
  },
23
23
  "peerDependencies": {
package/dist/store.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { queue, getAllTranslationsFromLanguage, getTranslationCore, } from "i18n-keyless-core";
2
2
  import { create } from "zustand";
3
3
  import { storeKeys, setItem, getItem, clearI18nKeylessStorage, validateLanguage } from "./utils";
4
+ import { sendTranslationsUsageToI18nKeyless } from "i18n-keyless-core/service";
4
5
  queue.on("empty", () => {
5
6
  // when each word is translated, fetch the translations for the current language
6
7
  const store = useI18nKeyless.getState();
@@ -12,6 +13,7 @@ export const useI18nKeyless = create((set, get) => ({
12
13
  uniqueId: null,
13
14
  lastRefresh: null,
14
15
  translations: {},
16
+ lastUsedTranslation: {},
15
17
  currentLanguage: "fr",
16
18
  config: {
17
19
  API_KEY: "",
@@ -46,6 +48,24 @@ export const useI18nKeyless = create((set, get) => ({
46
48
  setItem(storeKeys.lastRefresh, response.data.lastRefresh, storage);
47
49
  }
48
50
  },
51
+ sendTranslationsUsage: async () => {
52
+ const store = get();
53
+ if (!store.config) {
54
+ throw new Error(`i18n-keyless: config is not initialized sending last used translation`);
55
+ }
56
+ const storage = store.config.storage;
57
+ const lastUsedTranslation = store.lastUsedTranslation;
58
+ if (Object.keys(lastUsedTranslation).length === 0) {
59
+ return;
60
+ }
61
+ const response = await sendTranslationsUsageToI18nKeyless(lastUsedTranslation, store);
62
+ if (response?.ok) {
63
+ set({ lastUsedTranslation: {} });
64
+ if (storage) {
65
+ setItem(storeKeys.lastUsedTranslation, "", storage);
66
+ }
67
+ }
68
+ },
49
69
  setLanguage: async (lang) => {
50
70
  const store = get();
51
71
  if (!store.config) {
@@ -93,6 +113,16 @@ async function hydrate() {
93
113
  if (debug)
94
114
  console.log("i18n-keyless: _hydrate: no translations");
95
115
  }
116
+ const lastUsedTranslation = await getItem(storeKeys.lastUsedTranslation, storage, JSON.parse);
117
+ if (lastUsedTranslation) {
118
+ if (debug)
119
+ console.log("i18n-keyless: _hydrate: last used translation", lastUsedTranslation);
120
+ useI18nKeyless.setState({ lastUsedTranslation: lastUsedTranslation });
121
+ }
122
+ else {
123
+ if (debug)
124
+ console.log("i18n-keyless: _hydrate: no last used translation");
125
+ }
96
126
  const currentLanguage = await getItem(storeKeys.currentLanguage, storage);
97
127
  if (currentLanguage) {
98
128
  if (debug)
@@ -159,6 +189,7 @@ export async function init(newConfig) {
159
189
  newConfig.onInit?.(currentLanguage);
160
190
  // initialize the language to fetch all the translations
161
191
  useI18nKeyless.getState().setLanguage(currentLanguage);
192
+ useI18nKeyless.getState().sendTranslationsUsage();
162
193
  }
163
194
  export function useCurrentLanguage() {
164
195
  const currentLanguage = useI18nKeyless((state) => state.currentLanguage);
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { I18nKeylessResponse, Lang, Translations, HandleTranslateFunction, GetAllTranslationsFunction, UniqueId, LastRefresh, LanguagesConfig } from "i18n-keyless-core";
1
+ import type { I18nKeylessResponse, Lang, Translations, LastUsedTranslation, HandleTranslateFunction, GetAllTranslationsFunction, SendTranslationsUsageFunction, UniqueId, LastRefresh, LanguagesConfig } from "i18n-keyless-core";
2
2
  type GetStorageFunction = (key: string) => string | null | undefined | Promise<string | null | undefined>;
3
3
  type SetStorageFunction = (key: string, value: string) => void | Promise<void>;
4
4
  type RemoveStorageFunction = (key: string) => void | Promise<void>;
@@ -69,6 +69,15 @@ export interface I18nConfig {
69
69
  * - not use this `getAllTranslations` function nor API_KEY key, and provide your own API_URL
70
70
  */
71
71
  getAllTranslations?: GetAllTranslationsFunction;
72
+ /**
73
+ * if this function exists, it will be called instead of the API call
74
+ * if this function doesn't exist, the default behavior is to call the API
75
+ * therefore you need either to
76
+ * - use this `sendTranslationsUsage` function to handle the translation with your own API
77
+ * - not use this `sendTranslationsUsage` function, and use the built in API call with the API_KEY filled
78
+ * - not use this `sendTranslationsUsage` function nor API_KEY key, and provide your own API_URL
79
+ */
80
+ sendTranslationsUsage?: SendTranslationsUsageFunction;
72
81
  /**
73
82
  * the storage to use for the translations
74
83
  *
@@ -119,6 +128,13 @@ export interface TranslationStoreState {
119
128
  * the translations fetched from i18n-keyless' API
120
129
  */
121
130
  translations: Translations;
131
+ /**
132
+ * save the date in format YYYY-MM-DD when a key is used
133
+ * this information is sent to i18n-keyless' API on lib initialization
134
+ * it's used to clean up the translations database
135
+ * and to avoid paying for translations that are not used anymore
136
+ */
137
+ lastUsedTranslation: LastUsedTranslation;
122
138
  /**
123
139
  * the current language of the user
124
140
  */
@@ -149,6 +165,7 @@ export type TranslationOptions = {
149
165
  interface TranslationStoreActions {
150
166
  setTranslations: (translations: I18nKeylessResponse | void) => void;
151
167
  setLanguage: (lang: Lang) => void;
168
+ sendTranslationsUsage: () => Promise<void>;
152
169
  }
153
170
  export type TranslationStore = TranslationStoreState & TranslationStoreActions;
154
171
  export {};
package/dist/utils.d.ts CHANGED
@@ -7,6 +7,7 @@ export declare const storeKeys: {
7
7
  lastRefresh: "i18n-keyless-last-refresh";
8
8
  translations: "i18n-keyless-translations";
9
9
  currentLanguage: "i18n-keyless-current-language";
10
+ lastUsedTranslation: "i18n-keyless-last-used-translation";
10
11
  };
11
12
  /**
12
13
  * Retrieves an item from storage using various storage API patterns
package/dist/utils.js CHANGED
@@ -6,6 +6,7 @@ export const storeKeys = {
6
6
  lastRefresh: "i18n-keyless-last-refresh",
7
7
  translations: "i18n-keyless-translations",
8
8
  currentLanguage: "i18n-keyless-current-language",
9
+ lastUsedTranslation: "i18n-keyless-last-used-translation",
9
10
  };
10
11
  /**
11
12
  * Retrieves an item from storage using various storage API patterns
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "i18n-keyless-react",
3
3
  "private": false,
4
- "version": "1.13.0",
4
+ "version": "1.14.2",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  "postpublish": "rm -rf ./dist && rm *.tgz"
18
18
  },
19
19
  "dependencies": {
20
- "i18n-keyless-core": "1.13.0",
20
+ "i18n-keyless-core": "1.14.2",
21
21
  "zustand": "^5.0.3"
22
22
  },
23
23
  "peerDependencies": {