@toototech/webbuilder-plugins 0.1.0
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/LICENSE +1 -0
- package/README.md +3 -0
- package/dist/basic/cssScope.d.ts +3 -0
- package/dist/basic/index.d.ts +81 -0
- package/dist/basic/injectStyle.d.ts +20 -0
- package/dist/basic/plugin.d.ts +19 -0
- package/dist/basic/publisher.d.ts +4 -0
- package/dist/basic/registries/interactive/accordion/index.d.ts +3 -0
- package/dist/basic/registries/interactive/backButton/index.d.ts +3 -0
- package/dist/basic/registries/interactive/button/index.d.ts +10 -0
- package/dist/basic/registries/interactive/countUp/index.d.ts +9 -0
- package/dist/basic/registries/interactive/customCode/index.d.ts +3 -0
- package/dist/basic/registries/interactive/index.d.ts +2 -0
- package/dist/basic/registries/interactive/inquiryForm/index.d.ts +3 -0
- package/dist/basic/registries/interactive/klaviyoSubscribe/index.d.ts +3 -0
- package/dist/basic/registries/interactive/popup/index.d.ts +5 -0
- package/dist/basic/registries/interactive/salesmartlyChatButton/index.d.ts +10 -0
- package/dist/basic/registries/interactive/search/index.d.ts +10 -0
- package/dist/basic/registries/interactive/socialShare/index.d.ts +33 -0
- package/dist/basic/registries/interactive/tabs/index.d.ts +3 -0
- package/dist/basic/registries/layout/container/index.d.ts +19 -0
- package/dist/basic/registries/layout/divider/index.d.ts +7 -0
- package/dist/basic/registries/layout/grid/index.d.ts +11 -0
- package/dist/basic/registries/layout/index.d.ts +2 -0
- package/dist/basic/registries/layout/layoutBase/index.d.ts +10 -0
- package/dist/basic/registries/layout/section/index.d.ts +3 -0
- package/dist/basic/registries/layout/sectionGridBlock/index.d.ts +3 -0
- package/dist/basic/registries/layout/spacer/index.d.ts +7 -0
- package/dist/basic/registries/media/banner/index.d.ts +11 -0
- package/dist/basic/registries/media/carousel/index.d.ts +6 -0
- package/dist/basic/registries/media/flipbook/index.d.ts +5 -0
- package/dist/basic/registries/media/icon/index.d.ts +3 -0
- package/dist/basic/registries/media/image/index.d.ts +3 -0
- package/dist/basic/registries/media/index.d.ts +2 -0
- package/dist/basic/registries/media/industryTabs/index.d.ts +3 -0
- package/dist/basic/registries/media/marquee/index.d.ts +4 -0
- package/dist/basic/registries/media/ourSolutions/helpers.d.ts +289 -0
- package/dist/basic/registries/media/ourSolutions/index.d.ts +4 -0
- package/dist/basic/registries/media/ourSolutions/script.d.ts +1 -0
- package/dist/basic/registries/media/ourSolutions/style.d.ts +1 -0
- package/dist/basic/registries/media/pdfViewer/index.d.ts +3 -0
- package/dist/basic/registries/media/productCategories/index.d.ts +4 -0
- package/dist/basic/registries/media/tabMediaGallery/index.d.ts +3 -0
- package/dist/basic/registries/media/video/index.d.ts +12 -0
- package/dist/basic/registries/navigation/footer/index.d.ts +10 -0
- package/dist/basic/registries/navigation/index.d.ts +2 -0
- package/dist/basic/registries/navigation/languageSwitcher/index.d.ts +6 -0
- package/dist/basic/registries/navigation/logo/index.d.ts +9 -0
- package/dist/basic/registries/navigation/navbar/constants.d.ts +38 -0
- package/dist/basic/registries/navigation/navbar/factories.d.ts +848 -0
- package/dist/basic/registries/navigation/navbar/helpers.d.ts +12 -0
- package/dist/basic/registries/navigation/navbar/index.d.ts +4 -0
- package/dist/basic/registries/navigation/navbar/registerMegaTypes.d.ts +2 -0
- package/dist/basic/registries/navigation/navbar/registerMenuTypes.d.ts +2 -0
- package/dist/basic/registries/navigation/navbar/registerRootTypes.d.ts +2 -0
- package/dist/basic/registries/navigation/navbar/script.d.ts +1 -0
- package/dist/basic/registries/navigation/navbar/style.d.ts +1 -0
- package/dist/basic/registries/navigation/socialLinks/index.d.ts +3 -0
- package/dist/basic/registries/section/allApplications/index.d.ts +3 -0
- package/dist/basic/registries/section/cardCarouselSection/index.d.ts +3 -0
- package/dist/basic/registries/section/caseSpotlight/index.d.ts +3 -0
- package/dist/basic/registries/section/companyScale/index.d.ts +3 -0
- package/dist/basic/registries/section/customizationGrid/index.d.ts +3 -0
- package/dist/basic/registries/section/factoryMap/index.d.ts +3 -0
- package/dist/basic/registries/section/focaHistoryTimeline/index.d.ts +3 -0
- package/dist/basic/registries/section/historyTimeline/index.d.ts +3 -0
- package/dist/basic/registries/section/homeBannerCarousel/index.d.ts +4 -0
- package/dist/basic/registries/section/hotspotShowcase/index.d.ts +30 -0
- package/dist/basic/registries/section/index.d.ts +2 -0
- package/dist/basic/registries/section/map/index.d.ts +4 -0
- package/dist/basic/registries/section/milestoneCardStrip/index.d.ts +3 -0
- package/dist/basic/registries/section/moreCardCarousel/index.d.ts +3 -0
- package/dist/basic/registries/section/ourAdvantages/index.d.ts +4 -0
- package/dist/basic/registries/section/overviewSplit/index.d.ts +3 -0
- package/dist/basic/registries/section/processTimeline/index.d.ts +3 -0
- package/dist/basic/registries/section/productCardStrip/index.d.ts +3 -0
- package/dist/basic/registries/section/resourceSection/index.d.ts +6 -0
- package/dist/basic/registries/section/responsiveHeroCarousel/index.d.ts +4 -0
- package/dist/basic/registries/section/serviceIconGrid/index.d.ts +4 -0
- package/dist/basic/registries/section/servicesCarousel/index.d.ts +4 -0
- package/dist/basic/registries/section/servicesShowcase/index.d.ts +4 -0
- package/dist/basic/registries/section/servicesThb/index.d.ts +4 -0
- package/dist/basic/registries/section/solutionList/index.d.ts +4 -0
- package/dist/basic/registries/section/staticPinMap/index.d.ts +4 -0
- package/dist/basic/registries/section/statsCards/index.d.ts +3 -0
- package/dist/basic/registries/section/swiperRuntime.d.ts +3 -0
- package/dist/basic/registries/shared/sharedTraits.d.ts +37 -0
- package/dist/basic/registries/types.d.ts +5 -0
- package/dist/basic/registries/typography/heading/index.d.ts +8 -0
- package/dist/basic/registries/typography/index.d.ts +2 -0
- package/dist/basic/registries/typography/textEditor/index.d.ts +6 -0
- package/dist/basic/registryManifest.d.ts +9 -0
- package/dist/basic/styleHelpers.d.ts +29 -0
- package/dist/basic/svgIcon.d.ts +11 -0
- package/dist/basic/traitBridge.d.ts +20 -0
- package/dist/basic/traitFactory.d.ts +106 -0
- package/dist/basic.js +1146 -0
- package/dist/cms/cmsFactory.d.ts +164 -0
- package/dist/cms/dynamicRenderPipeline.d.ts +12 -0
- package/dist/cms/index.d.ts +31 -0
- package/dist/cms/plugin.d.ts +12 -0
- package/dist/cms/publisher.d.ts +7 -0
- package/dist/cms/registries/dynamic/cms/constants.d.ts +16 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/bindings.d.ts +78 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/breadcrumbBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/conditionalBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/datetimeBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/htmlBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/imageBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/linkBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/seoBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/textBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/blocks/tocBlock.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/constants.d.ts +19 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/helpers.d.ts +52 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/registerBlock.d.ts +57 -0
- package/dist/cms/registries/dynamic/cms/dynamicField/styles.d.ts +7 -0
- package/dist/cms/registries/dynamic/cms/media/previewMediaTrait.d.ts +7 -0
- package/dist/cms/registries/dynamic/cms/menu/siteMenuAttrs.d.ts +11 -0
- package/dist/cms/registries/dynamic/cms/menuTree/menuTreeAttrs.d.ts +8 -0
- package/dist/cms/registries/dynamic/cms/post/styles.d.ts +6 -0
- package/dist/cms/registries/dynamic/cms/product/detail.styles.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/product/detailV2.styles.d.ts +1 -0
- package/dist/cms/registries/dynamic/cms/product/previewProductTrait.d.ts +6 -0
- package/dist/cms/registries/dynamic/cms/product/styles.d.ts +6 -0
- package/dist/cms/registries/dynamic/dataProvider.d.ts +45 -0
- package/dist/cms/registries/dynamic/loopGrid/paginationStyles.d.ts +5 -0
- package/dist/cms/registries/dynamic/loopGrid/preview.d.ts +16 -0
- package/dist/cms/registries/dynamic/loopGrid/publisher.d.ts +3 -0
- package/dist/cms/registries/dynamic/loopGrid/types.d.ts +97 -0
- package/dist/cms/registries/navigation/navbarThb/index.d.ts +3 -0
- package/dist/cms/registries/navigation/navbarThb/script.d.ts +1 -0
- package/dist/cms/registries/navigation/navbarThb/style.d.ts +1 -0
- package/dist/cms.js +4535 -0
- package/dist/global-settings/components/FontFamilySelect.vue.d.ts +29 -0
- package/dist/global-settings/components/FontManagerPanel.vue.d.ts +37 -0
- package/dist/global-settings/index.d.ts +8 -0
- package/dist/global-settings/plugin.d.ts +3 -0
- package/dist/global-settings/publisher.d.ts +15 -0
- package/dist/global-settings/runtime/canvasInjection.d.ts +13 -0
- package/dist/global-settings/runtime/panelDraftSave.d.ts +17 -0
- package/dist/global-settings/runtime/settingsSource.d.ts +4 -0
- package/dist/global-settings/useFontManager.d.ts +38 -0
- package/dist/global-settings/useGoogleFonts.d.ts +20 -0
- package/dist/global-settings/vue.d.ts +1 -0
- package/dist/global-settings.js +66 -0
- package/dist/i18n/I18nPanel.vue.d.ts +23 -0
- package/dist/i18n/i18n.d.ts +25 -0
- package/dist/i18n/index.d.ts +7 -0
- package/dist/i18n/languageOrder.d.ts +9 -0
- package/dist/i18n/plugin.d.ts +21 -0
- package/dist/i18n/types.d.ts +101 -0
- package/dist/i18n/useWebBuilderI18n.d.ts +164 -0
- package/dist/i18n/vue.d.ts +1 -0
- package/dist/i18n-BYR3l48y.js +959 -0
- package/dist/i18n.js +929 -0
- package/dist/index-CxJlLwvG.js +35378 -0
- package/dist/index-DWfJ4PBm.js +5724 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +12 -0
- package/dist/layout-template/components/LayoutPanel.vue.d.ts +37 -0
- package/dist/layout-template/components/TemplateRulesPanel.vue.d.ts +41 -0
- package/dist/layout-template/config/layoutSharedResources.d.ts +9 -0
- package/dist/layout-template/config/templateSharedResources.d.ts +28 -0
- package/dist/layout-template/index.d.ts +9 -0
- package/dist/layout-template/plugin.d.ts +13 -0
- package/dist/layout-template/runtime/storageAdapter.d.ts +49 -0
- package/dist/layout-template/utils/layoutProjectData.d.ts +15 -0
- package/dist/layout-template/utils/layoutRulePages.d.ts +19 -0
- package/dist/layout-template/utils/layoutSettings.d.ts +45 -0
- package/dist/layout-template/utils/templateRules.d.ts +52 -0
- package/dist/layout-template/vue.d.ts +2 -0
- package/dist/layout-template.js +435 -0
- package/dist/layoutSettings-D4SYUMri.js +252 -0
- package/dist/plugin-BPA8qlaC.js +40 -0
- package/dist/plugin-C0PrxrIe.js +228 -0
- package/dist/plugin-DQshk1sY.js +361 -0
- package/dist/plugin-DebyCjXx.js +191 -0
- package/dist/plugin-Dr6TOtyH.js +73 -0
- package/dist/publisher/index.d.ts +5 -0
- package/dist/publisher/publisherAssets.d.ts +9 -0
- package/dist/publisher/publisherComponents.d.ts +7 -0
- package/dist/publisher/publisherPlugins.d.ts +12 -0
- package/dist/publisher-C6VWXq8u.js +25 -0
- package/dist/publisher.js +1711 -0
- package/dist/solar-BsElUqfQ.js +29843 -0
- package/dist/style.css +1181 -0
- package/dist/templateSharedResources-D1u7eFIs.js +89 -0
- package/dist/types-DNbok59z.js +2359 -0
- package/dist/useFontManager-CdrLq1eG.js +336 -0
- package/dist/vue.d.ts +3 -0
- package/dist/vue.js +2171 -0
- package/package.json +77 -0
|
@@ -0,0 +1,959 @@
|
|
|
1
|
+
const WB_I18N_KEY_ATTR = "data-wb-i18n-key";
|
|
2
|
+
const WB_I18N_SKIP_ATTR = "data-wb-i18n-skip";
|
|
3
|
+
const TRANSLATION_ONLY_KEYS = /* @__PURE__ */ new Set(["wbI18nTranslations", "i18nTranslations", "__wbI18nPreview"]);
|
|
4
|
+
const TRANSLATION_ONLY_ATTRS = /* @__PURE__ */ new Set(["data-wb-i18n-locale", "data-wb-i18n-translation"]);
|
|
5
|
+
const ATTRIBUTE_FIELDS = [
|
|
6
|
+
{ field: "alt", attr: "alt" },
|
|
7
|
+
{ field: "title", attr: "title" },
|
|
8
|
+
{ field: "placeholder", attr: "placeholder" },
|
|
9
|
+
{ field: "aria-label", attr: "aria-label" }
|
|
10
|
+
];
|
|
11
|
+
const PROP_FIELD_PREFIX = "prop:";
|
|
12
|
+
const STRUCTURAL_COMPONENT_KEYS = /* @__PURE__ */ new Set([
|
|
13
|
+
"attributes",
|
|
14
|
+
"components",
|
|
15
|
+
"content",
|
|
16
|
+
"style",
|
|
17
|
+
"styles",
|
|
18
|
+
"script",
|
|
19
|
+
"script-props",
|
|
20
|
+
"classes",
|
|
21
|
+
"selectors",
|
|
22
|
+
"traits",
|
|
23
|
+
"toolbar",
|
|
24
|
+
"type",
|
|
25
|
+
"tagName",
|
|
26
|
+
"void",
|
|
27
|
+
"removable",
|
|
28
|
+
"copyable",
|
|
29
|
+
"selectable",
|
|
30
|
+
"draggable",
|
|
31
|
+
"droppable",
|
|
32
|
+
"editable",
|
|
33
|
+
"stylable",
|
|
34
|
+
"unstylable"
|
|
35
|
+
]);
|
|
36
|
+
const INTERNAL_VISIBLE_CONFIG_KEYS = /* @__PURE__ */ new Set(["fmMenuTitle"]);
|
|
37
|
+
const NON_PROJECT_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
38
|
+
"_changing",
|
|
39
|
+
"_events",
|
|
40
|
+
"_listenId",
|
|
41
|
+
"_listeners",
|
|
42
|
+
"_pending",
|
|
43
|
+
"_previousAttributes",
|
|
44
|
+
"changed",
|
|
45
|
+
"children",
|
|
46
|
+
"collection",
|
|
47
|
+
"delegate",
|
|
48
|
+
"editor",
|
|
49
|
+
"el",
|
|
50
|
+
"em",
|
|
51
|
+
"model",
|
|
52
|
+
"models",
|
|
53
|
+
"parent",
|
|
54
|
+
"previousModels",
|
|
55
|
+
"view",
|
|
56
|
+
"views",
|
|
57
|
+
"$el"
|
|
58
|
+
]);
|
|
59
|
+
const MAX_CONFIG_SCAN_DEPTH = 12;
|
|
60
|
+
const MAX_CONFIG_VALUE_COUNT = 200;
|
|
61
|
+
const MAX_MODEL_KEY_SCAN_NODES = 3e3;
|
|
62
|
+
const MAX_PROJECT_SCAN_NODES = 12e3;
|
|
63
|
+
const MODEL_VISIBLE_CONFIG_KEYS = [
|
|
64
|
+
"ariaLabel",
|
|
65
|
+
"caption",
|
|
66
|
+
"description",
|
|
67
|
+
"emptyText",
|
|
68
|
+
"errorMessage",
|
|
69
|
+
"eyebrow",
|
|
70
|
+
"heading",
|
|
71
|
+
"label",
|
|
72
|
+
"linkText",
|
|
73
|
+
"placeholder",
|
|
74
|
+
"subtitle",
|
|
75
|
+
"successMessage",
|
|
76
|
+
"summary",
|
|
77
|
+
"text",
|
|
78
|
+
"title",
|
|
79
|
+
"buttonText",
|
|
80
|
+
"ctaText",
|
|
81
|
+
"submitText",
|
|
82
|
+
"moreText"
|
|
83
|
+
];
|
|
84
|
+
const MODEL_VISIBLE_CONFIG_OBJECT_KEYS = ["inquiryI18nTexts"];
|
|
85
|
+
const VISIBLE_KEY_PATTERN = /(ariaLabel|aria-label|alt|caption|description|emptyText|errorMessage|eyebrow|heading|label|linkText|name|placeholder|subtitle|successMessage|summary|text|title|buttonText|ctaText|submitText|moreText)$/i;
|
|
86
|
+
const NON_TRANSLATABLE_KEY_PATTERN = /(url|href|src|path|route|resource|id|key|type|target|mode|sort|order|index|count|width|height|color|icon|image|file|mime|query|filter|code|class|style|css|js|html)$/i;
|
|
87
|
+
const TEXT_NODE_TYPES = /* @__PURE__ */ new Set(["textnode", "#text"]);
|
|
88
|
+
const GENERATED_CHILD_TRANSLATION_OWNER_TYPES = /* @__PURE__ */ new Set(["wb-image", "wb-inquiry-form"]);
|
|
89
|
+
const WB_LAYOUT_PAGE_CUSTOM_KEY = "wbLayoutSlot";
|
|
90
|
+
const WB_LAYOUT_PAGE_ID_CUSTOM_KEY = "wbLayoutPageId";
|
|
91
|
+
const getPageLayoutSlot = (page) => {
|
|
92
|
+
var _a, _b, _c;
|
|
93
|
+
const custom = ((_a = page == null ? void 0 : page.get) == null ? void 0 : _a.call(page, "custom")) ?? (page == null ? void 0 : page.custom) ?? {};
|
|
94
|
+
const slot = custom == null ? void 0 : custom[WB_LAYOUT_PAGE_CUSTOM_KEY];
|
|
95
|
+
if (slot === "header" || slot === "footer")
|
|
96
|
+
return slot;
|
|
97
|
+
const layoutPageId = `${(custom == null ? void 0 : custom[WB_LAYOUT_PAGE_ID_CUSTOM_KEY]) ?? ((_b = page == null ? void 0 : page.get) == null ? void 0 : _b.call(page, "id")) ?? (page == null ? void 0 : page.id) ?? ""}`.trim();
|
|
98
|
+
if (/^wb-header(?:-\d+)?$/.test(layoutPageId))
|
|
99
|
+
return "header";
|
|
100
|
+
if (/^wb-footer(?:-\d+)?$/.test(layoutPageId))
|
|
101
|
+
return "footer";
|
|
102
|
+
const name = `${((_c = page == null ? void 0 : page.get) == null ? void 0 : _c.call(page, "name")) ?? (page == null ? void 0 : page.name) ?? ""}`.trim();
|
|
103
|
+
if (/^Header(?:\s+\d+)?$/.test(name))
|
|
104
|
+
return "header";
|
|
105
|
+
if (/^Footer(?:\s+\d+)?$/.test(name))
|
|
106
|
+
return "footer";
|
|
107
|
+
return null;
|
|
108
|
+
};
|
|
109
|
+
const SEO_FIELDS = [
|
|
110
|
+
{ field: "seo.title", customKey: "tdkTitle", legacyKey: "title" },
|
|
111
|
+
{ field: "seo.description", customKey: "tdkDescription", legacyKey: "description" },
|
|
112
|
+
{ field: "seo.keywords", customKey: "tdkKeywords", legacyKey: "keywords" }
|
|
113
|
+
];
|
|
114
|
+
const toArray = (value) => {
|
|
115
|
+
if (Array.isArray(value))
|
|
116
|
+
return value;
|
|
117
|
+
if (Array.isArray(value == null ? void 0 : value.models))
|
|
118
|
+
return value.models;
|
|
119
|
+
return [];
|
|
120
|
+
};
|
|
121
|
+
const normalizeText = (value) => `${value ?? ""}`.replace(/\s+/g, " ").trim();
|
|
122
|
+
const isTruthyAttr = (value) => /^(1|true|yes|on)$/i.test(`${value ?? ""}`.trim());
|
|
123
|
+
const isNoTranslateAttr = (value) => /^no$/i.test(`${value ?? ""}`.trim());
|
|
124
|
+
const getClassNames = (attrs) => `${(attrs == null ? void 0 : attrs.class) ?? ""}`.split(/\s+/).filter(Boolean);
|
|
125
|
+
const isCmsDynamicContentAttrs = (attrs) => {
|
|
126
|
+
if (!attrs || typeof attrs !== "object")
|
|
127
|
+
return false;
|
|
128
|
+
return Boolean(normalizeText(attrs["data-cms-html"])) || Boolean(normalizeText(attrs["data-cms-repeat"])) || getClassNames(attrs).includes("wb-footer-menu__list");
|
|
129
|
+
};
|
|
130
|
+
const isNonTranslatableLiteral = (value) => {
|
|
131
|
+
const normalized = normalizeText(value);
|
|
132
|
+
if (!normalized)
|
|
133
|
+
return false;
|
|
134
|
+
if (!/[\p{L}\p{N}]/u.test(normalized))
|
|
135
|
+
return true;
|
|
136
|
+
if (/^(?:https?:|mailto:|tel:|data:|javascript:|\/|\.\/|#)/i.test(normalized))
|
|
137
|
+
return true;
|
|
138
|
+
if (/^[\w.+-]+@[\w.-]+\.[a-z]{2,}$/i.test(normalized))
|
|
139
|
+
return true;
|
|
140
|
+
if (/^\+?[\d\s().-]{6,}$/.test(normalized))
|
|
141
|
+
return true;
|
|
142
|
+
return false;
|
|
143
|
+
};
|
|
144
|
+
const isIdentityTranslationAllowed = (source) => {
|
|
145
|
+
const normalized = normalizeText(source);
|
|
146
|
+
if (!normalized)
|
|
147
|
+
return false;
|
|
148
|
+
if (isNonTranslatableLiteral(normalized))
|
|
149
|
+
return true;
|
|
150
|
+
let hasLetter = false;
|
|
151
|
+
let hasLowercase = false;
|
|
152
|
+
for (const char of normalized) {
|
|
153
|
+
if (!new RegExp("\\p{L}", "u").test(char))
|
|
154
|
+
continue;
|
|
155
|
+
hasLetter = true;
|
|
156
|
+
if (char.toLocaleLowerCase() === char && char.toLocaleUpperCase() !== char) {
|
|
157
|
+
hasLowercase = true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (!hasLetter)
|
|
161
|
+
return true;
|
|
162
|
+
if (hasLowercase)
|
|
163
|
+
return false;
|
|
164
|
+
return /^[A-Z0-9][A-Z0-9\s+\-_/&.()]*$/.test(normalized);
|
|
165
|
+
};
|
|
166
|
+
const isUnchangedNonIdentityTranslation = (source, translation) => {
|
|
167
|
+
const normalizedSource = normalizeText(source);
|
|
168
|
+
const normalizedTranslation = normalizeText(translation);
|
|
169
|
+
if (!normalizedSource || !normalizedTranslation)
|
|
170
|
+
return false;
|
|
171
|
+
return normalizedSource.toLocaleLowerCase() === normalizedTranslation.toLocaleLowerCase() && !isIdentityTranslationAllowed(normalizedSource);
|
|
172
|
+
};
|
|
173
|
+
const isExplicitTranslatedIdentity = (source, saved) => (saved == null ? void 0 : saved.status) === "translated" && (!saved.sourceHash || saved.sourceHash === source.sourceHash) && isUnchangedNonIdentityTranslation(source.source, saved.translation);
|
|
174
|
+
const hasHtmlTag = (value) => /<[a-z][\s\S]*>/i.test(value);
|
|
175
|
+
const encodePropPath = (segments) => segments.map((segment) => encodeURIComponent(String(segment))).join("/");
|
|
176
|
+
const decodePropPath = (path) => path.split("/").filter(Boolean).map((segment) => {
|
|
177
|
+
const decoded = decodeURIComponent(segment);
|
|
178
|
+
return /^\d+$/.test(decoded) ? Number(decoded) : decoded;
|
|
179
|
+
});
|
|
180
|
+
const makePropField = (segments) => `${PROP_FIELD_PREFIX}${encodePropPath(segments)}`;
|
|
181
|
+
const isPropField = (field) => `${field}`.startsWith(PROP_FIELD_PREFIX);
|
|
182
|
+
const CANONICAL_TEXT_COMPONENT_FIELD = makePropField(["components", 0, "content"]);
|
|
183
|
+
const entryId = (entry) => `${entry.key}::${entry.field}`;
|
|
184
|
+
const getWebBuilderI18nEntryId = entryId;
|
|
185
|
+
const hashI18nSource = (source) => {
|
|
186
|
+
let hash = 2166136261;
|
|
187
|
+
const normalized = `${source ?? ""}`;
|
|
188
|
+
for (let i = 0; i < normalized.length; i += 1) {
|
|
189
|
+
hash ^= normalized.charCodeAt(i);
|
|
190
|
+
hash = Math.imul(hash, 16777619);
|
|
191
|
+
}
|
|
192
|
+
return (hash >>> 0).toString(36);
|
|
193
|
+
};
|
|
194
|
+
const makeKey = (seed) => `wb_${hashI18nSource(seed)}`;
|
|
195
|
+
const clonePlain = (value) => JSON.parse(JSON.stringify(value ?? null));
|
|
196
|
+
const getComponentAttrs = (component) => {
|
|
197
|
+
var _a, _b;
|
|
198
|
+
return ((_a = component == null ? void 0 : component.getAttributes) == null ? void 0 : _a.call(component)) ?? ((_b = component == null ? void 0 : component.get) == null ? void 0 : _b.call(component, "attributes")) ?? (component == null ? void 0 : component.attributes) ?? {};
|
|
199
|
+
};
|
|
200
|
+
const setComponentAttrs = (component, attrs) => {
|
|
201
|
+
var _a;
|
|
202
|
+
if (component == null ? void 0 : component.addAttributes) {
|
|
203
|
+
component.addAttributes(attrs);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const current = getComponentAttrs(component);
|
|
207
|
+
(_a = component == null ? void 0 : component.set) == null ? void 0 : _a.call(component, "attributes", { ...current, ...attrs });
|
|
208
|
+
};
|
|
209
|
+
const removeComponentAttrs = (component, attrs) => {
|
|
210
|
+
if (component == null ? void 0 : component.removeAttributes) {
|
|
211
|
+
component.removeAttributes(attrs);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const current = getComponentAttrs(component);
|
|
215
|
+
const next = { ...current };
|
|
216
|
+
attrs.forEach((attr) => {
|
|
217
|
+
delete next[attr];
|
|
218
|
+
});
|
|
219
|
+
if (component == null ? void 0 : component.set) {
|
|
220
|
+
component.set("attributes", next);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
attrs.forEach((attr) => {
|
|
224
|
+
delete current[attr];
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
const getModelChildren = (component) => {
|
|
228
|
+
var _a, _b;
|
|
229
|
+
const children = ((_a = component == null ? void 0 : component.components) == null ? void 0 : _a.call(component)) ?? ((_b = component == null ? void 0 : component.get) == null ? void 0 : _b.call(component, "components")) ?? [];
|
|
230
|
+
return toArray(children);
|
|
231
|
+
};
|
|
232
|
+
const getModelParent = (component) => {
|
|
233
|
+
var _a, _b, _c;
|
|
234
|
+
if (!component || typeof component !== "object")
|
|
235
|
+
return null;
|
|
236
|
+
return ((_a = component.parent) == null ? void 0 : _a.call(component)) ?? ((_b = component.collection) == null ? void 0 : _b.parent) ?? ((_c = component.get) == null ? void 0 : _c.call(component, "parent")) ?? null;
|
|
237
|
+
};
|
|
238
|
+
const getProjectChildren = (component) => {
|
|
239
|
+
return Array.isArray(component == null ? void 0 : component.components) ? component.components : [];
|
|
240
|
+
};
|
|
241
|
+
const getComponentType = (component) => {
|
|
242
|
+
var _a;
|
|
243
|
+
return `${((_a = component == null ? void 0 : component.get) == null ? void 0 : _a.call(component, "type")) ?? (component == null ? void 0 : component.type) ?? (component == null ? void 0 : component.tagName) ?? ""}`.trim();
|
|
244
|
+
};
|
|
245
|
+
const isTextElementComponent = (component) => getComponentType(component).toLowerCase() === "text";
|
|
246
|
+
const isTextNodeComponent = (component) => TEXT_NODE_TYPES.has(getComponentType(component).toLowerCase());
|
|
247
|
+
const ownsGeneratedTranslatableChildren = (component) => GENERATED_CHILD_TRANSLATION_OWNER_TYPES.has(getComponentType(component));
|
|
248
|
+
const isI18nSkippedAttrs = (attrs) => {
|
|
249
|
+
if (!attrs || typeof attrs !== "object")
|
|
250
|
+
return false;
|
|
251
|
+
return isTruthyAttr(attrs[WB_I18N_SKIP_ATTR]) || isNoTranslateAttr(attrs.translate) || getClassNames(attrs).includes("notranslate") || isCmsDynamicContentAttrs(attrs);
|
|
252
|
+
};
|
|
253
|
+
const isModelNodeI18nSkipped = (component) => isI18nSkippedAttrs(getComponentAttrs(component));
|
|
254
|
+
const isProjectNodeI18nSkipped = (component) => isI18nSkippedAttrs((component == null ? void 0 : component.attributes) ?? {});
|
|
255
|
+
const getModelI18nControlTarget = (component) => {
|
|
256
|
+
if (!component || typeof component !== "object")
|
|
257
|
+
return null;
|
|
258
|
+
if (!isTextNodeComponent(component))
|
|
259
|
+
return component;
|
|
260
|
+
return getModelParent(component) ?? component;
|
|
261
|
+
};
|
|
262
|
+
const isModelI18nSkipped = (component) => {
|
|
263
|
+
let current = component;
|
|
264
|
+
let depth = 0;
|
|
265
|
+
while (current && typeof current === "object" && depth < 20) {
|
|
266
|
+
if (isModelNodeI18nSkipped(current))
|
|
267
|
+
return true;
|
|
268
|
+
current = getModelParent(current);
|
|
269
|
+
depth += 1;
|
|
270
|
+
}
|
|
271
|
+
return false;
|
|
272
|
+
};
|
|
273
|
+
const setModelI18nSkipped = (component, skipped) => {
|
|
274
|
+
const target = getModelI18nControlTarget(component);
|
|
275
|
+
if (!target)
|
|
276
|
+
return false;
|
|
277
|
+
if (skipped) {
|
|
278
|
+
setComponentAttrs(target, {
|
|
279
|
+
[WB_I18N_SKIP_ATTR]: "true",
|
|
280
|
+
translate: "no"
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
removeComponentAttrs(target, [WB_I18N_SKIP_ATTR]);
|
|
284
|
+
if (isNoTranslateAttr(getComponentAttrs(target).translate)) {
|
|
285
|
+
removeComponentAttrs(target, ["translate"]);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return true;
|
|
289
|
+
};
|
|
290
|
+
const getComponentLabel = (component) => {
|
|
291
|
+
var _a;
|
|
292
|
+
const attrs = getComponentAttrs(component);
|
|
293
|
+
return `${((_a = component == null ? void 0 : component.get) == null ? void 0 : _a.call(component, "name")) ?? (component == null ? void 0 : component.name) ?? ""}`.trim() || `${attrs.class ?? attrs.id ?? getComponentType(component) ?? "Component"}`.trim();
|
|
294
|
+
};
|
|
295
|
+
const getDirectTextSourceFromModel = (component) => {
|
|
296
|
+
var _a, _b;
|
|
297
|
+
const content = (_a = component == null ? void 0 : component.get) == null ? void 0 : _a.call(component, "content");
|
|
298
|
+
if (typeof content === "string" && normalizeText(content))
|
|
299
|
+
return content;
|
|
300
|
+
const children = (_b = component == null ? void 0 : component.get) == null ? void 0 : _b.call(component, "components");
|
|
301
|
+
if (typeof children === "string" && normalizeText(children))
|
|
302
|
+
return children;
|
|
303
|
+
return "";
|
|
304
|
+
};
|
|
305
|
+
const getDirectTextSourceFromProject = (component) => {
|
|
306
|
+
if (typeof (component == null ? void 0 : component.content) === "string" && normalizeText(component.content)) {
|
|
307
|
+
return component.content;
|
|
308
|
+
}
|
|
309
|
+
if (typeof (component == null ? void 0 : component.components) === "string" && normalizeText(component.components)) {
|
|
310
|
+
return component.components;
|
|
311
|
+
}
|
|
312
|
+
return "";
|
|
313
|
+
};
|
|
314
|
+
const getDirectTextFieldFromProject = (component, source) => {
|
|
315
|
+
if (isTextElementComponent(component) && normalizeText(source)) {
|
|
316
|
+
return CANONICAL_TEXT_COMPONENT_FIELD;
|
|
317
|
+
}
|
|
318
|
+
return hasHtmlTag(source) ? "html" : "text";
|
|
319
|
+
};
|
|
320
|
+
const isLikelyTranslatableConfigString = (value) => {
|
|
321
|
+
const normalized = normalizeText(value);
|
|
322
|
+
if (!normalized)
|
|
323
|
+
return false;
|
|
324
|
+
if (/^#(?:[0-9a-f]{3,8})$/i.test(normalized))
|
|
325
|
+
return false;
|
|
326
|
+
if (isNonTranslatableLiteral(normalized))
|
|
327
|
+
return false;
|
|
328
|
+
if (/^<svg[\s>]/i.test(normalized))
|
|
329
|
+
return false;
|
|
330
|
+
if (/^[\w-]+\/[\w./-]+$/.test(normalized))
|
|
331
|
+
return false;
|
|
332
|
+
if (/^\{\{[\s\S]*\}\}$/.test(normalized))
|
|
333
|
+
return false;
|
|
334
|
+
if (/^[\d\s.,:%+*/()[\]-]+$/.test(normalized))
|
|
335
|
+
return false;
|
|
336
|
+
return true;
|
|
337
|
+
};
|
|
338
|
+
const isAltLikeField = (field) => {
|
|
339
|
+
const normalized = `${field}`.replace(/^prop:/, "");
|
|
340
|
+
return field === "alt" || /(?:^|\/)(?:alt|imageAlt)$/i.test(normalized);
|
|
341
|
+
};
|
|
342
|
+
const isNonTranslatableEntry = (entry) => {
|
|
343
|
+
const source = normalizeText(entry.source);
|
|
344
|
+
if (!source)
|
|
345
|
+
return false;
|
|
346
|
+
if (isAltLikeField(entry.field) && source.toLocaleLowerCase() === "logo")
|
|
347
|
+
return true;
|
|
348
|
+
return false;
|
|
349
|
+
};
|
|
350
|
+
const isVisibleConfigKey = (key, path) => {
|
|
351
|
+
if (!VISIBLE_KEY_PATTERN.test(key))
|
|
352
|
+
return false;
|
|
353
|
+
if (NON_TRANSLATABLE_KEY_PATTERN.test(key) && !/(alt|ariaLabel|aria-label|label|name|placeholder|text|title|description)$/i.test(key)) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
if (path.length === 1 && key === "name")
|
|
357
|
+
return false;
|
|
358
|
+
return true;
|
|
359
|
+
};
|
|
360
|
+
const collectVisibleConfigValues = (value, basePath = [], result = [], seen = /* @__PURE__ */ new WeakSet()) => {
|
|
361
|
+
if (basePath.length > MAX_CONFIG_SCAN_DEPTH)
|
|
362
|
+
return result;
|
|
363
|
+
if (result.length >= MAX_CONFIG_VALUE_COUNT)
|
|
364
|
+
return result;
|
|
365
|
+
if (Array.isArray(value)) {
|
|
366
|
+
if (seen.has(value))
|
|
367
|
+
return result;
|
|
368
|
+
seen.add(value);
|
|
369
|
+
value.some((item, index) => {
|
|
370
|
+
collectVisibleConfigValues(item, [...basePath, index], result, seen);
|
|
371
|
+
return result.length >= MAX_CONFIG_VALUE_COUNT;
|
|
372
|
+
});
|
|
373
|
+
return result;
|
|
374
|
+
}
|
|
375
|
+
if (!value || typeof value !== "object")
|
|
376
|
+
return result;
|
|
377
|
+
if (seen.has(value))
|
|
378
|
+
return result;
|
|
379
|
+
seen.add(value);
|
|
380
|
+
Object.entries(value).some(([key, childValue]) => {
|
|
381
|
+
if (STRUCTURAL_COMPONENT_KEYS.has(key))
|
|
382
|
+
return;
|
|
383
|
+
if (INTERNAL_VISIBLE_CONFIG_KEYS.has(key))
|
|
384
|
+
return;
|
|
385
|
+
if (NON_PROJECT_CONFIG_KEYS.has(key))
|
|
386
|
+
return;
|
|
387
|
+
const path = [...basePath, key];
|
|
388
|
+
if (typeof childValue === "string") {
|
|
389
|
+
if (isVisibleConfigKey(key, path) && isLikelyTranslatableConfigString(childValue)) {
|
|
390
|
+
result.push({
|
|
391
|
+
field: makePropField(path),
|
|
392
|
+
source: childValue,
|
|
393
|
+
label: path.map(String).join(" > ")
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return result.length >= MAX_CONFIG_VALUE_COUNT;
|
|
397
|
+
}
|
|
398
|
+
if (childValue && typeof childValue === "object") {
|
|
399
|
+
collectVisibleConfigValues(childValue, path, result, seen);
|
|
400
|
+
}
|
|
401
|
+
return result.length >= MAX_CONFIG_VALUE_COUNT;
|
|
402
|
+
});
|
|
403
|
+
return result;
|
|
404
|
+
};
|
|
405
|
+
const hasVisibleModelConfigString = (component) => MODEL_VISIBLE_CONFIG_KEYS.some((key) => {
|
|
406
|
+
var _a;
|
|
407
|
+
const value = (_a = component == null ? void 0 : component.get) == null ? void 0 : _a.call(component, key);
|
|
408
|
+
return typeof value === "string" && isVisibleConfigKey(key, [key]) && isLikelyTranslatableConfigString(value);
|
|
409
|
+
}) || MODEL_VISIBLE_CONFIG_OBJECT_KEYS.some((key) => {
|
|
410
|
+
var _a;
|
|
411
|
+
const value = (_a = component == null ? void 0 : component.get) == null ? void 0 : _a.call(component, key);
|
|
412
|
+
return value && typeof value === "object" && collectVisibleConfigValues(value, [key]).length > 0;
|
|
413
|
+
});
|
|
414
|
+
const isComponentTranslatableModel = (component) => {
|
|
415
|
+
if (isModelI18nSkipped(component))
|
|
416
|
+
return false;
|
|
417
|
+
if (isTextNodeComponent(component))
|
|
418
|
+
return false;
|
|
419
|
+
const attrs = getComponentAttrs(component);
|
|
420
|
+
if (ATTRIBUTE_FIELDS.some(({ attr }) => normalizeText(attrs[attr])))
|
|
421
|
+
return true;
|
|
422
|
+
if (hasVisibleModelConfigString(component))
|
|
423
|
+
return true;
|
|
424
|
+
if (getModelChildren(component).some(
|
|
425
|
+
(child) => isTextNodeComponent(child) && normalizeText(getDirectTextSourceFromModel(child))
|
|
426
|
+
)) {
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
return Boolean(normalizeText(getDirectTextSourceFromModel(component)));
|
|
430
|
+
};
|
|
431
|
+
const collectI18nKeysFromModel = (component, options = {}) => {
|
|
432
|
+
const keys = /* @__PURE__ */ new Set();
|
|
433
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
434
|
+
let scannedNodes = 0;
|
|
435
|
+
const walk = (node) => {
|
|
436
|
+
if (!node || typeof node !== "object")
|
|
437
|
+
return;
|
|
438
|
+
if (seen.has(node) || scannedNodes >= MAX_MODEL_KEY_SCAN_NODES)
|
|
439
|
+
return;
|
|
440
|
+
seen.add(node);
|
|
441
|
+
scannedNodes += 1;
|
|
442
|
+
if (isModelNodeI18nSkipped(node))
|
|
443
|
+
return;
|
|
444
|
+
const key = `${getComponentAttrs(node)[WB_I18N_KEY_ATTR] ?? ""}`.trim();
|
|
445
|
+
if (key)
|
|
446
|
+
keys.add(key);
|
|
447
|
+
getModelChildren(node).forEach(walk);
|
|
448
|
+
};
|
|
449
|
+
if (component) {
|
|
450
|
+
if (isModelI18nSkipped(component))
|
|
451
|
+
return keys;
|
|
452
|
+
walk(component);
|
|
453
|
+
if (options.includeAncestors && !keys.size) {
|
|
454
|
+
let current = component;
|
|
455
|
+
let depth = 0;
|
|
456
|
+
while (current && typeof current === "object" && depth < 20) {
|
|
457
|
+
const key = `${getComponentAttrs(current)[WB_I18N_KEY_ATTR] ?? ""}`.trim();
|
|
458
|
+
if (isModelNodeI18nSkipped(current))
|
|
459
|
+
break;
|
|
460
|
+
if (key) {
|
|
461
|
+
keys.add(key);
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
current = getModelParent(current);
|
|
465
|
+
depth += 1;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
return keys;
|
|
470
|
+
};
|
|
471
|
+
const ensureModelI18nKeys = (editor, options = {}) => {
|
|
472
|
+
var _a, _b, _c;
|
|
473
|
+
const changed = [];
|
|
474
|
+
const used = /* @__PURE__ */ new Set();
|
|
475
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
476
|
+
let scannedNodes = 0;
|
|
477
|
+
const ensureNode = (component, path) => {
|
|
478
|
+
if (!component || typeof component !== "object")
|
|
479
|
+
return;
|
|
480
|
+
if (seen.has(component) || scannedNodes >= MAX_MODEL_KEY_SCAN_NODES)
|
|
481
|
+
return;
|
|
482
|
+
seen.add(component);
|
|
483
|
+
scannedNodes += 1;
|
|
484
|
+
if (isModelNodeI18nSkipped(component))
|
|
485
|
+
return;
|
|
486
|
+
const attrs = getComponentAttrs(component);
|
|
487
|
+
const current = `${attrs[WB_I18N_KEY_ATTR] ?? ""}`.trim();
|
|
488
|
+
const needsKey = isComponentTranslatableModel(component);
|
|
489
|
+
let nextKey = current;
|
|
490
|
+
if (needsKey && (!nextKey || used.has(nextKey))) {
|
|
491
|
+
const seed = [
|
|
492
|
+
path,
|
|
493
|
+
getComponentType(component),
|
|
494
|
+
getComponentLabel(component),
|
|
495
|
+
getDirectTextSourceFromModel(component)
|
|
496
|
+
].join("|");
|
|
497
|
+
let candidate = makeKey(seed);
|
|
498
|
+
let index = 1;
|
|
499
|
+
while (used.has(candidate)) {
|
|
500
|
+
candidate = `${makeKey(seed)}_${index}`;
|
|
501
|
+
index += 1;
|
|
502
|
+
}
|
|
503
|
+
nextKey = candidate;
|
|
504
|
+
setComponentAttrs(component, { [WB_I18N_KEY_ATTR]: nextKey });
|
|
505
|
+
changed.push(nextKey);
|
|
506
|
+
}
|
|
507
|
+
if (nextKey)
|
|
508
|
+
used.add(nextKey);
|
|
509
|
+
if (ownsGeneratedTranslatableChildren(component))
|
|
510
|
+
return;
|
|
511
|
+
getModelChildren(component).forEach((child, index) => ensureNode(child, `${path}.${index}`));
|
|
512
|
+
};
|
|
513
|
+
const pages = toArray((_b = (_a = editor == null ? void 0 : editor.Pages) == null ? void 0 : _a.getAll) == null ? void 0 : _b.call(_a));
|
|
514
|
+
if (pages.length) {
|
|
515
|
+
pages.forEach((page, pageIndex) => {
|
|
516
|
+
var _a2, _b2;
|
|
517
|
+
if (!options.includeLayoutPages && getPageLayoutSlot(page))
|
|
518
|
+
return;
|
|
519
|
+
const pageId = `${((_a2 = page == null ? void 0 : page.get) == null ? void 0 : _a2.call(page, "id")) ?? (page == null ? void 0 : page.id) ?? pageIndex}`.trim();
|
|
520
|
+
const root = (_b2 = page == null ? void 0 : page.getMainComponent) == null ? void 0 : _b2.call(page);
|
|
521
|
+
ensureNode(root, `page:${pageId}`);
|
|
522
|
+
});
|
|
523
|
+
return changed;
|
|
524
|
+
}
|
|
525
|
+
ensureNode((_c = editor == null ? void 0 : editor.getWrapper) == null ? void 0 : _c.call(editor), "wrapper");
|
|
526
|
+
return changed;
|
|
527
|
+
};
|
|
528
|
+
const pushEntry = (entries, usedIds, entry) => {
|
|
529
|
+
const source = `${entry.source ?? ""}`;
|
|
530
|
+
if (!isLikelyTranslatableConfigString(source))
|
|
531
|
+
return;
|
|
532
|
+
if (isNonTranslatableEntry({ ...entry, source }))
|
|
533
|
+
return;
|
|
534
|
+
const next = {
|
|
535
|
+
...entry,
|
|
536
|
+
source,
|
|
537
|
+
sourceHash: hashI18nSource(source)
|
|
538
|
+
};
|
|
539
|
+
const id = entryId(next);
|
|
540
|
+
if (usedIds.has(id))
|
|
541
|
+
return;
|
|
542
|
+
usedIds.add(id);
|
|
543
|
+
entries.push(next);
|
|
544
|
+
};
|
|
545
|
+
const extractPageSeoEntries = (page, entries, usedIds) => {
|
|
546
|
+
var _a, _b, _c;
|
|
547
|
+
const pageId = `${(page == null ? void 0 : page.id) ?? ((_a = page == null ? void 0 : page.get) == null ? void 0 : _a.call(page, "id")) ?? ""}`.trim() || "page";
|
|
548
|
+
const custom = (page == null ? void 0 : page.custom) ?? ((_b = page == null ? void 0 : page.get) == null ? void 0 : _b.call(page, "custom")) ?? {};
|
|
549
|
+
const tdk = (custom == null ? void 0 : custom.tdk) ?? {};
|
|
550
|
+
const label = `${(page == null ? void 0 : page.name) ?? ((_c = page == null ? void 0 : page.get) == null ? void 0 : _c.call(page, "name")) ?? pageId}`.trim();
|
|
551
|
+
SEO_FIELDS.forEach(({ field, customKey, legacyKey }) => {
|
|
552
|
+
const source = `${(custom == null ? void 0 : custom[customKey]) ?? (legacyKey ? tdk == null ? void 0 : tdk[legacyKey] : "") ?? ""}`.trim();
|
|
553
|
+
pushEntry(entries, usedIds, {
|
|
554
|
+
key: `page:${pageId}:seo`,
|
|
555
|
+
field,
|
|
556
|
+
source,
|
|
557
|
+
pageId,
|
|
558
|
+
componentType: "page-seo",
|
|
559
|
+
label: label ? `${label} SEO` : "Page SEO"
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
};
|
|
563
|
+
const extractProjectComponentEntries = (component, entries, usedIds, pageId, path, context) => {
|
|
564
|
+
if (!component || typeof component !== "object")
|
|
565
|
+
return;
|
|
566
|
+
if (context.seen.has(component) || context.scannedNodes >= MAX_PROJECT_SCAN_NODES)
|
|
567
|
+
return;
|
|
568
|
+
context.seen.add(component);
|
|
569
|
+
context.scannedNodes += 1;
|
|
570
|
+
if (isProjectNodeI18nSkipped(component))
|
|
571
|
+
return;
|
|
572
|
+
if (isTextNodeComponent(component))
|
|
573
|
+
return;
|
|
574
|
+
const attrs = component.attributes ?? {};
|
|
575
|
+
const source = getDirectTextSourceFromProject(component);
|
|
576
|
+
const fallbackSeed = [pageId, path, component.type, component.tagName, source].join("|");
|
|
577
|
+
const key = `${attrs[WB_I18N_KEY_ATTR] ?? ""}`.trim() || makeKey(fallbackSeed);
|
|
578
|
+
const componentType = `${component.type ?? component.tagName ?? ""}`.trim();
|
|
579
|
+
const label = `${component.name ?? attrs.class ?? attrs.id ?? componentType ?? "Component"}`.trim();
|
|
580
|
+
const textField = getDirectTextFieldFromProject(component, source);
|
|
581
|
+
pushEntry(entries, usedIds, {
|
|
582
|
+
key,
|
|
583
|
+
field: textField,
|
|
584
|
+
source,
|
|
585
|
+
pageId,
|
|
586
|
+
componentType,
|
|
587
|
+
label
|
|
588
|
+
});
|
|
589
|
+
ATTRIBUTE_FIELDS.forEach(({ field, attr }) => {
|
|
590
|
+
pushEntry(entries, usedIds, {
|
|
591
|
+
key,
|
|
592
|
+
field,
|
|
593
|
+
source: `${attrs[attr] ?? ""}`,
|
|
594
|
+
pageId,
|
|
595
|
+
componentType,
|
|
596
|
+
label
|
|
597
|
+
});
|
|
598
|
+
});
|
|
599
|
+
collectVisibleConfigValues(component).forEach((configEntry) => {
|
|
600
|
+
pushEntry(entries, usedIds, {
|
|
601
|
+
key,
|
|
602
|
+
field: configEntry.field,
|
|
603
|
+
source: configEntry.source,
|
|
604
|
+
pageId,
|
|
605
|
+
componentType,
|
|
606
|
+
label: label ? `${label} ${configEntry.label}` : configEntry.label
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
if (ownsGeneratedTranslatableChildren(component))
|
|
610
|
+
return;
|
|
611
|
+
getProjectChildren(component).forEach((child, index) => {
|
|
612
|
+
if (isTextNodeComponent(child)) {
|
|
613
|
+
const childSource = getDirectTextSourceFromProject(child);
|
|
614
|
+
const propKey = typeof (child == null ? void 0 : child.content) === "string" ? "content" : "components";
|
|
615
|
+
pushEntry(entries, usedIds, {
|
|
616
|
+
key,
|
|
617
|
+
field: makePropField(["components", index, propKey]),
|
|
618
|
+
source: childSource,
|
|
619
|
+
pageId,
|
|
620
|
+
componentType,
|
|
621
|
+
label: label ? `${label} text` : "Text"
|
|
622
|
+
});
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
extractProjectComponentEntries(child, entries, usedIds, pageId, `${path}.${index}`, context);
|
|
626
|
+
});
|
|
627
|
+
};
|
|
628
|
+
const extractI18nEntriesFromProjectData = (projectData, options = {}) => {
|
|
629
|
+
const entries = [];
|
|
630
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
631
|
+
const pages = Array.isArray(projectData == null ? void 0 : projectData.pages) ? projectData == null ? void 0 : projectData.pages : [];
|
|
632
|
+
const context = { seen: /* @__PURE__ */ new WeakSet(), scannedNodes: 0 };
|
|
633
|
+
pages.forEach((page, pageIndex) => {
|
|
634
|
+
if (!options.includeLayoutPages && getPageLayoutSlot(page))
|
|
635
|
+
return;
|
|
636
|
+
const pageId = `${(page == null ? void 0 : page.id) ?? pageIndex}`.trim();
|
|
637
|
+
extractPageSeoEntries(page, entries, usedIds);
|
|
638
|
+
const frames = Array.isArray(page == null ? void 0 : page.frames) ? page.frames : [];
|
|
639
|
+
frames.forEach((frame, frameIndex) => {
|
|
640
|
+
var _a;
|
|
641
|
+
const components = Array.isArray((_a = frame == null ? void 0 : frame.component) == null ? void 0 : _a.components) ? frame.component.components : Array.isArray(frame == null ? void 0 : frame.components) ? frame.components : [];
|
|
642
|
+
components.forEach((component, index) => {
|
|
643
|
+
extractProjectComponentEntries(
|
|
644
|
+
component,
|
|
645
|
+
entries,
|
|
646
|
+
usedIds,
|
|
647
|
+
pageId,
|
|
648
|
+
`page.${pageIndex}.frame.${frameIndex}.${index}`,
|
|
649
|
+
context
|
|
650
|
+
);
|
|
651
|
+
});
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
if (!pages.length) {
|
|
655
|
+
const components = Array.isArray(projectData == null ? void 0 : projectData.components) ? projectData == null ? void 0 : projectData.components : [];
|
|
656
|
+
components.forEach((component, index) => {
|
|
657
|
+
extractProjectComponentEntries(
|
|
658
|
+
component,
|
|
659
|
+
entries,
|
|
660
|
+
usedIds,
|
|
661
|
+
"default",
|
|
662
|
+
`root.${index}`,
|
|
663
|
+
context
|
|
664
|
+
);
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
return entries;
|
|
668
|
+
};
|
|
669
|
+
const stripNodeTranslationData = (node) => {
|
|
670
|
+
if (Array.isArray(node))
|
|
671
|
+
return node.map(stripNodeTranslationData);
|
|
672
|
+
if (!node || typeof node !== "object")
|
|
673
|
+
return node;
|
|
674
|
+
const next = {};
|
|
675
|
+
Object.entries(node).forEach(([key, value]) => {
|
|
676
|
+
if (TRANSLATION_ONLY_KEYS.has(key))
|
|
677
|
+
return;
|
|
678
|
+
if (key === "attributes" && value && typeof value === "object" && !Array.isArray(value)) {
|
|
679
|
+
next.attributes = Object.fromEntries(
|
|
680
|
+
Object.entries(value).filter(([attr]) => !TRANSLATION_ONLY_ATTRS.has(attr))
|
|
681
|
+
);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
next[key] = stripNodeTranslationData(value);
|
|
685
|
+
});
|
|
686
|
+
return next;
|
|
687
|
+
};
|
|
688
|
+
const stripI18nTranslationsFromProjectData = (projectData) => {
|
|
689
|
+
return stripNodeTranslationData(clonePlain(projectData));
|
|
690
|
+
};
|
|
691
|
+
const buildTranslationMap = (entries) => {
|
|
692
|
+
const map = /* @__PURE__ */ new Map();
|
|
693
|
+
entries.forEach((entry) => {
|
|
694
|
+
if (normalizeText(entry.translation))
|
|
695
|
+
map.set(entryId(entry), entry);
|
|
696
|
+
});
|
|
697
|
+
return map;
|
|
698
|
+
};
|
|
699
|
+
const setComponentPropByField = (component, field, translation) => {
|
|
700
|
+
const rawField = `${field}`;
|
|
701
|
+
if (!rawField.startsWith(PROP_FIELD_PREFIX))
|
|
702
|
+
return;
|
|
703
|
+
if (rawField === CANONICAL_TEXT_COMPONENT_FIELD && isTextElementComponent(component)) {
|
|
704
|
+
if (typeof component.content === "string") {
|
|
705
|
+
component.content = translation;
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
if (typeof component.components === "string") {
|
|
709
|
+
component.components = translation;
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const firstChild = getProjectChildren(component)[0];
|
|
713
|
+
if (firstChild && typeof firstChild === "object") {
|
|
714
|
+
if (typeof firstChild.content === "string") {
|
|
715
|
+
firstChild.content = translation;
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
if (typeof firstChild.components === "string") {
|
|
719
|
+
firstChild.components = translation;
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const path = decodePropPath(rawField.slice(PROP_FIELD_PREFIX.length));
|
|
725
|
+
if (!path.length)
|
|
726
|
+
return;
|
|
727
|
+
let target = component;
|
|
728
|
+
for (let index = 0; index < path.length - 1; index += 1) {
|
|
729
|
+
const segment = path[index];
|
|
730
|
+
if (target == null || typeof target !== "object")
|
|
731
|
+
return;
|
|
732
|
+
target = target[segment];
|
|
733
|
+
}
|
|
734
|
+
const leaf = path[path.length - 1];
|
|
735
|
+
if (target != null && typeof target === "object" && typeof target[leaf] === "string") {
|
|
736
|
+
target[leaf] = translation;
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
const syncGeneratedWbImageAlt = (component, alt) => {
|
|
740
|
+
if (getComponentType(component) !== "wb-image")
|
|
741
|
+
return;
|
|
742
|
+
const updateImageNode = (node) => {
|
|
743
|
+
if (!node || typeof node !== "object")
|
|
744
|
+
return false;
|
|
745
|
+
if (`${node.tagName ?? node.type ?? ""}`.toLowerCase() === "img") {
|
|
746
|
+
node.attributes = {
|
|
747
|
+
...node.attributes ?? {},
|
|
748
|
+
alt
|
|
749
|
+
};
|
|
750
|
+
return true;
|
|
751
|
+
}
|
|
752
|
+
return getProjectChildren(node).some(updateImageNode);
|
|
753
|
+
};
|
|
754
|
+
getProjectChildren(component).some(updateImageNode);
|
|
755
|
+
};
|
|
756
|
+
const hasClassName = (component, className) => {
|
|
757
|
+
var _a;
|
|
758
|
+
return `${((_a = component == null ? void 0 : component.attributes) == null ? void 0 : _a.class) ?? ""}`.split(/\s+/).includes(className);
|
|
759
|
+
};
|
|
760
|
+
const syncGeneratedInquiryFormTexts = (component) => {
|
|
761
|
+
if (getComponentType(component) !== "wb-inquiry-form")
|
|
762
|
+
return;
|
|
763
|
+
const i18nTexts = component.inquiryI18nTexts;
|
|
764
|
+
if (!i18nTexts || typeof i18nTexts !== "object")
|
|
765
|
+
return;
|
|
766
|
+
const fields = Array.isArray(i18nTexts.fields) ? i18nTexts.fields : [];
|
|
767
|
+
const fieldTextByCode = new Map(
|
|
768
|
+
fields.map((field) => [`${(field == null ? void 0 : field.code) ?? ""}`.trim(), field]).filter(([code]) => Boolean(code))
|
|
769
|
+
);
|
|
770
|
+
const syncFieldNode = (fieldNode) => {
|
|
771
|
+
var _a;
|
|
772
|
+
const children = getProjectChildren(fieldNode);
|
|
773
|
+
const control = children.find((child) => {
|
|
774
|
+
var _a2;
|
|
775
|
+
const name = `${((_a2 = child == null ? void 0 : child.attributes) == null ? void 0 : _a2.name) ?? ""}`.trim();
|
|
776
|
+
return name && fieldTextByCode.has(name);
|
|
777
|
+
});
|
|
778
|
+
if (!control)
|
|
779
|
+
return;
|
|
780
|
+
const fieldText = fieldTextByCode.get(`${((_a = control.attributes) == null ? void 0 : _a.name) ?? ""}`.trim());
|
|
781
|
+
if (!fieldText || typeof fieldText !== "object")
|
|
782
|
+
return;
|
|
783
|
+
const label = children.find((child) => hasClassName(child, "wb-inquiry__label"));
|
|
784
|
+
if (label && typeof fieldText.label === "string") {
|
|
785
|
+
label.content = fieldText.label;
|
|
786
|
+
}
|
|
787
|
+
if (control.attributes && typeof fieldText.placeholder === "string") {
|
|
788
|
+
control.attributes = {
|
|
789
|
+
...control.attributes,
|
|
790
|
+
placeholder: `${control.attributes["data-field-kind"] ?? ""}`.trim() && fieldText.optionPlaceholder ? fieldText.optionPlaceholder : fieldText.placeholder
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
const hint = children.find((child) => hasClassName(child, "wb-inquiry__field-hint"));
|
|
794
|
+
if (hint && typeof fieldText.helperText === "string") {
|
|
795
|
+
hint.content = fieldText.helperText;
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
const walk = (node) => {
|
|
799
|
+
if (!node || typeof node !== "object")
|
|
800
|
+
return;
|
|
801
|
+
if (hasClassName(node, "wb-inquiry__field"))
|
|
802
|
+
syncFieldNode(node);
|
|
803
|
+
if (hasClassName(node, "wb-inquiry__submit") && typeof i18nTexts.submitText === "string") {
|
|
804
|
+
node.content = i18nTexts.submitText;
|
|
805
|
+
}
|
|
806
|
+
getProjectChildren(node).forEach(walk);
|
|
807
|
+
};
|
|
808
|
+
getProjectChildren(component).forEach(walk);
|
|
809
|
+
};
|
|
810
|
+
const applyTranslatedEntry = (component, key, map) => {
|
|
811
|
+
const applyField = (field) => {
|
|
812
|
+
var _a;
|
|
813
|
+
const translation = (_a = map.get(`${key}::${field}`)) == null ? void 0 : _a.translation;
|
|
814
|
+
return translation === void 0 ? void 0 : translation;
|
|
815
|
+
};
|
|
816
|
+
const text = applyField("text") ?? applyField("html");
|
|
817
|
+
if (text !== void 0) {
|
|
818
|
+
if (typeof component.content === "string")
|
|
819
|
+
component.content = text;
|
|
820
|
+
else if (typeof component.components === "string")
|
|
821
|
+
component.components = text;
|
|
822
|
+
}
|
|
823
|
+
ATTRIBUTE_FIELDS.forEach(({ field, attr }) => {
|
|
824
|
+
const translation = applyField(field);
|
|
825
|
+
if (translation === void 0)
|
|
826
|
+
return;
|
|
827
|
+
component.attributes = {
|
|
828
|
+
...component.attributes ?? {},
|
|
829
|
+
[attr]: translation
|
|
830
|
+
};
|
|
831
|
+
});
|
|
832
|
+
let inquiryFormTextChanged = false;
|
|
833
|
+
Array.from(map.values()).filter((entry) => entry.key === key && isPropField(entry.field)).forEach((entry) => {
|
|
834
|
+
const translation = `${entry.translation ?? ""}`;
|
|
835
|
+
if (!normalizeText(translation))
|
|
836
|
+
return;
|
|
837
|
+
setComponentPropByField(component, entry.field, translation);
|
|
838
|
+
if (entry.field === "prop:imageAlt") {
|
|
839
|
+
syncGeneratedWbImageAlt(component, translation);
|
|
840
|
+
}
|
|
841
|
+
if (`${entry.field}`.startsWith("prop:inquiryI18nTexts/")) {
|
|
842
|
+
inquiryFormTextChanged = true;
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
if (inquiryFormTextChanged) {
|
|
846
|
+
syncGeneratedInquiryFormTexts(component);
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
const applyProjectComponentTranslations = (component, map) => {
|
|
850
|
+
var _a;
|
|
851
|
+
if (!component || typeof component !== "object")
|
|
852
|
+
return;
|
|
853
|
+
if (isProjectNodeI18nSkipped(component))
|
|
854
|
+
return;
|
|
855
|
+
const key = `${((_a = component.attributes) == null ? void 0 : _a[WB_I18N_KEY_ATTR]) ?? ""}`.trim();
|
|
856
|
+
if (key)
|
|
857
|
+
applyTranslatedEntry(component, key, map);
|
|
858
|
+
getProjectChildren(component).forEach((child) => applyProjectComponentTranslations(child, map));
|
|
859
|
+
};
|
|
860
|
+
const applyPageSeoTranslations = (page, map) => {
|
|
861
|
+
const pageId = `${(page == null ? void 0 : page.id) ?? ""}`.trim() || "page";
|
|
862
|
+
const key = `page:${pageId}:seo`;
|
|
863
|
+
const custom = { ...page.custom ?? {} };
|
|
864
|
+
const tdk = { ...custom.tdk ?? {} };
|
|
865
|
+
SEO_FIELDS.forEach(({ field, customKey, legacyKey }) => {
|
|
866
|
+
var _a;
|
|
867
|
+
const translation = (_a = map.get(`${key}::${field}`)) == null ? void 0 : _a.translation;
|
|
868
|
+
if (translation === void 0)
|
|
869
|
+
return;
|
|
870
|
+
custom[customKey] = translation;
|
|
871
|
+
if (legacyKey)
|
|
872
|
+
tdk[legacyKey] = translation;
|
|
873
|
+
});
|
|
874
|
+
page.custom = { ...custom, tdk };
|
|
875
|
+
};
|
|
876
|
+
const applyI18nTranslationsToProjectData = (projectData, entries) => {
|
|
877
|
+
const next = stripI18nTranslationsFromProjectData(projectData);
|
|
878
|
+
const map = buildTranslationMap(entries);
|
|
879
|
+
if (!next || !map.size)
|
|
880
|
+
return next;
|
|
881
|
+
const pages = Array.isArray(next.pages) ? next.pages : [];
|
|
882
|
+
pages.forEach((page) => {
|
|
883
|
+
applyPageSeoTranslations(page, map);
|
|
884
|
+
const frames = Array.isArray(page == null ? void 0 : page.frames) ? page.frames : [];
|
|
885
|
+
frames.forEach((frame) => {
|
|
886
|
+
var _a;
|
|
887
|
+
const components = Array.isArray((_a = frame == null ? void 0 : frame.component) == null ? void 0 : _a.components) ? frame.component.components : Array.isArray(frame == null ? void 0 : frame.components) ? frame.components : [];
|
|
888
|
+
components.forEach((component) => applyProjectComponentTranslations(component, map));
|
|
889
|
+
});
|
|
890
|
+
});
|
|
891
|
+
if (!pages.length && Array.isArray(next.components)) {
|
|
892
|
+
next.components.forEach((component) => applyProjectComponentTranslations(component, map));
|
|
893
|
+
}
|
|
894
|
+
return next;
|
|
895
|
+
};
|
|
896
|
+
const resolveI18nEntryStatus = (source, saved) => {
|
|
897
|
+
if (!normalizeText(saved == null ? void 0 : saved.translation))
|
|
898
|
+
return "missing";
|
|
899
|
+
if (isUnchangedNonIdentityTranslation(source.source, saved == null ? void 0 : saved.translation) && !isExplicitTranslatedIdentity(source, saved)) {
|
|
900
|
+
return "missing";
|
|
901
|
+
}
|
|
902
|
+
if ((saved == null ? void 0 : saved.sourceHash) && saved.sourceHash !== source.sourceHash)
|
|
903
|
+
return "stale";
|
|
904
|
+
return "translated";
|
|
905
|
+
};
|
|
906
|
+
const resolveI18nReviewStatus = (source, saved) => {
|
|
907
|
+
const status = resolveI18nEntryStatus(source, saved);
|
|
908
|
+
if (status === "missing")
|
|
909
|
+
return void 0;
|
|
910
|
+
return "reviewed";
|
|
911
|
+
};
|
|
912
|
+
const mergeI18nEntries = (sourceEntries, savedEntries) => {
|
|
913
|
+
const savedMap = new Map(savedEntries.map((entry) => [entryId(entry), entry]));
|
|
914
|
+
return sourceEntries.map((source) => {
|
|
915
|
+
const saved = findSavedEntryForSource(source, savedMap);
|
|
916
|
+
const status = resolveI18nEntryStatus(source, saved);
|
|
917
|
+
const translation = isUnchangedNonIdentityTranslation(source.source, saved == null ? void 0 : saved.translation) && !isExplicitTranslatedIdentity(source, saved) ? "" : (saved == null ? void 0 : saved.translation) ?? "";
|
|
918
|
+
return {
|
|
919
|
+
...source,
|
|
920
|
+
translation,
|
|
921
|
+
status,
|
|
922
|
+
translationOrigin: saved == null ? void 0 : saved.translationOrigin,
|
|
923
|
+
reviewStatus: resolveI18nReviewStatus(source, saved),
|
|
924
|
+
translatedAt: saved == null ? void 0 : saved.translatedAt,
|
|
925
|
+
reviewedAt: saved == null ? void 0 : saved.reviewedAt
|
|
926
|
+
};
|
|
927
|
+
});
|
|
928
|
+
};
|
|
929
|
+
const findSavedEntryForSource = (source, savedMap) => {
|
|
930
|
+
const exact = savedMap.get(entryId(source));
|
|
931
|
+
if (exact)
|
|
932
|
+
return exact;
|
|
933
|
+
const field = `${source.field}`;
|
|
934
|
+
const aliases = field === "text" || field === "html" ? [CANONICAL_TEXT_COMPONENT_FIELD] : field === CANONICAL_TEXT_COMPONENT_FIELD ? ["text", "html"] : [];
|
|
935
|
+
const candidates = aliases.map((alias) => savedMap.get(`${source.key}::${alias}`)).filter(Boolean);
|
|
936
|
+
if (!candidates.length)
|
|
937
|
+
return void 0;
|
|
938
|
+
return candidates.find((candidate) => candidate.sourceHash === source.sourceHash) ?? candidates.find(
|
|
939
|
+
(candidate) => normalizeText(candidate.source) === normalizeText(source.source)
|
|
940
|
+
) ?? candidates[0];
|
|
941
|
+
};
|
|
942
|
+
export {
|
|
943
|
+
WB_I18N_KEY_ATTR as W,
|
|
944
|
+
extractI18nEntriesFromProjectData as a,
|
|
945
|
+
applyI18nTranslationsToProjectData as b,
|
|
946
|
+
WB_I18N_SKIP_ATTR as c,
|
|
947
|
+
collectI18nKeysFromModel as d,
|
|
948
|
+
ensureModelI18nKeys as e,
|
|
949
|
+
isIdentityTranslationAllowed as f,
|
|
950
|
+
getWebBuilderI18nEntryId as g,
|
|
951
|
+
hashI18nSource as h,
|
|
952
|
+
isUnchangedNonIdentityTranslation as i,
|
|
953
|
+
isModelI18nSkipped as j,
|
|
954
|
+
resolveI18nReviewStatus as k,
|
|
955
|
+
stripI18nTranslationsFromProjectData as l,
|
|
956
|
+
mergeI18nEntries as m,
|
|
957
|
+
resolveI18nEntryStatus as r,
|
|
958
|
+
setModelI18nSkipped as s
|
|
959
|
+
};
|