@plentymarkets/shop-core 1.13.4 → 1.13.5

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/module.d.mts CHANGED
@@ -1,8 +1,11 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
- export { Cookie, CookieGroup, CookieGroupFromNuxtConfig, Events, JsonCookie, Notification, PaymentButtonComponent, PaymentButtonComponentProps } from '../dist/runtime/types/index.js';
2
+ export { Cookie, CookieGroup, CookieGroupFromNuxtConfig, Events, JsonCookie, LocalizationMessage, Notification, PaymentButtonComponent, PaymentButtonComponentProps } from '../dist/runtime/types/index.js';
3
3
 
4
4
  interface ModuleOptions {
5
5
  apiUrl: string;
6
+ apiEndpoint: string;
7
+ configId: number;
8
+ securityToken: string;
6
9
  }
7
10
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
8
11
 
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "name": "shop-core",
2
+ "name": "@plentymarkets/shop-core",
3
3
  "configKey": "shopCore",
4
- "version": "1.13.4",
4
+ "version": "1.13.5",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -1,15 +1,63 @@
1
1
  import { defineNuxtModule, createResolver, addImports } from '@nuxt/kit';
2
+ import { ofetch } from 'ofetch';
3
+ import { writeFile } from 'fs/promises';
4
+ import { join } from 'path';
2
5
 
3
- const module = defineNuxtModule({
6
+ const fetchAllTranslations = async (url, configId, securityToken) => {
7
+ return await ofetch(
8
+ `${url}/rest/storefront/translations/${configId}/complete`,
9
+ {
10
+ method: "GET",
11
+ headers: {
12
+ "X-Security-Token": securityToken,
13
+ "Content-Type": "application/json"
14
+ }
15
+ }
16
+ );
17
+ };
18
+
19
+ const module$1 = defineNuxtModule({
4
20
  meta: {
5
- name: "shop-core",
21
+ name: "@plentymarkets/shop-core",
6
22
  configKey: "shopCore"
7
23
  },
8
- // Default configuration options of the Nuxt module
9
24
  defaults: {},
10
- async setup(_options, _nuxt) {
25
+ moduleDependencies: {
26
+ "@nuxtjs/i18n": {
27
+ version: ">=9.5.4"
28
+ }
29
+ },
30
+ async setup(_options, nuxt) {
11
31
  const resolver = createResolver(import.meta.url);
12
- _nuxt.options.runtimeConfig.public.shopCore = _options;
32
+ nuxt.options.runtimeConfig.public.shopCore = {
33
+ apiUrl: _options.apiUrl,
34
+ configId: _options.configId
35
+ };
36
+ const overridesDir = resolver.resolve("./runtime/lang/overrides");
37
+ const allLocalesForOverride = [];
38
+ if (_options.apiEndpoint && _options.configId && _options.securityToken) {
39
+ try {
40
+ const { data } = await fetchAllTranslations(_options.apiEndpoint, _options.configId, _options.securityToken);
41
+ for (const key of Object.keys(data)) {
42
+ allLocalesForOverride.push(key);
43
+ await writeFile(join(overridesDir, `${key}.json`), JSON.stringify({ translated: data[key] }, null, 2));
44
+ }
45
+ } catch (error) {
46
+ console.warn("Failed to fetch translations: ", error);
47
+ }
48
+ }
49
+ nuxt.hook("i18n:registerModule", (register) => {
50
+ if (allLocalesForOverride.length > 0) {
51
+ register({
52
+ langDir: resolver.resolve("./runtime/lang/overrides"),
53
+ // @ts-ignore
54
+ locales: allLocalesForOverride.map((locale) => ({
55
+ code: locale,
56
+ file: `${locale}.json`
57
+ }))
58
+ });
59
+ }
60
+ });
13
61
  addImports({
14
62
  name: "useSdk",
15
63
  as: "useSdk",
@@ -55,7 +103,22 @@ const module = defineNuxtModule({
55
103
  as: "useCartStockReservation",
56
104
  from: resolver.resolve("./runtime/composables/useCartStockReservation")
57
105
  });
106
+ addImports({
107
+ name: "useEditorLocalizationKeys",
108
+ as: "useEditorLocalizationKeys",
109
+ from: resolver.resolve("./runtime/composables/localization/useEditorLocalizationKeys")
110
+ });
111
+ addImports({
112
+ name: "useEditorLocalizationLocales",
113
+ as: "useEditorLocalizationLocales",
114
+ from: resolver.resolve("./runtime/composables/localization/useEditorLocalizationLocales")
115
+ });
116
+ addImports({
117
+ name: "t",
118
+ as: "t",
119
+ from: resolver.resolve("./runtime/composables/useT")
120
+ });
58
121
  }
59
122
  });
60
123
 
61
- export { module as default };
124
+ export { module$1 as default };
@@ -0,0 +1,21 @@
1
+ import type { LocalizationMessage, I18nInstance } from '../../types/index.js';
2
+ export declare const unflattenTranslations: (flat: Record<string, string>) => Record<string, any>;
3
+ /**
4
+ * Load default keys from i18n messages (PWA)
5
+ * @param keysMap
6
+ * @param $i18n
7
+ */
8
+ export declare const loadDefaultKeys: (keysMap: Map<string, Record<string, LocalizationMessage>>, $i18n: I18nInstance) => Promise<void>;
9
+ /**
10
+ * Load translated keys from i18n messages (Module Overrides)
11
+ * @param keysMap
12
+ * @param $i18n
13
+ */
14
+ export declare const loadTranslatedKeys: (keysMap: Map<string, Record<string, LocalizationMessage>>, $i18n: I18nInstance) => void;
15
+ /**
16
+ * Load all translations from the backend
17
+ * @param keysMap
18
+ * @param $i18n
19
+ * @param backendLanguages
20
+ */
21
+ export declare const loadKeysFromBackend: (keysMap: Map<string, Record<string, LocalizationMessage>>, $i18n: I18nInstance, backendLanguages?: Set<string>) => Promise<void>;
@@ -0,0 +1,157 @@
1
+ import { useRuntimeConfig } from "nuxt/app";
2
+ import { useSdk } from "#imports";
3
+ function flattenTranslations(data) {
4
+ const result = {};
5
+ function flattenObject(obj, prefix = "") {
6
+ const flattened = {};
7
+ for (const [key, value] of Object.entries(obj)) {
8
+ const newKey = prefix ? `${prefix}.${key}` : key;
9
+ if (typeof value === "string") {
10
+ flattened[newKey] = value;
11
+ } else {
12
+ Object.assign(flattened, flattenObject(value, newKey));
13
+ }
14
+ }
15
+ return flattened;
16
+ }
17
+ for (const [lang, modules] of Object.entries(data)) {
18
+ result[lang] = flattenObject(modules);
19
+ }
20
+ return result;
21
+ }
22
+ export const unflattenTranslations = (flat) => {
23
+ const result = {};
24
+ for (const [key, value] of Object.entries(flat)) {
25
+ const parts = key.split(".");
26
+ let current = result;
27
+ for (let i = 0; i < parts.length - 1; i++) {
28
+ const part = parts[i];
29
+ if (!current[part]) current[part] = {};
30
+ current = current[part];
31
+ }
32
+ const lastPart = parts[parts.length - 1];
33
+ current[lastPart] = value;
34
+ }
35
+ return result;
36
+ };
37
+ const isCompiledMessage = (value) => {
38
+ return typeof value === "object" && value !== null && ("loc" in value && typeof value.loc === "object" && value.loc !== null && "source" in value.loc && typeof value.loc.source === "string" || "b" in value && typeof value.b === "object" && value.b !== null && "s" in value.b && typeof value.b.s === "string");
39
+ };
40
+ const createEmptyMessage = (availableLocales) => {
41
+ let data = {};
42
+ for (const locale of availableLocales) {
43
+ data = {
44
+ ...data,
45
+ [locale]: {
46
+ value: "",
47
+ input: "",
48
+ isDeployed: true
49
+ }
50
+ };
51
+ }
52
+ return data;
53
+ };
54
+ const getTranslationValue = (value) => {
55
+ if (isCompiledMessage(value) && value) {
56
+ const data = value;
57
+ return data?.loc?.source ?? data?.b?.s ?? "";
58
+ }
59
+ if (typeof value === "string") {
60
+ return value;
61
+ }
62
+ return null;
63
+ };
64
+ const isNestedObject = (value) => {
65
+ return value !== null && typeof value === "object" && !Array.isArray(value) && !isCompiledMessage(value);
66
+ };
67
+ const extractKeysWithValues = (obj, prefix = "") => {
68
+ const result = {};
69
+ for (const key in obj) {
70
+ let fullKey = prefix ? `${prefix}.${key}` : key;
71
+ if (fullKey.endsWith(".body.static")) {
72
+ continue;
73
+ }
74
+ if (fullKey.endsWith(".loc.source")) {
75
+ fullKey = fullKey.substring(0, fullKey.length - ".loc.source".length);
76
+ }
77
+ const value = obj[key];
78
+ if (isNestedObject(value)) {
79
+ Object.assign(result, extractKeysWithValues(value, fullKey));
80
+ } else {
81
+ const translationValue = getTranslationValue(value);
82
+ if (translationValue)
83
+ result[fullKey] = {
84
+ value: translationValue,
85
+ default: translationValue,
86
+ input: translationValue,
87
+ isDeployed: true
88
+ };
89
+ }
90
+ }
91
+ return result;
92
+ };
93
+ export const loadDefaultKeys = async (keysMap, $i18n) => {
94
+ for (const locale of $i18n.availableLocales) {
95
+ await $i18n.loadLocaleMessages(locale);
96
+ const messages = $i18n.getLocaleMessage(locale);
97
+ const keysWithValues = extractKeysWithValues(messages);
98
+ for (const [key, value] of Object.entries(keysWithValues)) {
99
+ if (key.startsWith("translated.")) continue;
100
+ if (!keysMap.has(key)) {
101
+ keysMap.set(key, createEmptyMessage($i18n.availableLocales));
102
+ }
103
+ const translations = keysMap.get(key);
104
+ translations[locale] = value;
105
+ }
106
+ }
107
+ };
108
+ export const loadTranslatedKeys = (keysMap, $i18n) => {
109
+ for (const locale of $i18n.availableLocales) {
110
+ const messages = $i18n.getLocaleMessage(locale);
111
+ const translatedMessages = messages["translated"];
112
+ if (!translatedMessages) continue;
113
+ const keysWithValues = extractKeysWithValues(translatedMessages);
114
+ for (const [key, value] of Object.entries(keysWithValues)) {
115
+ if (!keysMap.has(key)) {
116
+ keysMap.set(key, createEmptyMessage($i18n.availableLocales));
117
+ }
118
+ const translations = keysMap.get(key);
119
+ if (translations[locale]) {
120
+ translations[locale].value = value.value;
121
+ translations[locale].input = value.input;
122
+ } else {
123
+ translations[locale] = value;
124
+ }
125
+ }
126
+ }
127
+ };
128
+ export const loadKeysFromBackend = async (keysMap, $i18n, backendLanguages) => {
129
+ try {
130
+ const config = useRuntimeConfig().public.shopCore;
131
+ const configId = config?.configId;
132
+ if (!configId) return;
133
+ const { data } = await useSdk().plentysystems.getAllTranslations({ configId });
134
+ const flattened = flattenTranslations(data);
135
+ for (const [lang, translations] of Object.entries(flattened)) {
136
+ if (backendLanguages && Object.keys(translations).length > 0) backendLanguages.add(lang);
137
+ for (const [key, value] of Object.entries(translations)) {
138
+ if (!keysMap.has(key)) {
139
+ keysMap.set(key, createEmptyMessage($i18n.availableLocales));
140
+ }
141
+ const localeTranslations = keysMap.get(key);
142
+ if (localeTranslations[lang]) {
143
+ localeTranslations[lang].isDeployed = localeTranslations[lang].value === value;
144
+ localeTranslations[lang].value = value;
145
+ localeTranslations[lang].input = value;
146
+ } else {
147
+ localeTranslations[lang] = {
148
+ value,
149
+ input: value,
150
+ isDeployed: false
151
+ };
152
+ }
153
+ }
154
+ }
155
+ } catch {
156
+ }
157
+ };
@@ -0,0 +1,20 @@
1
+ import type { MultilingualKeysState } from '../../types/index.js';
2
+ export declare const useEditorLocalizationKeys: () => {
3
+ updateTranslationInput: (key: string, locale: string, newInput: string) => void;
4
+ checkHasUnsavedChanges: () => boolean;
5
+ collectChangedTranslations: () => Record<string, Record<string, string>>;
6
+ loadKeys: () => Promise<void>;
7
+ getTranslatedCount: (locale: string) => {
8
+ translated: number;
9
+ undeployed: number;
10
+ total: number;
11
+ };
12
+ getCategoryFromKey: (key: string) => string;
13
+ getKeyFromFullKey: (key: string) => string;
14
+ saveLocalizations: () => Promise<void>;
15
+ keys: import("vue").Ref<MultilingualKeysState[], MultilingualKeysState[]>;
16
+ drawerOpen: import("vue").Ref<boolean, boolean>;
17
+ hasChanges: import("vue").Ref<boolean, boolean>;
18
+ backendLanguages: import("vue").Ref<Set<string>, Set<string>>;
19
+ loading: import("vue").Ref<boolean, boolean>;
20
+ };
@@ -0,0 +1,176 @@
1
+ import { useState, useNuxtApp, useRuntimeConfig } from "nuxt/app";
2
+ import { toRefs } from "vue";
3
+ import { loadDefaultKeys, loadTranslatedKeys, loadKeysFromBackend, unflattenTranslations } from "./helpers.js";
4
+ import { useSdk, useNotification, useEditorLocalizationLocales } from "#imports";
5
+ import { allLanguages } from "./useEditorLocalizationLocales.js";
6
+ export const useEditorLocalizationKeys = () => {
7
+ const state = useState("useEditorLocalizationKeys", () => ({
8
+ keys: [],
9
+ drawerOpen: false,
10
+ hasChanges: false,
11
+ backendLanguages: /* @__PURE__ */ new Set(),
12
+ loading: false
13
+ }));
14
+ const loadKeys = async () => {
15
+ if (state.value.loading) return;
16
+ const $i18n = useNuxtApp().$i18n;
17
+ state.value.loading = true;
18
+ state.value.keys = [];
19
+ state.value.backendLanguages = /* @__PURE__ */ new Set();
20
+ const keysMap = /* @__PURE__ */ new Map();
21
+ await loadDefaultKeys(keysMap, $i18n);
22
+ loadTranslatedKeys(keysMap, $i18n);
23
+ await loadKeysFromBackend(keysMap, $i18n, state.value.backendLanguages);
24
+ state.value.keys = Array.from(keysMap.entries()).map(([key, translations]) => ({
25
+ key,
26
+ translations
27
+ })).sort((a, b) => a.key.localeCompare(b.key));
28
+ state.value.loading = false;
29
+ state.value.drawerOpen = true;
30
+ };
31
+ const getTranslatedCount = (locale) => {
32
+ let translatedCount = 0;
33
+ let undeployedCount = 0;
34
+ let totalCount = state.value.keys.length;
35
+ for (const keyState of state.value.keys) {
36
+ if (keyState.translations[locale] && keyState.translations[locale].value.length > 0) {
37
+ translatedCount++;
38
+ if (!keyState.translations[locale].isDeployed) {
39
+ undeployedCount++;
40
+ }
41
+ }
42
+ }
43
+ return {
44
+ translated: translatedCount,
45
+ undeployed: undeployedCount,
46
+ total: totalCount
47
+ };
48
+ };
49
+ const getCategoryFromKey = (key) => {
50
+ const parts = key.split(".");
51
+ const category = (parts.length > 1 ? parts[0] : "uncategorized") ?? "";
52
+ return category.replace(/([A-Z])/g, " $1").replace(/^./, (match) => match.toUpperCase()).trim();
53
+ };
54
+ const getKeyFromFullKey = (key) => {
55
+ const parts = key.split(".");
56
+ return parts.length > 1 ? parts.slice(1).join(".") : key;
57
+ };
58
+ const collectChangedTranslations = () => {
59
+ const { selectedLocales } = useEditorLocalizationLocales();
60
+ if (!selectedLocales.value || selectedLocales.value.length === 0) return {};
61
+ const translationsByLocale = {};
62
+ const selectedLocalesSet = new Set(selectedLocales.value);
63
+ for (let i = 0; i < state.value.keys.length; i++) {
64
+ const keyState = state.value.keys[i];
65
+ for (const locale in keyState.translations) {
66
+ if (!selectedLocalesSet.has(locale)) continue;
67
+ const translation = keyState.translations[locale];
68
+ if (translation && translation.input && translation.input !== translation.value) {
69
+ if (!translationsByLocale[locale]) translationsByLocale[locale] = {};
70
+ translationsByLocale[locale][keyState.key] = translation.input;
71
+ }
72
+ }
73
+ }
74
+ return translationsByLocale;
75
+ };
76
+ const checkHasUnsavedChanges = () => {
77
+ const { selectedLocales } = useEditorLocalizationLocales();
78
+ if (!selectedLocales.value || selectedLocales.value.length === 0) return false;
79
+ const selectedLocalesSet = new Set(selectedLocales.value);
80
+ for (const keyState of state.value.keys) {
81
+ for (const locale in keyState.translations) {
82
+ if (!selectedLocalesSet.has(locale)) continue;
83
+ const translation = keyState.translations[locale];
84
+ if (translation && translation.input && translation.input !== translation.value) {
85
+ return true;
86
+ }
87
+ }
88
+ }
89
+ return false;
90
+ };
91
+ const updateTranslationInput = (key, locale, newInput) => {
92
+ const keyState = state.value.keys.find((k) => k.key === key);
93
+ if (!keyState || !keyState.translations[locale]) return;
94
+ const translation = keyState.translations[locale];
95
+ translation.input = newInput;
96
+ if (newInput !== translation.value) {
97
+ state.value.hasChanges = true;
98
+ } else if (state.value.hasChanges) {
99
+ state.value.hasChanges = checkHasUnsavedChanges();
100
+ }
101
+ };
102
+ const saveLanguageTranslations = async (language, configId, translations) => {
103
+ try {
104
+ const nestedTranslations = unflattenTranslations(translations);
105
+ const languageExistsInBackend = state.value.backendLanguages.has(language);
106
+ const sdk = useSdk().plentysystems;
107
+ const saveMethod = languageExistsInBackend ? sdk.patchMergeTranslations : sdk.doCreateTranslations;
108
+ await saveMethod({ configId, language, translations: nestedTranslations });
109
+ if (!languageExistsInBackend) state.value.backendLanguages.add(language);
110
+ return { language, success: true };
111
+ } catch (error) {
112
+ return { language, success: false, error };
113
+ }
114
+ };
115
+ const updateLocalStateAfterSave = (language, savedTranslations) => {
116
+ for (let i = 0; i < state.value.keys.length; i++) {
117
+ const keyState = state.value.keys[i];
118
+ const translation = keyState.translations[language];
119
+ if (translation && savedTranslations[keyState.key] !== void 0) {
120
+ translation.isDeployed = true;
121
+ translation.value = translation.input;
122
+ }
123
+ }
124
+ };
125
+ const notifySaveResults = (results) => {
126
+ const { send } = useNotification();
127
+ const successful = results.filter((r) => r.success).map((r) => allLanguages[r.language] || r.language.toUpperCase());
128
+ const failed = results.filter((r) => !r.success).map((r) => allLanguages[r.language] || r.language.toUpperCase());
129
+ if (successful.length > 0) {
130
+ send({
131
+ message: `Translations for ${successful.join(", ")} saved successfully`,
132
+ type: "positive"
133
+ });
134
+ }
135
+ if (failed.length > 0) {
136
+ send({
137
+ message: `Failed to save translations for ${failed.join(", ")}`,
138
+ type: "negative",
139
+ persist: true
140
+ });
141
+ }
142
+ };
143
+ const saveLocalizations = async () => {
144
+ const config = useRuntimeConfig().public.shopCore;
145
+ const configId = config?.configId;
146
+ if (!configId) return;
147
+ const translationsByLocale = collectChangedTranslations();
148
+ const localesToSave = Object.keys(translationsByLocale);
149
+ if (localesToSave.length === 0) return;
150
+ state.value.loading = true;
151
+ try {
152
+ const savePromises = localesToSave.map(
153
+ (language) => saveLanguageTranslations(language, configId, translationsByLocale[language])
154
+ );
155
+ const results = await Promise.all(savePromises);
156
+ results.forEach((result) => {
157
+ if (result.success) updateLocalStateAfterSave(result.language, translationsByLocale[result.language]);
158
+ });
159
+ notifySaveResults(results);
160
+ state.value.hasChanges = false;
161
+ } finally {
162
+ state.value.loading = false;
163
+ }
164
+ };
165
+ return {
166
+ ...toRefs(state.value),
167
+ updateTranslationInput,
168
+ checkHasUnsavedChanges,
169
+ collectChangedTranslations,
170
+ loadKeys,
171
+ getTranslatedCount,
172
+ getCategoryFromKey,
173
+ getKeyFromFullKey,
174
+ saveLocalizations
175
+ };
176
+ };
@@ -0,0 +1,50 @@
1
+ export declare const allLanguages: {
2
+ de: string;
3
+ en: string;
4
+ bg: string;
5
+ fr: string;
6
+ it: string;
7
+ es: string;
8
+ tr: string;
9
+ nl: string;
10
+ pl: string;
11
+ pt: string;
12
+ no: string;
13
+ ro: string;
14
+ da: string;
15
+ sv: string;
16
+ cs: string;
17
+ ru: string;
18
+ sk: string;
19
+ zh: string;
20
+ vi: string;
21
+ };
22
+ export declare const useEditorLocalizationLocales: () => {
23
+ allLanguages: {
24
+ de: string;
25
+ en: string;
26
+ bg: string;
27
+ fr: string;
28
+ it: string;
29
+ es: string;
30
+ tr: string;
31
+ nl: string;
32
+ pl: string;
33
+ pt: string;
34
+ no: string;
35
+ ro: string;
36
+ da: string;
37
+ sv: string;
38
+ cs: string;
39
+ ru: string;
40
+ sk: string;
41
+ zh: string;
42
+ vi: string;
43
+ };
44
+ selectLocale: (locale: string) => void;
45
+ removeLocale: (locale: string) => void;
46
+ toggleLocale: (locale: string) => void;
47
+ initializeLocales: () => void;
48
+ selectedLocales: import("vue").Ref<string[], string[]>;
49
+ loading: import("vue").Ref<boolean, boolean>;
50
+ };
@@ -0,0 +1,67 @@
1
+ import { useState } from "#app";
2
+ import { toRefs } from "vue";
3
+ export const allLanguages = {
4
+ de: "German (default)",
5
+ en: "English (default)",
6
+ bg: "Bulgarian",
7
+ fr: "French",
8
+ it: "Italian",
9
+ es: "Spanish",
10
+ tr: "Turkish",
11
+ nl: "Dutch",
12
+ pl: "Polish",
13
+ pt: "Portuguese",
14
+ no: "Norwegian",
15
+ ro: "Romanian",
16
+ da: "Danish",
17
+ sv: "Swedish",
18
+ cs: "Czech",
19
+ ru: "Russian",
20
+ sk: "Slovak",
21
+ zh: "Chinese",
22
+ vi: "Vietnamese"
23
+ };
24
+ export const useEditorLocalizationLocales = () => {
25
+ const state = useState("useEditorLocalizationLocales", () => ({
26
+ selectedLocales: [],
27
+ loading: false
28
+ }));
29
+ const selectLocale = (locale) => {
30
+ if (!state.value.selectedLocales.includes(locale)) {
31
+ state.value.selectedLocales.push(locale);
32
+ saveLocales();
33
+ }
34
+ };
35
+ const removeLocale = (locale) => {
36
+ state.value.selectedLocales = state.value.selectedLocales.filter((l) => l !== locale);
37
+ saveLocales();
38
+ };
39
+ const toggleLocale = (locale) => {
40
+ if (state.value.selectedLocales.includes(locale)) {
41
+ removeLocale(locale);
42
+ } else {
43
+ selectLocale(locale);
44
+ }
45
+ saveLocales();
46
+ };
47
+ const initializeLocales = () => {
48
+ const selectedLocales = localStorage.getItem("editorLocalizationSelectedLocales");
49
+ if (selectedLocales) {
50
+ const parsedLocales = JSON.parse(selectedLocales);
51
+ state.value.selectedLocales = parsedLocales.filter((l) => allLanguages.hasOwnProperty(l));
52
+ } else {
53
+ state.value.selectedLocales = ["de", "en"];
54
+ }
55
+ };
56
+ const saveLocales = () => {
57
+ localStorage.setItem("editorLocalizationSelectedLocales", JSON.stringify(state.value.selectedLocales));
58
+ };
59
+ return {
60
+ ...toRefs(state.value),
61
+ allLanguages,
62
+ selectLocale,
63
+ removeLocale,
64
+ toggleLocale,
65
+ initializeLocales
66
+ };
67
+ };
@@ -0,0 +1 @@
1
+ export declare const t: (key: string, listOrNamed?: Record<string, unknown>) => string;
@@ -0,0 +1,9 @@
1
+ import { useNuxtApp } from "nuxt/app";
2
+ export const t = (key, listOrNamed) => {
3
+ const $i18n = useNuxtApp().$i18n;
4
+ const prefix = "translated.";
5
+ if ($i18n.te(prefix + key)) {
6
+ return $i18n.t(prefix + key, listOrNamed ?? {});
7
+ }
8
+ return $i18n.t(key, listOrNamed ?? {});
9
+ };
@@ -2,3 +2,4 @@ export * from './cookies.js';
2
2
  export * from './events.js';
3
3
  export * from './render.js';
4
4
  export * from './notification.js';
5
+ export * from './localization.js';
@@ -2,3 +2,4 @@ export * from "./cookies.js";
2
2
  export * from "./events.js";
3
3
  export * from "./render.js";
4
4
  export * from "./notification.js";
5
+ export * from "./localization.js";
@@ -0,0 +1,42 @@
1
+ export type MultilingualKeysState = {
2
+ key: string;
3
+ translations: {
4
+ [locale: string]: LocalizationMessage;
5
+ };
6
+ };
7
+ export type CompiledMessage = {
8
+ type?: number;
9
+ loc?: {
10
+ source: string;
11
+ start: {
12
+ line: number;
13
+ column: number;
14
+ offset: number;
15
+ };
16
+ end: {
17
+ line: number;
18
+ column: number;
19
+ offset: number;
20
+ };
21
+ };
22
+ b?: {
23
+ s: string;
24
+ };
25
+ start?: number;
26
+ end?: number;
27
+ body?: unknown;
28
+ items?: unknown[];
29
+ };
30
+ export type LocalizationMessage = {
31
+ value: string;
32
+ input: string;
33
+ default?: string;
34
+ isDeployed: boolean;
35
+ };
36
+ export interface I18nInstance {
37
+ availableLocales: string[];
38
+ loadLocaleMessages: (locale: string) => Promise<void>;
39
+ getLocaleMessage: (locale: string) => Record<string, unknown>;
40
+ te: (key: string) => boolean;
41
+ t: (key: string, params?: Record<string, unknown>) => string;
42
+ }
File without changes
package/dist/types.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { type Cookie, type CookieGroup, type CookieGroupFromNuxtConfig, type Events, type JsonCookie, type Notification, type PaymentButtonComponent, type PaymentButtonComponentProps } from '../dist/runtime/types/index.js'
1
+ export { type Cookie, type CookieGroup, type CookieGroupFromNuxtConfig, type Events, type JsonCookie, type LocalizationMessage, type Notification, type PaymentButtonComponent, type PaymentButtonComponentProps } from '../dist/runtime/types/index.js'
2
2
 
3
3
  export { default } from './module.mjs'
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plentymarkets/shop-core",
3
- "version": "1.13.4",
3
+ "version": "1.13.5",
4
4
  "description": "Core module for PlentyONE Shop",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,6 +13,10 @@
13
13
  },
14
14
  "license": "MIT",
15
15
  "type": "module",
16
+ "engines": {
17
+ "node": ">=20.0.0",
18
+ "npm": ">=10.0.0"
19
+ },
16
20
  "exports": {
17
21
  ".": {
18
22
  "require": "./dist/module.mjs",
@@ -38,20 +42,21 @@
38
42
  "test": "vitest run",
39
43
  "test:coverage": "vitest run --coverage",
40
44
  "test:watch": "vitest watch",
41
- "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
45
+ "test:types": "vue-tsc --noEmit"
42
46
  },
43
47
  "dependencies": {
44
- "@plentymarkets/shop-api": "^0.142.0",
48
+ "@plentymarkets/shop-api": "^0.143.0",
45
49
  "@vue-storefront/sdk": "^3.4.1",
46
50
  "cookie": "^1.0.2",
47
51
  "js-sha256": "^0.11.0",
48
- "resolve": "^1.22.10"
52
+ "resolve": "^1.22.10",
53
+ "ofetch": "^1.5.1"
49
54
  },
50
55
  "overrides": {
51
56
  "prettier": "^3.6.2"
52
57
  },
53
58
  "devDependencies": {
54
- "@nuxt/devtools": "^1.7.0",
59
+ "@nuxt/devtools": "^3.1.0",
55
60
  "@nuxt/eslint-config": "^0.7.6",
56
61
  "@nuxt/kit": "^4.1.3",
57
62
  "@nuxt/module-builder": "^1.0.2",
@@ -59,19 +64,21 @@
59
64
  "@nuxt/test-utils": "^3.19.0",
60
65
  "@nuxtjs/i18n": "9.5.4",
61
66
  "@types/node": "latest",
67
+ "@typescript-eslint/parser": "^8.47.0",
62
68
  "@vitest/coverage-v8": "^3.2.4",
63
- "@vue-storefront/eslint-config": "^4.1.0",
64
69
  "@vue/test-utils": "^2.4.6",
65
70
  "changelogen": "^0.5.7",
66
71
  "eslint": "^9.24.0",
67
72
  "eslint-config-prettier": "^9.1.0",
68
73
  "eslint-plugin-vuejs-accessibility": "^2.4.1",
69
- "happy-dom": "^16.8.1",
74
+ "happy-dom": "^20.0.2",
70
75
  "nuxi": "3.17.2",
71
76
  "nuxt": "^4.1.3",
72
77
  "prettier": "^3.6.2",
73
78
  "typescript": "~5.9.2",
79
+ "typescript-eslint": "^8.47.0",
74
80
  "vitest": "^3.2.4",
81
+ "vue-eslint-parser": "^10.2.0",
75
82
  "vue-tsc": "^2.2.8"
76
83
  }
77
84
  }