@vaadin/hilla-react-i18n 24.5.0 → 24.6.0-alpha2
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/index.d.ts +5 -0
- package/index.d.ts.map +1 -1
- package/index.js +27 -0
- package/index.js.map +2 -2
- package/package.json +3 -3
package/index.d.ts
CHANGED
|
@@ -83,6 +83,11 @@ export declare class I18n {
|
|
|
83
83
|
*/
|
|
84
84
|
registerChunk(chunkName: string): Promise<void>;
|
|
85
85
|
private updateLanguage;
|
|
86
|
+
/**
|
|
87
|
+
* Reloads all translations for the current language. This method should only
|
|
88
|
+
* be used for HMR in development mode.
|
|
89
|
+
*/
|
|
90
|
+
private reloadTranslations;
|
|
86
91
|
/**
|
|
87
92
|
* Returns a translated string for the given translation key. The key should
|
|
88
93
|
* match a key in the loaded translations. If no translation is found for the
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,cAAc,EAAuB,MAAM,6BAA6B,CAAC;AAI9F,OAAO,KAAK,EAAE,WAAW,EAAoC,MAAM,YAAY,CAAC;AAgBhF,qBAAa,IAAI;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,cAAc,EAAuB,MAAM,6BAA6B,CAAC;AAI9F,OAAO,KAAK,EAAE,WAAW,EAAoC,MAAM,YAAY,CAAC;AAgBhF,qBAAa,IAAI;;;IA8Bf;;;;;;;;OAQG;IACH,IAAI,WAAW,IAAI,cAAc,CAAC,OAAO,CAAC,CAEzC;IAED;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAEjD;IAED;;;;;;;OAOG;IACH,IAAI,gBAAgB,IAAI,cAAc,CAAC,MAAM,GAAG,SAAS,CAAC,CAEzD;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,SAAS,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrD;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD;;;;;;;OAOG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAYvC,cAAc;IAqC5B;;;OAGG;YACW,kBAAkB;IAsBhC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;CAQjE;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,MAAa,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;;;;GAuBG,CAAC,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAEnF"}
|
package/index.js
CHANGED
|
@@ -26,6 +26,11 @@ class I18n {
|
|
|
26
26
|
`The Hilla I18n API is currently considered experimental and may change in the future. To use it you need to explicitly enable it in Copilot or by adding com.vaadin.experimental.hillaI18n=true to vaadin-featureflags.properties`
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
|
+
if (import.meta.hot) {
|
|
30
|
+
import.meta.hot.on("translations-update", () => {
|
|
31
|
+
this.reloadTranslations();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
29
34
|
}
|
|
30
35
|
/**
|
|
31
36
|
* Returns a signal indicating whether the I18n instance has been initialized.
|
|
@@ -150,6 +155,28 @@ class I18n {
|
|
|
150
155
|
}
|
|
151
156
|
});
|
|
152
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Reloads all translations for the current language. This method should only
|
|
160
|
+
* be used for HMR in development mode.
|
|
161
|
+
*/
|
|
162
|
+
async reloadTranslations() {
|
|
163
|
+
const currentLanguage = this.#language.value;
|
|
164
|
+
if (!currentLanguage) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let translationsResult;
|
|
168
|
+
try {
|
|
169
|
+
translationsResult = await this.#backend.loadTranslations(currentLanguage);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
console.error(`Failed to reload translations for language: ${currentLanguage}`, e);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
batch(() => {
|
|
175
|
+
this.#translations.value = translationsResult.translations;
|
|
176
|
+
this.#resolvedLanguage.value = translationsResult.resolvedLanguage;
|
|
177
|
+
this.#formatCache = new FormatCache(currentLanguage);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
153
180
|
/**
|
|
154
181
|
* Returns a translated string for the given translation key. The key should
|
|
155
182
|
* match a key in the loaded translations. If no translation is found for the
|
package/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { batch, type ReadonlySignal, signal, type Signal } from '@vaadin/hilla-react-signals';\nimport { DefaultBackend, type I18nBackend } from './backend.js';\nimport { FormatCache } from './FormatCache.js';\nimport { getLanguageSettings, updateLanguageSettings } from './settings.js';\nimport type { I18nOptions, Translations, TranslationsResult } from './types.js';\n\nfunction determineInitialLanguage(options?: I18nOptions): string {\n // Use explicitly configured language if defined\n if (options?.language) {\n return options.language;\n }\n // Use last used language as fallback\n const settings = getLanguageSettings();\n if (settings?.language) {\n return settings.language;\n }\n // Otherwise use browser language\n return navigator.language;\n}\n\nexport class I18n {\n readonly #backend: I18nBackend = new DefaultBackend();\n\n readonly #initialized: Signal<boolean> = signal(false);\n readonly #language: Signal<string | undefined> = signal(undefined);\n readonly #translations: Signal<Translations> = signal({});\n readonly #resolvedLanguage: Signal<string | undefined> = signal(undefined);\n readonly #chunks = new Set<string>();\n\n #formatCache: FormatCache = new FormatCache(navigator.language);\n\n constructor() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (!(window as any).Vaadin?.featureFlags?.hillaI18n) {\n // Remove when removing feature flag\n throw new Error(\n `The Hilla I18n API is currently considered experimental and may change in the future. To use it you need to explicitly enable it in Copilot or by adding com.vaadin.experimental.hillaI18n=true to vaadin-featureflags.properties`,\n );\n }\n }\n\n /**\n * Returns a signal indicating whether the I18n instance has been initialized.\n * The instance is considered initialized after `configure` has been called\n * and translations for the initial language have been loaded. Can be used to\n * show a placeholder or loading indicator until the translations are ready.\n *\n * Subscribers to this signal will be notified when initialization is complete\n * and translations are ready to be used.\n */\n get initialized(): ReadonlySignal<boolean> {\n return this.#initialized;\n }\n\n /**\n * Returns a signal with the currently configured language.\n *\n * Subscribers to this signal will be notified when the language has changed\n * and new translations have been loaded.\n */\n get language(): ReadonlySignal<string | undefined> {\n return this.#language;\n }\n\n /**\n * Returns a signal with the resolved language. The resolved language is the\n * language that was actually used to load translations. It may differ from\n * the configured language if there are no translations available for the\n * configured language. For example, when setting the language to \"de-DE\" but\n * translations are only available for \"de\", the resolved language will be\n * \"de\".\n */\n get resolvedLanguage(): ReadonlySignal<string | undefined> {\n return this.#resolvedLanguage;\n }\n\n /**\n * Initializes the I18n instance. This method should be called once to load\n * translations for the initial language. The `translate` API will not return\n * properly translated strings until the initializations has completed.\n *\n * The initialization runs asynchronously as translations are loaded from the\n * backend. The method returns a promise that resolves when the translations\n * have been loaded, after which the `translate` API can safely be used.\n *\n * The initial language is determined as follows:\n * 1. If a user opens the app for the first time, the browser language is used.\n * 2. If the language has been changed in a previous usage of the app using\n * `setLanguage`, the last used language is used. The last used language is\n * automatically stored in local storage.\n *\n * Alternatively, the initial language can be explicitly configured using the\n * `language` option. The language should be a valid IETF BCP 47 language tag,\n * such as `en` or `en-US`.\n *\n * @param options - Optional options object to specify the initial language.\n */\n async configure(options?: I18nOptions): Promise<void> {\n const initialLanguage = determineInitialLanguage(options);\n await this.updateLanguage(initialLanguage);\n }\n\n /**\n * Changes the current language and loads translations for the new language.\n * Components using the `translate` API will automatically re-render, and\n * subscribers to the `language` signal will be notified, when the new\n * translations have been loaded.\n *\n * The language should be a valid IETF BCP 47 language tag, such as `en` or\n * `en-US`.\n *\n * If there is no translation file for that specific language tag, the backend\n * will try to load the translation file for the parent language tag. For\n * example, if there is no translation file for `en-US`, the backend will try\n * to load the translation file for `en`. Otherwise, it will fall back to the\n * default translation file `translations.properties`.\n *\n * Changing the language is an asynchronous operation. The method returns a\n * promise that resolves when the translations for the new language have been\n * loaded.\n *\n * @param newLanguage - a valid IETF BCP 47 language tag, such as `en` or `en-US`\n */\n async setLanguage(newLanguage: string): Promise<void> {\n await this.updateLanguage(newLanguage, true);\n }\n\n /**\n * Registers the chunk name for loading translations, and loads the\n * translations for the specified chunk.\n *\n * @internal only for automatic internal calls from production JS bundles\n *\n * @param chunkName - the production JS bundle chunk name\n */\n async registerChunk(chunkName: string): Promise<void> {\n if (this.#chunks.has(chunkName)) {\n return;\n }\n\n this.#chunks.add(chunkName);\n\n if (this.#language.value) {\n await this.updateLanguage(this.#language.value, false, chunkName);\n }\n }\n\n private async updateLanguage(newLanguage: string, updateSettings = false, newChunk?: string) {\n if (this.#language.value === newLanguage && !newChunk) {\n return;\n }\n\n const chunks = newChunk\n ? [newChunk] // New chunk is registered, load only that\n : this.#chunks.size > 0\n ? [...this.#chunks.values()] // Load the new language for all chunks registered so far\n : undefined; // Load the new language without specifying chunks, assuming dev. mode\n\n let translationsResult: TranslationsResult;\n try {\n translationsResult = await this.#backend.loadTranslations(newLanguage, chunks);\n } catch (e) {\n console.error(`Failed to load translations for language: ${newLanguage}`, e);\n return;\n }\n\n // Update all signals together to avoid triggering side effects multiple times\n batch(() => {\n this.#translations.value = newChunk\n ? { ...this.#translations.value, ...translationsResult.translations }\n : translationsResult.translations;\n this.#language.value = newLanguage;\n this.#resolvedLanguage.value = translationsResult.resolvedLanguage;\n this.#formatCache = new FormatCache(newLanguage);\n this.#initialized.value = true;\n\n if (updateSettings) {\n updateLanguageSettings({\n language: newLanguage,\n });\n }\n });\n }\n\n /**\n * Returns a translated string for the given translation key. The key should\n * match a key in the loaded translations. If no translation is found for the\n * key, the key itself is returned.\n *\n * Translations may contain placeholders, following the ICU MessageFormat\n * syntax. They can be replaced by passing a `params` object with placeholder\n * values, where keys correspond to the placeholder names and values are the\n * replacement value. Values should be basic types such as strings, numbers,\n * or dates that match the placeholder format configured in the translation\n * string. For example, when using a placeholder `{count, number}`, the value\n * should be a number, when using `{date, date}`, the value should be a Date\n * object, and so on.\n *\n * This method internally accesses a signal, meaning that React components\n * that use it will automatically re-render when translations change.\n * Likewise, signal effects automatically subscribe to translation changes\n * when calling this method.\n *\n * @param key - The translation key to translate\n * @param params - Optional object with placeholder values\n */\n translate(key: string, params?: Record<string, unknown>): string {\n const translation = this.#translations.value[key];\n if (!translation) {\n return key;\n }\n const format = this.#formatCache.getFormat(translation);\n return format.format(params) as string;\n }\n}\n\n/**\n * The global I18n instance that is used to initialize translations, change the\n * current language, and translate strings.\n */\nexport const i18n = new I18n();\n\n/**\n * Returns a translated string for the given translation key. The key should\n * match a key in the loaded translations. If no translation is found for the\n * key, the key itself is returned.\n *\n * Translations may contain placeholders, following the ICU MessageFormat\n * syntax. They can be replaced by passing a `params` object with placeholder\n * values, where keys correspond to the placeholder names and values are the\n * replacement value. Values should be basic types such as strings, numbers,\n * or dates that match the placeholder format configured in the translation\n * string. For example, when using a placeholder `{count, number}`, the value\n * should be a number, when using `{date, date}`, the value should be a Date\n * object, and so on.\n *\n * This method internally accesses a signal, meaning that React components\n * that use it will automatically re-render when translations change.\n * Likewise, signal effects automatically subscribe to translation changes\n * when calling this method.\n *\n * This function is a shorthand for `i18n.translate` of the global I18n instance.\n *\n * @param key - The translation key to translate\n * @param params - Optional object with placeholder values\n */ export function translate(key: string, params?: Record<string, unknown>): string {\n return i18n.translate(key, params);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { batch, type ReadonlySignal, signal, type Signal } from '@vaadin/hilla-react-signals';\nimport { DefaultBackend, type I18nBackend } from './backend.js';\nimport { FormatCache } from './FormatCache.js';\nimport { getLanguageSettings, updateLanguageSettings } from './settings.js';\nimport type { I18nOptions, Translations, TranslationsResult } from './types.js';\n\nfunction determineInitialLanguage(options?: I18nOptions): string {\n // Use explicitly configured language if defined\n if (options?.language) {\n return options.language;\n }\n // Use last used language as fallback\n const settings = getLanguageSettings();\n if (settings?.language) {\n return settings.language;\n }\n // Otherwise use browser language\n return navigator.language;\n}\n\nexport class I18n {\n readonly #backend: I18nBackend = new DefaultBackend();\n\n readonly #initialized: Signal<boolean> = signal(false);\n readonly #language: Signal<string | undefined> = signal(undefined);\n readonly #translations: Signal<Translations> = signal({});\n readonly #resolvedLanguage: Signal<string | undefined> = signal(undefined);\n readonly #chunks = new Set<string>();\n\n #formatCache: FormatCache = new FormatCache(navigator.language);\n\n constructor() {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n if (!(window as any).Vaadin?.featureFlags?.hillaI18n) {\n // Remove when removing feature flag\n throw new Error(\n `The Hilla I18n API is currently considered experimental and may change in the future. To use it you need to explicitly enable it in Copilot or by adding com.vaadin.experimental.hillaI18n=true to vaadin-featureflags.properties`,\n );\n }\n // @ts-expect-error import.meta.hot does not have TS definitions\n if (import.meta.hot) {\n // @ts-expect-error import.meta.hot does not have TS definitions\n // eslint-disable-next-line\n import.meta.hot.on('translations-update', () => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.reloadTranslations();\n });\n }\n }\n\n /**\n * Returns a signal indicating whether the I18n instance has been initialized.\n * The instance is considered initialized after `configure` has been called\n * and translations for the initial language have been loaded. Can be used to\n * show a placeholder or loading indicator until the translations are ready.\n *\n * Subscribers to this signal will be notified when initialization is complete\n * and translations are ready to be used.\n */\n get initialized(): ReadonlySignal<boolean> {\n return this.#initialized;\n }\n\n /**\n * Returns a signal with the currently configured language.\n *\n * Subscribers to this signal will be notified when the language has changed\n * and new translations have been loaded.\n */\n get language(): ReadonlySignal<string | undefined> {\n return this.#language;\n }\n\n /**\n * Returns a signal with the resolved language. The resolved language is the\n * language that was actually used to load translations. It may differ from\n * the configured language if there are no translations available for the\n * configured language. For example, when setting the language to \"de-DE\" but\n * translations are only available for \"de\", the resolved language will be\n * \"de\".\n */\n get resolvedLanguage(): ReadonlySignal<string | undefined> {\n return this.#resolvedLanguage;\n }\n\n /**\n * Initializes the I18n instance. This method should be called once to load\n * translations for the initial language. The `translate` API will not return\n * properly translated strings until the initializations has completed.\n *\n * The initialization runs asynchronously as translations are loaded from the\n * backend. The method returns a promise that resolves when the translations\n * have been loaded, after which the `translate` API can safely be used.\n *\n * The initial language is determined as follows:\n * 1. If a user opens the app for the first time, the browser language is used.\n * 2. If the language has been changed in a previous usage of the app using\n * `setLanguage`, the last used language is used. The last used language is\n * automatically stored in local storage.\n *\n * Alternatively, the initial language can be explicitly configured using the\n * `language` option. The language should be a valid IETF BCP 47 language tag,\n * such as `en` or `en-US`.\n *\n * @param options - Optional options object to specify the initial language.\n */\n async configure(options?: I18nOptions): Promise<void> {\n const initialLanguage = determineInitialLanguage(options);\n await this.updateLanguage(initialLanguage);\n }\n\n /**\n * Changes the current language and loads translations for the new language.\n * Components using the `translate` API will automatically re-render, and\n * subscribers to the `language` signal will be notified, when the new\n * translations have been loaded.\n *\n * The language should be a valid IETF BCP 47 language tag, such as `en` or\n * `en-US`.\n *\n * If there is no translation file for that specific language tag, the backend\n * will try to load the translation file for the parent language tag. For\n * example, if there is no translation file for `en-US`, the backend will try\n * to load the translation file for `en`. Otherwise, it will fall back to the\n * default translation file `translations.properties`.\n *\n * Changing the language is an asynchronous operation. The method returns a\n * promise that resolves when the translations for the new language have been\n * loaded.\n *\n * @param newLanguage - a valid IETF BCP 47 language tag, such as `en` or `en-US`\n */\n async setLanguage(newLanguage: string): Promise<void> {\n await this.updateLanguage(newLanguage, true);\n }\n\n /**\n * Registers the chunk name for loading translations, and loads the\n * translations for the specified chunk.\n *\n * @internal only for automatic internal calls from production JS bundles\n *\n * @param chunkName - the production JS bundle chunk name\n */\n async registerChunk(chunkName: string): Promise<void> {\n if (this.#chunks.has(chunkName)) {\n return;\n }\n\n this.#chunks.add(chunkName);\n\n if (this.#language.value) {\n await this.updateLanguage(this.#language.value, false, chunkName);\n }\n }\n\n private async updateLanguage(newLanguage: string, updateSettings = false, newChunk?: string) {\n if (this.#language.value === newLanguage && !newChunk) {\n return;\n }\n\n const chunks = newChunk\n ? [newChunk] // New chunk is registered, load only that\n : this.#chunks.size > 0\n ? [...this.#chunks.values()] // Load the new language for all chunks registered so far\n : undefined; // Load the new language without specifying chunks, assuming dev. mode\n\n let translationsResult: TranslationsResult;\n try {\n translationsResult = await this.#backend.loadTranslations(newLanguage, chunks);\n } catch (e) {\n console.error(`Failed to load translations for language: ${newLanguage}`, e);\n return;\n }\n\n // Update all signals together to avoid triggering side effects multiple times\n batch(() => {\n this.#translations.value = newChunk\n ? { ...this.#translations.value, ...translationsResult.translations }\n : translationsResult.translations;\n this.#language.value = newLanguage;\n this.#resolvedLanguage.value = translationsResult.resolvedLanguage;\n this.#formatCache = new FormatCache(newLanguage);\n this.#initialized.value = true;\n\n if (updateSettings) {\n updateLanguageSettings({\n language: newLanguage,\n });\n }\n });\n }\n\n /**\n * Reloads all translations for the current language. This method should only\n * be used for HMR in development mode.\n */\n private async reloadTranslations() {\n const currentLanguage = this.#language.value;\n if (!currentLanguage) {\n return;\n }\n\n let translationsResult: TranslationsResult;\n try {\n translationsResult = await this.#backend.loadTranslations(currentLanguage);\n } catch (e) {\n console.error(`Failed to reload translations for language: ${currentLanguage}`, e);\n return;\n }\n\n // Update all signals together to avoid triggering side effects multiple times\n batch(() => {\n this.#translations.value = translationsResult.translations;\n this.#resolvedLanguage.value = translationsResult.resolvedLanguage;\n this.#formatCache = new FormatCache(currentLanguage);\n });\n }\n\n /**\n * Returns a translated string for the given translation key. The key should\n * match a key in the loaded translations. If no translation is found for the\n * key, the key itself is returned.\n *\n * Translations may contain placeholders, following the ICU MessageFormat\n * syntax. They can be replaced by passing a `params` object with placeholder\n * values, where keys correspond to the placeholder names and values are the\n * replacement value. Values should be basic types such as strings, numbers,\n * or dates that match the placeholder format configured in the translation\n * string. For example, when using a placeholder `{count, number}`, the value\n * should be a number, when using `{date, date}`, the value should be a Date\n * object, and so on.\n *\n * This method internally accesses a signal, meaning that React components\n * that use it will automatically re-render when translations change.\n * Likewise, signal effects automatically subscribe to translation changes\n * when calling this method.\n *\n * @param key - The translation key to translate\n * @param params - Optional object with placeholder values\n */\n translate(key: string, params?: Record<string, unknown>): string {\n const translation = this.#translations.value[key];\n if (!translation) {\n return key;\n }\n const format = this.#formatCache.getFormat(translation);\n return format.format(params) as string;\n }\n}\n\n/**\n * The global I18n instance that is used to initialize translations, change the\n * current language, and translate strings.\n */\nexport const i18n = new I18n();\n\n/**\n * Returns a translated string for the given translation key. The key should\n * match a key in the loaded translations. If no translation is found for the\n * key, the key itself is returned.\n *\n * Translations may contain placeholders, following the ICU MessageFormat\n * syntax. They can be replaced by passing a `params` object with placeholder\n * values, where keys correspond to the placeholder names and values are the\n * replacement value. Values should be basic types such as strings, numbers,\n * or dates that match the placeholder format configured in the translation\n * string. For example, when using a placeholder `{count, number}`, the value\n * should be a number, when using `{date, date}`, the value should be a Date\n * object, and so on.\n *\n * This method internally accesses a signal, meaning that React components\n * that use it will automatically re-render when translations change.\n * Likewise, signal effects automatically subscribe to translation changes\n * when calling this method.\n *\n * This function is a shorthand for `i18n.translate` of the global I18n instance.\n *\n * @param key - The translation key to translate\n * @param params - Optional object with placeholder values\n */ export function translate(key: string, params?: Record<string, unknown>): string {\n return i18n.translate(key, params);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/hilla-react-i18n",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.6.0-alpha2",
|
|
4
4
|
"description": "Hilla I18n utils for React",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.js",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@vaadin/hilla-frontend": "24.
|
|
50
|
-
"@vaadin/hilla-react-signals": "24.
|
|
49
|
+
"@vaadin/hilla-frontend": "24.6.0-alpha2",
|
|
50
|
+
"@vaadin/hilla-react-signals": "24.6.0-alpha2",
|
|
51
51
|
"intl-messageformat": "^10.5.11"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|