@wix/headless-localization-utils 1.0.1 → 1.0.3
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 +32 -4
- package/build/index.cjs.map +1 -1
- package/build/index.d.cts +3 -2
- package/build/index.d.ts +3 -2
- package/build/index.js +31 -4
- package/build/index.js.map +1 -1
- package/package.json +3 -3
package/build/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
MULTILINGUAL_COOKIE_HEADER_KEY: () => MULTILINGUAL_COOKIE_HEADER_KEY,
|
|
23
24
|
getLocalizationData: () => getLocalizationData
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -103,8 +104,34 @@ var getLanguageIfExists = (languageCode, availableLocales) => {
|
|
|
103
104
|
);
|
|
104
105
|
};
|
|
105
106
|
|
|
107
|
+
// src/languageHeaderUtils.ts
|
|
108
|
+
var calculateLocaleFromMultilingualCookie = (headers, supportedLanguages) => {
|
|
109
|
+
if (!supportedLanguages.length) {
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
const languageCode = getWixLanguageFromCookie(headers)?.languageCode;
|
|
113
|
+
if (!languageCode) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
return supportedLanguages.find(
|
|
117
|
+
(supportedLanguage) => supportedLanguage.languageCode === languageCode
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
var getWixLanguageFromCookie = (headers) => {
|
|
121
|
+
try {
|
|
122
|
+
const cookies = headers.get("cookie") ?? void 0;
|
|
123
|
+
const languageCookie = cookies?.split(";").find(
|
|
124
|
+
(keyValue) => keyValue.trim().startsWith(`${MULTILINGUAL_COOKIE_HEADER_KEY}=`)
|
|
125
|
+
);
|
|
126
|
+
return languageCookie ? { languageCode: languageCookie.split("=")[1] } : void 0;
|
|
127
|
+
} catch {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
106
132
|
// src/localizationUtils.ts
|
|
107
|
-
|
|
133
|
+
var MULTILINGUAL_COOKIE_HEADER_KEY = `wixLanguage`;
|
|
134
|
+
function getLocalizationData(url, header, siteProperties) {
|
|
108
135
|
const availableLocales = siteProperties?.multilingual?.supportedLanguages ?? [];
|
|
109
136
|
const explicitRequestedLocale = extractLanguageFromUrlAndValidate(
|
|
110
137
|
url,
|
|
@@ -114,11 +141,11 @@ function getLocalizationData(url, siteProperties) {
|
|
|
114
141
|
...availableLocales.map((locale2) => locale2.locale?.languageCode),
|
|
115
142
|
siteProperties?.locale?.languageCode
|
|
116
143
|
].filter((languageCode) => Boolean(languageCode));
|
|
117
|
-
const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
|
|
118
144
|
const locale = buildLocaleString(
|
|
119
|
-
explicitRequestedLocale?.locale ?? siteProperties?.locale
|
|
145
|
+
explicitRequestedLocale?.locale ?? calculateLocaleFromMultilingualCookie(header, availableLocales)?.locale ?? siteProperties?.locale
|
|
120
146
|
) ?? void 0;
|
|
121
|
-
const language = explicitRequestedLocale?.languageCode ?? siteProperties?.language ?? void 0;
|
|
147
|
+
const language = explicitRequestedLocale?.languageCode ?? calculateLocaleFromMultilingualCookie(header, availableLocales)?.languageCode ?? siteProperties?.language ?? void 0;
|
|
148
|
+
const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
|
|
122
149
|
const essentials = {
|
|
123
150
|
language,
|
|
124
151
|
locale,
|
|
@@ -129,6 +156,7 @@ function getLocalizationData(url, siteProperties) {
|
|
|
129
156
|
}
|
|
130
157
|
// Annotate the CommonJS export names for ESM import in node:
|
|
131
158
|
0 && (module.exports = {
|
|
159
|
+
MULTILINGUAL_COOKIE_HEADER_KEY,
|
|
132
160
|
getLocalizationData
|
|
133
161
|
});
|
|
134
162
|
//# sourceMappingURL=index.cjs.map
|
package/build/index.cjs.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/localeUtils.ts","../src/urlUtils.ts","../src/languageHeaderUtils.ts","../src/localizationUtils.ts"],"sourcesContent":["export {\n getLocalizationData,\n type LocalizationData,\n MULTILINGUAL_COOKIE_HEADER_KEY,\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 { scripts } from '@wix/headless-site-assets';\nimport {\n MULTILINGUAL_COOKIE_HEADER_KEY,\n WixLanguage,\n} from './localizationUtils.js';\n\nexport const calculateLocaleFromMultilingualCookie = (\n headers: Headers,\n supportedLanguages: scripts.SupportedLanguage[],\n) => {\n if (!supportedLanguages.length) {\n return undefined;\n }\n\n const languageCode = getWixLanguageFromCookie(headers)?.languageCode;\n if (!languageCode) {\n return undefined;\n }\n return supportedLanguages.find(\n (supportedLanguage) => supportedLanguage.languageCode === languageCode,\n );\n};\n\nconst getWixLanguageFromCookie = (\n headers: Headers,\n): WixLanguage | undefined => {\n try {\n const cookies = headers.get('cookie') ?? undefined;\n\n const languageCookie = cookies\n ?.split(';')\n .find((keyValue) =>\n keyValue.trim().startsWith(`${MULTILINGUAL_COOKIE_HEADER_KEY}=`),\n );\n\n return languageCookie\n ? { languageCode: languageCookie.split('=')[1] }\n : undefined;\n } catch {\n return undefined;\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';\nimport { calculateLocaleFromMultilingualCookie } from './languageHeaderUtils.js';\n\nexport type EssentialProperties = scripts.EssentialProperties;\nexport const MULTILINGUAL_COOKIE_HEADER_KEY = `wixLanguage`;\nexport interface WixLanguage {\n languageCode?: string;\n}\n\nexport type LocalizationData = {\n cleanUrl: string;\n essentials: Essentials;\n};\n\nexport function getLocalizationData(\n url: URL,\n header: Headers,\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 locale =\n buildLocaleString(\n explicitRequestedLocale?.locale ??\n calculateLocaleFromMultilingualCookie(header, availableLocales)\n ?.locale ??\n siteProperties?.locale,\n ) ?? undefined;\n\n const language =\n explicitRequestedLocale?.languageCode ??\n calculateLocaleFromMultilingualCookie(header, availableLocales)\n ?.languageCode ??\n siteProperties?.language ??\n undefined;\n\n const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);\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/build/index.d.cts
CHANGED
|
@@ -2,10 +2,11 @@ import { Essentials } from '@wix/headless-node';
|
|
|
2
2
|
import { scripts } from '@wix/headless-site-assets';
|
|
3
3
|
|
|
4
4
|
type EssentialProperties = scripts.EssentialProperties;
|
|
5
|
+
declare const MULTILINGUAL_COOKIE_HEADER_KEY = "wixLanguage";
|
|
5
6
|
type LocalizationData = {
|
|
6
7
|
cleanUrl: string;
|
|
7
8
|
essentials: Essentials;
|
|
8
9
|
};
|
|
9
|
-
declare function getLocalizationData(url: URL, siteProperties: EssentialProperties): LocalizationData;
|
|
10
|
+
declare function getLocalizationData(url: URL, header: Headers, siteProperties: EssentialProperties): LocalizationData;
|
|
10
11
|
|
|
11
|
-
export { type LocalizationData, getLocalizationData };
|
|
12
|
+
export { type LocalizationData, MULTILINGUAL_COOKIE_HEADER_KEY, getLocalizationData };
|
package/build/index.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ import { Essentials } from '@wix/headless-node';
|
|
|
2
2
|
import { scripts } from '@wix/headless-site-assets';
|
|
3
3
|
|
|
4
4
|
type EssentialProperties = scripts.EssentialProperties;
|
|
5
|
+
declare const MULTILINGUAL_COOKIE_HEADER_KEY = "wixLanguage";
|
|
5
6
|
type LocalizationData = {
|
|
6
7
|
cleanUrl: string;
|
|
7
8
|
essentials: Essentials;
|
|
8
9
|
};
|
|
9
|
-
declare function getLocalizationData(url: URL, siteProperties: EssentialProperties): LocalizationData;
|
|
10
|
+
declare function getLocalizationData(url: URL, header: Headers, siteProperties: EssentialProperties): LocalizationData;
|
|
10
11
|
|
|
11
|
-
export { type LocalizationData, getLocalizationData };
|
|
12
|
+
export { type LocalizationData, MULTILINGUAL_COOKIE_HEADER_KEY, getLocalizationData };
|
package/build/index.js
CHANGED
|
@@ -77,8 +77,34 @@ var getLanguageIfExists = (languageCode, availableLocales) => {
|
|
|
77
77
|
);
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
+
// src/languageHeaderUtils.ts
|
|
81
|
+
var calculateLocaleFromMultilingualCookie = (headers, supportedLanguages) => {
|
|
82
|
+
if (!supportedLanguages.length) {
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
85
|
+
const languageCode = getWixLanguageFromCookie(headers)?.languageCode;
|
|
86
|
+
if (!languageCode) {
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
return supportedLanguages.find(
|
|
90
|
+
(supportedLanguage) => supportedLanguage.languageCode === languageCode
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
var getWixLanguageFromCookie = (headers) => {
|
|
94
|
+
try {
|
|
95
|
+
const cookies = headers.get("cookie") ?? void 0;
|
|
96
|
+
const languageCookie = cookies?.split(";").find(
|
|
97
|
+
(keyValue) => keyValue.trim().startsWith(`${MULTILINGUAL_COOKIE_HEADER_KEY}=`)
|
|
98
|
+
);
|
|
99
|
+
return languageCookie ? { languageCode: languageCookie.split("=")[1] } : void 0;
|
|
100
|
+
} catch {
|
|
101
|
+
return void 0;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
80
105
|
// src/localizationUtils.ts
|
|
81
|
-
|
|
106
|
+
var MULTILINGUAL_COOKIE_HEADER_KEY = `wixLanguage`;
|
|
107
|
+
function getLocalizationData(url, header, siteProperties) {
|
|
82
108
|
const availableLocales = siteProperties?.multilingual?.supportedLanguages ?? [];
|
|
83
109
|
const explicitRequestedLocale = extractLanguageFromUrlAndValidate(
|
|
84
110
|
url,
|
|
@@ -88,11 +114,11 @@ function getLocalizationData(url, siteProperties) {
|
|
|
88
114
|
...availableLocales.map((locale2) => locale2.locale?.languageCode),
|
|
89
115
|
siteProperties?.locale?.languageCode
|
|
90
116
|
].filter((languageCode) => Boolean(languageCode));
|
|
91
|
-
const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
|
|
92
117
|
const locale = buildLocaleString(
|
|
93
|
-
explicitRequestedLocale?.locale ?? siteProperties?.locale
|
|
118
|
+
explicitRequestedLocale?.locale ?? calculateLocaleFromMultilingualCookie(header, availableLocales)?.locale ?? siteProperties?.locale
|
|
94
119
|
) ?? void 0;
|
|
95
|
-
const language = explicitRequestedLocale?.languageCode ?? siteProperties?.language ?? void 0;
|
|
120
|
+
const language = explicitRequestedLocale?.languageCode ?? calculateLocaleFromMultilingualCookie(header, availableLocales)?.languageCode ?? siteProperties?.language ?? void 0;
|
|
121
|
+
const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);
|
|
96
122
|
const essentials = {
|
|
97
123
|
language,
|
|
98
124
|
locale,
|
|
@@ -102,6 +128,7 @@ function getLocalizationData(url, siteProperties) {
|
|
|
102
128
|
return { cleanUrl, essentials };
|
|
103
129
|
}
|
|
104
130
|
export {
|
|
131
|
+
MULTILINGUAL_COOKIE_HEADER_KEY,
|
|
105
132
|
getLocalizationData
|
|
106
133
|
};
|
|
107
134
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"sources":["../src/localeUtils.ts","../src/urlUtils.ts","../src/languageHeaderUtils.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 { scripts } from '@wix/headless-site-assets';\nimport {\n MULTILINGUAL_COOKIE_HEADER_KEY,\n WixLanguage,\n} from './localizationUtils.js';\n\nexport const calculateLocaleFromMultilingualCookie = (\n headers: Headers,\n supportedLanguages: scripts.SupportedLanguage[],\n) => {\n if (!supportedLanguages.length) {\n return undefined;\n }\n\n const languageCode = getWixLanguageFromCookie(headers)?.languageCode;\n if (!languageCode) {\n return undefined;\n }\n return supportedLanguages.find(\n (supportedLanguage) => supportedLanguage.languageCode === languageCode,\n );\n};\n\nconst getWixLanguageFromCookie = (\n headers: Headers,\n): WixLanguage | undefined => {\n try {\n const cookies = headers.get('cookie') ?? undefined;\n\n const languageCookie = cookies\n ?.split(';')\n .find((keyValue) =>\n keyValue.trim().startsWith(`${MULTILINGUAL_COOKIE_HEADER_KEY}=`),\n );\n\n return languageCookie\n ? { languageCode: languageCookie.split('=')[1] }\n : undefined;\n } catch {\n return undefined;\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';\nimport { calculateLocaleFromMultilingualCookie } from './languageHeaderUtils.js';\n\nexport type EssentialProperties = scripts.EssentialProperties;\nexport const MULTILINGUAL_COOKIE_HEADER_KEY = `wixLanguage`;\nexport interface WixLanguage {\n languageCode?: string;\n}\n\nexport type LocalizationData = {\n cleanUrl: string;\n essentials: Essentials;\n};\n\nexport function getLocalizationData(\n url: URL,\n header: Headers,\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 locale =\n buildLocaleString(\n explicitRequestedLocale?.locale ??\n calculateLocaleFromMultilingualCookie(header, availableLocales)\n ?.locale ??\n siteProperties?.locale,\n ) ?? undefined;\n\n const language =\n explicitRequestedLocale?.languageCode ??\n calculateLocaleFromMultilingualCookie(header, availableLocales)\n ?.languageCode ??\n siteProperties?.language ??\n undefined;\n\n const cleanUrl = clearLanguageFromUrl(url.href, languageCodes);\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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/headless-localization-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"unpkg": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"typecheck": "tsc --noEmit"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@wix/headless-node": "1.
|
|
47
|
+
"@wix/headless-node": "1.23.0",
|
|
48
48
|
"@wix/headless-site-assets": "^1.0.9"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
]
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
|
-
"falconPackageHash": "
|
|
77
|
+
"falconPackageHash": "a897f873c70cd942f726a736161c2126fb69392c9ca303c30a79687e"
|
|
78
78
|
}
|