@wix/headless-localization-utils 1.0.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/build/index.cjs +134 -0
- package/build/index.cjs.map +1 -0
- package/build/index.d.cts +11 -0
- package/build/index.d.ts +11 -0
- package/build/index.js +107 -0
- package/build/index.js.map +1 -0
- package/package.json +78 -0
package/build/index.cjs
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
getLocalizationData: () => getLocalizationData
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/localeUtils.ts
|
|
28
|
+
var buildLocaleString = (locale) => {
|
|
29
|
+
if (!locale) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (locale.languageCode?.includes("-")) {
|
|
33
|
+
return locale.languageCode;
|
|
34
|
+
}
|
|
35
|
+
const localeParts = [locale.languageCode, locale.country].filter(Boolean);
|
|
36
|
+
if (localeParts.length === 0) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
return localeParts.join("-");
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/urlUtils.ts
|
|
43
|
+
var getLanguageFromQueryParam = (url) => url.searchParams.get("lang") ?? void 0;
|
|
44
|
+
var getLanguageFromSubfolder = (url) => url.pathname.split("/")[1];
|
|
45
|
+
var getLanguageFromSubdomain = (url) => url.hostname.split(".")[0];
|
|
46
|
+
var extractLanguageFromUrlAndValidate = (url, availableLocales) => {
|
|
47
|
+
const localeFromQueryParams = extractFromQueryParamsAndValidate(
|
|
48
|
+
url,
|
|
49
|
+
availableLocales
|
|
50
|
+
);
|
|
51
|
+
if (localeFromQueryParams?.resolutionMethod === "QUERY_PARAM") {
|
|
52
|
+
return localeFromQueryParams;
|
|
53
|
+
}
|
|
54
|
+
const localeFromSubfolder = extractFromSubfolderAndValidate(
|
|
55
|
+
url,
|
|
56
|
+
availableLocales
|
|
57
|
+
);
|
|
58
|
+
if (localeFromSubfolder?.resolutionMethod === "SUBDIRECTORY") {
|
|
59
|
+
return localeFromSubfolder;
|
|
60
|
+
}
|
|
61
|
+
const localeFromSubdomain = extractFromSubdomainAndValidate(
|
|
62
|
+
url,
|
|
63
|
+
availableLocales
|
|
64
|
+
);
|
|
65
|
+
if (localeFromSubdomain?.resolutionMethod === "SUBDOMAIN") {
|
|
66
|
+
return localeFromSubdomain;
|
|
67
|
+
}
|
|
68
|
+
return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;
|
|
69
|
+
};
|
|
70
|
+
var clearLanguageFromUrl = (urlString, languageCodes) => {
|
|
71
|
+
const url = new URL(urlString);
|
|
72
|
+
url.searchParams.delete("lang");
|
|
73
|
+
const subfolderLanguage = url.pathname.split("/")[1]?.toLowerCase();
|
|
74
|
+
if (languageCodes.includes(subfolderLanguage ?? "")) {
|
|
75
|
+
const segments = url.pathname.split("/");
|
|
76
|
+
segments.splice(1, 1);
|
|
77
|
+
url.pathname = segments.join("/");
|
|
78
|
+
}
|
|
79
|
+
const subdirectoryLanguage = url.hostname.split(".")[0]?.toLowerCase();
|
|
80
|
+
if (languageCodes.includes(subdirectoryLanguage ?? "")) {
|
|
81
|
+
const parts = url.hostname.split(".");
|
|
82
|
+
parts.shift();
|
|
83
|
+
url.hostname = parts.join(".");
|
|
84
|
+
}
|
|
85
|
+
return url.href;
|
|
86
|
+
};
|
|
87
|
+
var extractFromQueryParamsAndValidate = (url, availableLocales) => {
|
|
88
|
+
return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);
|
|
89
|
+
};
|
|
90
|
+
var extractFromSubfolderAndValidate = (url, availableLocales) => {
|
|
91
|
+
return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);
|
|
92
|
+
};
|
|
93
|
+
var extractFromSubdomainAndValidate = (url, availableLocales) => {
|
|
94
|
+
return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);
|
|
95
|
+
};
|
|
96
|
+
var getLanguageIfExists = (languageCode, availableLocales) => {
|
|
97
|
+
if (languageCode == null) {
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
const lowerCasedCode = languageCode.toLowerCase();
|
|
101
|
+
return availableLocales.find(
|
|
102
|
+
(locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// src/localizationUtils.ts
|
|
107
|
+
function getLocalizationData(url, siteProperties) {
|
|
108
|
+
const availableLocales = siteProperties?.multilingual?.supportedLanguages ?? [];
|
|
109
|
+
const explicitRequestedLocale = extractLanguageFromUrlAndValidate(
|
|
110
|
+
url,
|
|
111
|
+
availableLocales
|
|
112
|
+
);
|
|
113
|
+
const languageCodes = [
|
|
114
|
+
...availableLocales.map((locale2) => locale2.locale?.languageCode),
|
|
115
|
+
siteProperties?.locale?.languageCode
|
|
116
|
+
].filter((languageCode) => Boolean(languageCode));
|
|
117
|
+
const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
|
|
118
|
+
const locale = buildLocaleString(
|
|
119
|
+
explicitRequestedLocale?.locale ?? siteProperties?.locale
|
|
120
|
+
) ?? void 0;
|
|
121
|
+
const language = explicitRequestedLocale?.languageCode ?? siteProperties?.language ?? void 0;
|
|
122
|
+
const essentials = {
|
|
123
|
+
language,
|
|
124
|
+
locale,
|
|
125
|
+
multilingual: siteProperties?.multilingual,
|
|
126
|
+
timezone: siteProperties?.timeZone ?? void 0
|
|
127
|
+
};
|
|
128
|
+
return { cleanUrl, essentials };
|
|
129
|
+
}
|
|
130
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
131
|
+
0 && (module.exports = {
|
|
132
|
+
getLocalizationData
|
|
133
|
+
});
|
|
134
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/localeUtils.ts","../src/urlUtils.ts","../src/localizationUtils.ts"],"sourcesContent":["export {\n getLocalizationData,\n type LocalizationData,\n} from './localizationUtils.js';\n","import type { scripts } from '@wix/headless-site-assets';\n\n// Type for locale object\nexport type Locale = scripts.Locale;\n\n// Type for locale string building\nexport const buildLocaleString = (\n locale?: null | Locale,\n): string | undefined => {\n if (!locale) {\n return;\n }\n\n // in case of dialects, language code will be in the form of\n // en-au and not just en\n if (locale.languageCode?.includes('-')) {\n return locale.languageCode;\n }\n\n const localeParts = [locale.languageCode, locale.country].filter(Boolean);\n\n if (localeParts.length === 0) {\n return;\n }\n\n return localeParts.join('-');\n};\n","import type { scripts } from '@wix/headless-site-assets';\n\nexport type SupportedLanguage = scripts.SupportedLanguage;\n\ntype AvailableLocale = SupportedLanguage;\n\nconst getLanguageFromQueryParam = (url: URL) =>\n url.searchParams.get('lang') ?? undefined;\nconst getLanguageFromSubfolder = (url: URL) => url.pathname.split('/')[1];\nconst getLanguageFromSubdomain = (url: URL) => url.hostname.split('.')[0];\n\nexport const extractLanguageFromUrlAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n const localeFromQueryParams = extractFromQueryParamsAndValidate(\n url,\n availableLocales,\n );\n if (localeFromQueryParams?.resolutionMethod === 'QUERY_PARAM') {\n return localeFromQueryParams;\n }\n\n const localeFromSubfolder = extractFromSubfolderAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubfolder?.resolutionMethod === 'SUBDIRECTORY') {\n return localeFromSubfolder;\n }\n\n const localeFromSubdomain = extractFromSubdomainAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubdomain?.resolutionMethod === 'SUBDOMAIN') {\n return localeFromSubdomain;\n }\n\n // Fallback if a locale is available but doesn't have the correct resolution method\n return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;\n};\n\nexport const clearLanguageFromUrl = (\n urlString: string,\n languageCodes: string[],\n): string => {\n const url = new URL(urlString);\n url.searchParams.delete('lang');\n\n const subfolderLanguage = url.pathname.split('/')[1]?.toLowerCase();\n if (languageCodes.includes(subfolderLanguage ?? '')) {\n const segments = url.pathname.split('/'); // ['', 'en', 'docs', 'api']\n segments.splice(1, 1); // Remove index 1\n url.pathname = segments.join('/');\n }\n\n const subdirectoryLanguage = url.hostname.split('.')[0]?.toLowerCase();\n if (languageCodes.includes(subdirectoryLanguage ?? '')) {\n const parts = url.hostname.split('.'); // ['fr', 'example', 'com']\n parts.shift(); // ['example', 'com']\n url.hostname = parts.join('.');\n }\n\n return url.href;\n};\n\n// https://somesite.com/hello?lang:XX\nconst extractFromQueryParamsAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);\n};\n\n// https://somesite.com/XX/hello\nconst extractFromSubfolderAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);\n};\n\n// https://XX.somesite.com/hello\nconst extractFromSubdomainAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);\n};\n\nconst getLanguageIfExists = (\n languageCode: string | undefined,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n if (languageCode == null) {\n return undefined;\n }\n const lowerCasedCode = languageCode.toLowerCase();\n return availableLocales.find(\n (locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode,\n );\n};\n","import type { Essentials, Multilingual } from '@wix/headless-node';\nimport type { scripts } from '@wix/headless-site-assets';\nimport { buildLocaleString } from './localeUtils.js';\nimport {\n clearLanguageFromUrl,\n extractLanguageFromUrlAndValidate,\n} from './urlUtils.js';\n\nexport type EssentialProperties = scripts.EssentialProperties;\n\nexport type LocalizationData = {\n cleanUrl: string;\n essentials: Essentials;\n};\n\nexport function getLocalizationData(\n url: URL,\n siteProperties: EssentialProperties,\n): LocalizationData {\n const availableLocales =\n siteProperties?.multilingual?.supportedLanguages ?? [];\n const explicitRequestedLocale = extractLanguageFromUrlAndValidate(\n url,\n availableLocales,\n );\n\n const languageCodes = [\n ...availableLocales.map((locale) => locale.locale?.languageCode),\n siteProperties?.locale?.languageCode,\n ].filter((languageCode) => Boolean(languageCode)) as string[];\n\n const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);\n\n const locale =\n buildLocaleString(\n explicitRequestedLocale?.locale ?? siteProperties?.locale,\n ) ?? undefined;\n\n const language =\n explicitRequestedLocale?.languageCode ??\n siteProperties?.language ??\n undefined;\n\n const essentials: Essentials = {\n language,\n locale,\n multilingual: siteProperties?.multilingual as Multilingual | undefined,\n timezone: siteProperties?.timeZone ?? undefined,\n };\n\n return { cleanUrl, essentials };\n}\n"],"mappings":"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","names":["locale"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Essentials } from '@wix/headless-node';
|
|
2
|
+
import { scripts } from '@wix/headless-site-assets';
|
|
3
|
+
|
|
4
|
+
type EssentialProperties = scripts.EssentialProperties;
|
|
5
|
+
type LocalizationData = {
|
|
6
|
+
cleanUrl: string;
|
|
7
|
+
essentials: Essentials;
|
|
8
|
+
};
|
|
9
|
+
declare function getLocalizationData(url: URL, siteProperties: EssentialProperties): LocalizationData;
|
|
10
|
+
|
|
11
|
+
export { type LocalizationData, getLocalizationData };
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Essentials } from '@wix/headless-node';
|
|
2
|
+
import { scripts } from '@wix/headless-site-assets';
|
|
3
|
+
|
|
4
|
+
type EssentialProperties = scripts.EssentialProperties;
|
|
5
|
+
type LocalizationData = {
|
|
6
|
+
cleanUrl: string;
|
|
7
|
+
essentials: Essentials;
|
|
8
|
+
};
|
|
9
|
+
declare function getLocalizationData(url: URL, siteProperties: EssentialProperties): LocalizationData;
|
|
10
|
+
|
|
11
|
+
export { type LocalizationData, getLocalizationData };
|
package/build/index.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/localeUtils.ts
|
|
2
|
+
var buildLocaleString = (locale) => {
|
|
3
|
+
if (!locale) {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
if (locale.languageCode?.includes("-")) {
|
|
7
|
+
return locale.languageCode;
|
|
8
|
+
}
|
|
9
|
+
const localeParts = [locale.languageCode, locale.country].filter(Boolean);
|
|
10
|
+
if (localeParts.length === 0) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
return localeParts.join("-");
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/urlUtils.ts
|
|
17
|
+
var getLanguageFromQueryParam = (url) => url.searchParams.get("lang") ?? void 0;
|
|
18
|
+
var getLanguageFromSubfolder = (url) => url.pathname.split("/")[1];
|
|
19
|
+
var getLanguageFromSubdomain = (url) => url.hostname.split(".")[0];
|
|
20
|
+
var extractLanguageFromUrlAndValidate = (url, availableLocales) => {
|
|
21
|
+
const localeFromQueryParams = extractFromQueryParamsAndValidate(
|
|
22
|
+
url,
|
|
23
|
+
availableLocales
|
|
24
|
+
);
|
|
25
|
+
if (localeFromQueryParams?.resolutionMethod === "QUERY_PARAM") {
|
|
26
|
+
return localeFromQueryParams;
|
|
27
|
+
}
|
|
28
|
+
const localeFromSubfolder = extractFromSubfolderAndValidate(
|
|
29
|
+
url,
|
|
30
|
+
availableLocales
|
|
31
|
+
);
|
|
32
|
+
if (localeFromSubfolder?.resolutionMethod === "SUBDIRECTORY") {
|
|
33
|
+
return localeFromSubfolder;
|
|
34
|
+
}
|
|
35
|
+
const localeFromSubdomain = extractFromSubdomainAndValidate(
|
|
36
|
+
url,
|
|
37
|
+
availableLocales
|
|
38
|
+
);
|
|
39
|
+
if (localeFromSubdomain?.resolutionMethod === "SUBDOMAIN") {
|
|
40
|
+
return localeFromSubdomain;
|
|
41
|
+
}
|
|
42
|
+
return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;
|
|
43
|
+
};
|
|
44
|
+
var clearLanguageFromUrl = (urlString, languageCodes) => {
|
|
45
|
+
const url = new URL(urlString);
|
|
46
|
+
url.searchParams.delete("lang");
|
|
47
|
+
const subfolderLanguage = url.pathname.split("/")[1]?.toLowerCase();
|
|
48
|
+
if (languageCodes.includes(subfolderLanguage ?? "")) {
|
|
49
|
+
const segments = url.pathname.split("/");
|
|
50
|
+
segments.splice(1, 1);
|
|
51
|
+
url.pathname = segments.join("/");
|
|
52
|
+
}
|
|
53
|
+
const subdirectoryLanguage = url.hostname.split(".")[0]?.toLowerCase();
|
|
54
|
+
if (languageCodes.includes(subdirectoryLanguage ?? "")) {
|
|
55
|
+
const parts = url.hostname.split(".");
|
|
56
|
+
parts.shift();
|
|
57
|
+
url.hostname = parts.join(".");
|
|
58
|
+
}
|
|
59
|
+
return url.href;
|
|
60
|
+
};
|
|
61
|
+
var extractFromQueryParamsAndValidate = (url, availableLocales) => {
|
|
62
|
+
return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);
|
|
63
|
+
};
|
|
64
|
+
var extractFromSubfolderAndValidate = (url, availableLocales) => {
|
|
65
|
+
return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);
|
|
66
|
+
};
|
|
67
|
+
var extractFromSubdomainAndValidate = (url, availableLocales) => {
|
|
68
|
+
return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);
|
|
69
|
+
};
|
|
70
|
+
var getLanguageIfExists = (languageCode, availableLocales) => {
|
|
71
|
+
if (languageCode == null) {
|
|
72
|
+
return void 0;
|
|
73
|
+
}
|
|
74
|
+
const lowerCasedCode = languageCode.toLowerCase();
|
|
75
|
+
return availableLocales.find(
|
|
76
|
+
(locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/localizationUtils.ts
|
|
81
|
+
function getLocalizationData(url, siteProperties) {
|
|
82
|
+
const availableLocales = siteProperties?.multilingual?.supportedLanguages ?? [];
|
|
83
|
+
const explicitRequestedLocale = extractLanguageFromUrlAndValidate(
|
|
84
|
+
url,
|
|
85
|
+
availableLocales
|
|
86
|
+
);
|
|
87
|
+
const languageCodes = [
|
|
88
|
+
...availableLocales.map((locale2) => locale2.locale?.languageCode),
|
|
89
|
+
siteProperties?.locale?.languageCode
|
|
90
|
+
].filter((languageCode) => Boolean(languageCode));
|
|
91
|
+
const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
|
|
92
|
+
const locale = buildLocaleString(
|
|
93
|
+
explicitRequestedLocale?.locale ?? siteProperties?.locale
|
|
94
|
+
) ?? void 0;
|
|
95
|
+
const language = explicitRequestedLocale?.languageCode ?? siteProperties?.language ?? void 0;
|
|
96
|
+
const essentials = {
|
|
97
|
+
language,
|
|
98
|
+
locale,
|
|
99
|
+
multilingual: siteProperties?.multilingual,
|
|
100
|
+
timezone: siteProperties?.timeZone ?? void 0
|
|
101
|
+
};
|
|
102
|
+
return { cleanUrl, essentials };
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
getLocalizationData
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/localeUtils.ts","../src/urlUtils.ts","../src/localizationUtils.ts"],"sourcesContent":["import type { scripts } from '@wix/headless-site-assets';\n\n// Type for locale object\nexport type Locale = scripts.Locale;\n\n// Type for locale string building\nexport const buildLocaleString = (\n locale?: null | Locale,\n): string | undefined => {\n if (!locale) {\n return;\n }\n\n // in case of dialects, language code will be in the form of\n // en-au and not just en\n if (locale.languageCode?.includes('-')) {\n return locale.languageCode;\n }\n\n const localeParts = [locale.languageCode, locale.country].filter(Boolean);\n\n if (localeParts.length === 0) {\n return;\n }\n\n return localeParts.join('-');\n};\n","import type { scripts } from '@wix/headless-site-assets';\n\nexport type SupportedLanguage = scripts.SupportedLanguage;\n\ntype AvailableLocale = SupportedLanguage;\n\nconst getLanguageFromQueryParam = (url: URL) =>\n url.searchParams.get('lang') ?? undefined;\nconst getLanguageFromSubfolder = (url: URL) => url.pathname.split('/')[1];\nconst getLanguageFromSubdomain = (url: URL) => url.hostname.split('.')[0];\n\nexport const extractLanguageFromUrlAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n const localeFromQueryParams = extractFromQueryParamsAndValidate(\n url,\n availableLocales,\n );\n if (localeFromQueryParams?.resolutionMethod === 'QUERY_PARAM') {\n return localeFromQueryParams;\n }\n\n const localeFromSubfolder = extractFromSubfolderAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubfolder?.resolutionMethod === 'SUBDIRECTORY') {\n return localeFromSubfolder;\n }\n\n const localeFromSubdomain = extractFromSubdomainAndValidate(\n url,\n availableLocales,\n );\n if (localeFromSubdomain?.resolutionMethod === 'SUBDOMAIN') {\n return localeFromSubdomain;\n }\n\n // Fallback if a locale is available but doesn't have the correct resolution method\n return localeFromQueryParams ?? localeFromSubfolder ?? localeFromSubdomain;\n};\n\nexport const clearLanguageFromUrl = (\n urlString: string,\n languageCodes: string[],\n): string => {\n const url = new URL(urlString);\n url.searchParams.delete('lang');\n\n const subfolderLanguage = url.pathname.split('/')[1]?.toLowerCase();\n if (languageCodes.includes(subfolderLanguage ?? '')) {\n const segments = url.pathname.split('/'); // ['', 'en', 'docs', 'api']\n segments.splice(1, 1); // Remove index 1\n url.pathname = segments.join('/');\n }\n\n const subdirectoryLanguage = url.hostname.split('.')[0]?.toLowerCase();\n if (languageCodes.includes(subdirectoryLanguage ?? '')) {\n const parts = url.hostname.split('.'); // ['fr', 'example', 'com']\n parts.shift(); // ['example', 'com']\n url.hostname = parts.join('.');\n }\n\n return url.href;\n};\n\n// https://somesite.com/hello?lang:XX\nconst extractFromQueryParamsAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromQueryParam(url), availableLocales);\n};\n\n// https://somesite.com/XX/hello\nconst extractFromSubfolderAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubfolder(url), availableLocales);\n};\n\n// https://XX.somesite.com/hello\nconst extractFromSubdomainAndValidate = (\n url: URL,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n return getLanguageIfExists(getLanguageFromSubdomain(url), availableLocales);\n};\n\nconst getLanguageIfExists = (\n languageCode: string | undefined,\n availableLocales: AvailableLocale[],\n): AvailableLocale | undefined => {\n if (languageCode == null) {\n return undefined;\n }\n const lowerCasedCode = languageCode.toLowerCase();\n return availableLocales.find(\n (locale) => locale.locale?.languageCode?.toLowerCase() === lowerCasedCode,\n );\n};\n","import type { Essentials, Multilingual } from '@wix/headless-node';\nimport type { scripts } from '@wix/headless-site-assets';\nimport { buildLocaleString } from './localeUtils.js';\nimport {\n clearLanguageFromUrl,\n extractLanguageFromUrlAndValidate,\n} from './urlUtils.js';\n\nexport type EssentialProperties = scripts.EssentialProperties;\n\nexport type LocalizationData = {\n cleanUrl: string;\n essentials: Essentials;\n};\n\nexport function getLocalizationData(\n url: URL,\n siteProperties: EssentialProperties,\n): LocalizationData {\n const availableLocales =\n siteProperties?.multilingual?.supportedLanguages ?? [];\n const explicitRequestedLocale = extractLanguageFromUrlAndValidate(\n url,\n availableLocales,\n );\n\n const languageCodes = [\n ...availableLocales.map((locale) => locale.locale?.languageCode),\n siteProperties?.locale?.languageCode,\n ].filter((languageCode) => Boolean(languageCode)) as string[];\n\n const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);\n\n const locale =\n buildLocaleString(\n explicitRequestedLocale?.locale ?? siteProperties?.locale,\n ) ?? undefined;\n\n const language =\n explicitRequestedLocale?.languageCode ??\n siteProperties?.language ??\n undefined;\n\n const essentials: Essentials = {\n language,\n locale,\n multilingual: siteProperties?.multilingual as Multilingual | undefined,\n timezone: siteProperties?.timeZone ?? undefined,\n };\n\n return { cleanUrl, essentials };\n}\n"],"mappings":"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","names":["locale"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wix/headless-localization-utils",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"unpkg": true,
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "tomsa",
|
|
8
|
+
"email": "tomsa@wix.com"
|
|
9
|
+
},
|
|
10
|
+
"main": "build/index.cjs",
|
|
11
|
+
"module": "build/index.js",
|
|
12
|
+
"types": "build/index.d.ts",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"files": [
|
|
16
|
+
"build"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": {
|
|
21
|
+
"types": "./build/index.d.ts",
|
|
22
|
+
"default": "./build/index.js"
|
|
23
|
+
},
|
|
24
|
+
"require": {
|
|
25
|
+
"types": "./build/index.d.ts",
|
|
26
|
+
"default": "./build/index.cjs"
|
|
27
|
+
},
|
|
28
|
+
"default": {
|
|
29
|
+
"types": "./build/index.d.ts",
|
|
30
|
+
"default": "./build/index.js"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"registry": "https://registry.npmjs.org/",
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"publishScoped": true,
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"test": "vitest",
|
|
42
|
+
"lint": "eslint --max-warnings=0 .",
|
|
43
|
+
"lint:fix": "eslint --max-warnings=0 . --fix",
|
|
44
|
+
"typecheck": "tsc --noEmit"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@wix/headless-node": "1.21.0",
|
|
48
|
+
"@wix/headless-site-assets": "^1.0.9"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^16.0.0",
|
|
52
|
+
"eslint": "^8.57.1",
|
|
53
|
+
"tsup": "^8.5.0",
|
|
54
|
+
"typescript": "~4.9.0",
|
|
55
|
+
"vitest": "^3.2.4"
|
|
56
|
+
},
|
|
57
|
+
"eslintConfig": {
|
|
58
|
+
"extends": "@wix/eslint-config-yoshi",
|
|
59
|
+
"ignorePatterns": [
|
|
60
|
+
"**/build/*"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"wix": {
|
|
64
|
+
"artifact": {
|
|
65
|
+
"groupId": "com.wixpress",
|
|
66
|
+
"artifactId": "headless-localization-utils"
|
|
67
|
+
},
|
|
68
|
+
"validations": {
|
|
69
|
+
"source": [
|
|
70
|
+
"lint"
|
|
71
|
+
],
|
|
72
|
+
"postDependenciesBuild": [
|
|
73
|
+
"typecheck"
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"falconPackageHash": "adbcff16f170e15e21f5e703cfcd0b5e183b5258f15ee998fb4dd41f"
|
|
78
|
+
}
|