@intlayer/core 7.5.12 → 7.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/deepTransformPlugins/getFilterMissingTranslationsContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getFilterTranslationsOnlyContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getFilteredLocalesContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getLocalizedContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getMaskContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getMissingLocalesContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getMultilingualDictionary.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getReplacedValuesContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/getSplittedContent.cjs.map +1 -1
- package/dist/cjs/deepTransformPlugins/insertContentInDictionary.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/editDictionaryByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/getContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/mergeDictionaries.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/removeContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/dictionaryManipulator/renameContentNodeByKeyPath.cjs.map +1 -1
- package/dist/cjs/dist/esm/getStorageAttributes.cjs +134 -0
- package/dist/cjs/dist/esm/getStorageAttributes.cjs.map +1 -0
- package/dist/cjs/dist/esm/localization/localeResolver.cjs +28 -0
- package/dist/cjs/dist/esm/localization/localeResolver.cjs.map +1 -0
- package/dist/cjs/dist/esm/utils/getCookie.cjs +32 -0
- package/dist/cjs/dist/esm/utils/getCookie.cjs.map +1 -0
- package/dist/cjs/dist/esm/utils/localeStorage.cjs +61 -0
- package/dist/cjs/dist/esm/utils/localeStorage.cjs.map +1 -0
- package/dist/cjs/formatters/date.cjs.map +1 -1
- package/dist/cjs/getStorageAttributes.cjs.map +1 -1
- package/dist/cjs/interpreter/getContent/deepTransform.cjs.map +1 -1
- package/dist/cjs/interpreter/getContent/getContent.cjs.map +1 -1
- package/dist/cjs/interpreter/getContent/plugins.cjs.map +1 -1
- package/dist/cjs/interpreter/getDictionary.cjs.map +1 -1
- package/dist/cjs/interpreter/getNesting.cjs.map +1 -1
- package/dist/cjs/interpreter/getTranslation.cjs.map +1 -1
- package/dist/cjs/localization/getBrowserLocale.cjs.map +1 -1
- package/dist/cjs/localization/getLocale.cjs +4 -3
- package/dist/cjs/localization/getLocale.cjs.map +1 -1
- package/dist/cjs/localization/localeDetector.cjs.map +1 -1
- package/dist/cjs/messageFormat/ICU.cjs.map +1 -1
- package/dist/cjs/messageFormat/i18next.cjs.map +1 -1
- package/dist/cjs/messageFormat/vue-i18n.cjs.map +1 -1
- package/dist/cjs/transpiler/file/file.cjs.map +1 -1
- package/dist/cjs/utils/localeStorage.cjs.map +1 -1
- package/dist/cjs/utils/parseYaml.cjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getFilterMissingTranslationsContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getFilterTranslationsOnlyContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getFilteredLocalesContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getLocalizedContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getMaskContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getMissingLocalesContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getMultilingualDictionary.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getReplacedValuesContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/getSplittedContent.mjs.map +1 -1
- package/dist/esm/deepTransformPlugins/insertContentInDictionary.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/editDictionaryByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/getContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/mergeDictionaries.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/removeContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/dictionaryManipulator/renameContentNodeByKeyPath.mjs.map +1 -1
- package/dist/esm/dist/esm/getStorageAttributes.mjs +133 -0
- package/dist/esm/dist/esm/getStorageAttributes.mjs.map +1 -0
- package/dist/esm/dist/esm/localization/localeResolver.mjs +26 -0
- package/dist/esm/dist/esm/localization/localeResolver.mjs.map +1 -0
- package/dist/esm/dist/esm/utils/getCookie.mjs +31 -0
- package/dist/esm/dist/esm/utils/getCookie.mjs.map +1 -0
- package/dist/esm/dist/esm/utils/localeStorage.mjs +59 -0
- package/dist/esm/dist/esm/utils/localeStorage.mjs.map +1 -0
- package/dist/esm/formatters/date.mjs.map +1 -1
- package/dist/esm/getStorageAttributes.mjs.map +1 -1
- package/dist/esm/interpreter/getContent/deepTransform.mjs.map +1 -1
- package/dist/esm/interpreter/getContent/getContent.mjs.map +1 -1
- package/dist/esm/interpreter/getContent/plugins.mjs.map +1 -1
- package/dist/esm/interpreter/getDictionary.mjs.map +1 -1
- package/dist/esm/interpreter/getNesting.mjs.map +1 -1
- package/dist/esm/interpreter/getTranslation.mjs.map +1 -1
- package/dist/esm/localization/getBrowserLocale.mjs.map +1 -1
- package/dist/esm/localization/getLocale.mjs +2 -1
- package/dist/esm/localization/getLocale.mjs.map +1 -1
- package/dist/esm/localization/localeDetector.mjs.map +1 -1
- package/dist/esm/messageFormat/ICU.mjs.map +1 -1
- package/dist/esm/messageFormat/i18next.mjs.map +1 -1
- package/dist/esm/messageFormat/vue-i18n.mjs.map +1 -1
- package/dist/esm/transpiler/file/file.mjs.map +1 -1
- package/dist/esm/utils/localeStorage.mjs.map +1 -1
- package/dist/esm/utils/parseYaml.mjs.map +1 -1
- package/dist/types/deepTransformPlugins/getFilterMissingTranslationsContent.d.ts +8 -8
- package/dist/types/deepTransformPlugins/getFilterTranslationsOnlyContent.d.ts +8 -8
- package/dist/types/dictionaryManipulator/orderDictionaries.d.ts +2 -2
- package/dist/types/dictionaryManipulator/orderDictionaries.d.ts.map +1 -1
- package/dist/types/interpreter/getContent/plugins.d.ts.map +1 -1
- package/dist/types/messageFormat/ICU.d.ts.map +1 -1
- package/dist/types/transpiler/enumeration/enumeration.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { DefaultValues } from "@intlayer/config/client";
|
|
2
|
+
|
|
3
|
+
//#region dist/esm/getStorageAttributes.mjs
|
|
4
|
+
/**
|
|
5
|
+
* Creates a cookie entry with default values for missing attributes
|
|
6
|
+
*/
|
|
7
|
+
const createCookieEntry = (options) => {
|
|
8
|
+
const { name, path, expires, domain, secure, sameSite, httpOnly } = options ?? {};
|
|
9
|
+
return {
|
|
10
|
+
name: name ?? DefaultValues.Routing.COOKIE_NAME,
|
|
11
|
+
attributes: {
|
|
12
|
+
path,
|
|
13
|
+
expires,
|
|
14
|
+
domain,
|
|
15
|
+
secure,
|
|
16
|
+
sameSite,
|
|
17
|
+
httpOnly
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Creates a web storage entry (localStorage or sessionStorage) with default name
|
|
23
|
+
*/
|
|
24
|
+
const createWebStorageEntry = (options) => {
|
|
25
|
+
const { name } = options ?? {};
|
|
26
|
+
return { name: name ?? DefaultValues.Routing.LOCALE_STORAGE_NAME };
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Creates a header entry with default name
|
|
30
|
+
*/
|
|
31
|
+
const createHeaderEntry = (options) => {
|
|
32
|
+
const { name } = options ?? {};
|
|
33
|
+
return { name: name ?? DefaultValues.Routing.HEADER_NAME };
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Determines if a storage entry is a cookie based on its properties
|
|
37
|
+
*/
|
|
38
|
+
const isCookieEntry = (entry) => {
|
|
39
|
+
return entry.type === "cookie" || "sameSite" in entry || "httpOnly" in entry || "secure" in entry;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Determines the storage type from a string literal
|
|
43
|
+
*/
|
|
44
|
+
const isStorageType = (value) => {
|
|
45
|
+
return value === "cookie" || value === "localStorage" || value === "sessionStorage" || value === "header";
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Processes a single storage entry and returns the appropriate storage attributes
|
|
49
|
+
*/
|
|
50
|
+
const processStorageEntry = (entry) => {
|
|
51
|
+
if (typeof entry === "string") {
|
|
52
|
+
if (!isStorageType(entry)) return {
|
|
53
|
+
cookies: [],
|
|
54
|
+
localStorage: [],
|
|
55
|
+
sessionStorage: [],
|
|
56
|
+
headers: []
|
|
57
|
+
};
|
|
58
|
+
if (entry === "cookie") return { cookies: [createCookieEntry()] };
|
|
59
|
+
if (entry === "localStorage") return { localStorage: [createWebStorageEntry()] };
|
|
60
|
+
if (entry === "sessionStorage") return { sessionStorage: [createWebStorageEntry()] };
|
|
61
|
+
if (entry === "header") return { headers: [createHeaderEntry()] };
|
|
62
|
+
}
|
|
63
|
+
if (typeof entry === "object" && entry !== null) {
|
|
64
|
+
const typedEntry = entry;
|
|
65
|
+
if (isCookieEntry(typedEntry)) return { cookies: [createCookieEntry(typedEntry)] };
|
|
66
|
+
if ("type" in typedEntry && typedEntry.type === "localStorage") {
|
|
67
|
+
const { name: name$1, ...rest$1 } = typedEntry;
|
|
68
|
+
return { localStorage: [createWebStorageEntry({
|
|
69
|
+
name: name$1,
|
|
70
|
+
...rest$1
|
|
71
|
+
})] };
|
|
72
|
+
}
|
|
73
|
+
if ("type" in typedEntry && typedEntry.type === "sessionStorage") {
|
|
74
|
+
const { name: name$1, ...rest$1 } = typedEntry;
|
|
75
|
+
return { sessionStorage: [createWebStorageEntry({
|
|
76
|
+
name: name$1,
|
|
77
|
+
...rest$1
|
|
78
|
+
})] };
|
|
79
|
+
}
|
|
80
|
+
if ("type" in typedEntry && typedEntry.type === "header") {
|
|
81
|
+
const { name: name$1, ...rest$1 } = typedEntry;
|
|
82
|
+
return { headers: [createHeaderEntry({
|
|
83
|
+
name: name$1,
|
|
84
|
+
...rest$1
|
|
85
|
+
})] };
|
|
86
|
+
}
|
|
87
|
+
const { name, ...rest } = typedEntry;
|
|
88
|
+
return { localStorage: [createWebStorageEntry({
|
|
89
|
+
name,
|
|
90
|
+
...rest
|
|
91
|
+
})] };
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
cookies: [],
|
|
95
|
+
localStorage: [],
|
|
96
|
+
sessionStorage: [],
|
|
97
|
+
headers: []
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Merges multiple partial storage attributes into a single result
|
|
102
|
+
*/
|
|
103
|
+
const mergeStorageAttributes = (accumulated, partial) => {
|
|
104
|
+
return {
|
|
105
|
+
cookies: [...accumulated.cookies, ...partial.cookies ?? []],
|
|
106
|
+
localStorage: [...accumulated.localStorage, ...partial.localStorage ?? []],
|
|
107
|
+
sessionStorage: [...accumulated.sessionStorage, ...partial.sessionStorage ?? []],
|
|
108
|
+
headers: [...accumulated.headers, ...partial.headers ?? []]
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Extracts and normalizes storage configuration into separate arrays for each storage type
|
|
113
|
+
*
|
|
114
|
+
* @param options - The storage configuration from IntlayerConfig
|
|
115
|
+
* @returns An object containing arrays for cookies, localStorage, and sessionStorage
|
|
116
|
+
*/
|
|
117
|
+
const getStorageAttributes = (options) => {
|
|
118
|
+
const emptyResult = {
|
|
119
|
+
cookies: [],
|
|
120
|
+
localStorage: [],
|
|
121
|
+
sessionStorage: [],
|
|
122
|
+
headers: []
|
|
123
|
+
};
|
|
124
|
+
if (options === false || options === void 0) return emptyResult;
|
|
125
|
+
if (Array.isArray(options)) return options.reduce((acc, entry) => {
|
|
126
|
+
return mergeStorageAttributes(acc, processStorageEntry(entry));
|
|
127
|
+
}, emptyResult);
|
|
128
|
+
return mergeStorageAttributes(emptyResult, processStorageEntry(options));
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
export { getStorageAttributes };
|
|
133
|
+
//# sourceMappingURL=getStorageAttributes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getStorageAttributes.mjs","names":[],"sources":["../../getStorageAttributes.mjs"],"sourcesContent":["import { DefaultValues } from \"@intlayer/config/client\";\n\n//#region src/getStorageAttributes.ts\n/**\n* Creates a cookie entry with default values for missing attributes\n*/\nconst createCookieEntry = (options) => {\n\tconst { name, path, expires, domain, secure, sameSite, httpOnly } = options ?? {};\n\treturn {\n\t\tname: name ?? DefaultValues.Routing.COOKIE_NAME,\n\t\tattributes: {\n\t\t\tpath,\n\t\t\texpires,\n\t\t\tdomain,\n\t\t\tsecure,\n\t\t\tsameSite,\n\t\t\thttpOnly\n\t\t}\n\t};\n};\n/**\n* Creates a web storage entry (localStorage or sessionStorage) with default name\n*/\nconst createWebStorageEntry = (options) => {\n\tconst { name } = options ?? {};\n\treturn { name: name ?? DefaultValues.Routing.LOCALE_STORAGE_NAME };\n};\n/**\n* Creates a header entry with default name\n*/\nconst createHeaderEntry = (options) => {\n\tconst { name } = options ?? {};\n\treturn { name: name ?? DefaultValues.Routing.HEADER_NAME };\n};\n/**\n* Determines if a storage entry is a cookie based on its properties\n*/\nconst isCookieEntry = (entry) => {\n\treturn entry.type === \"cookie\" || \"sameSite\" in entry || \"httpOnly\" in entry || \"secure\" in entry;\n};\n/**\n* Determines the storage type from a string literal\n*/\nconst isStorageType = (value) => {\n\treturn value === \"cookie\" || value === \"localStorage\" || value === \"sessionStorage\" || value === \"header\";\n};\n/**\n* Processes a single storage entry and returns the appropriate storage attributes\n*/\nconst processStorageEntry = (entry) => {\n\tif (typeof entry === \"string\") {\n\t\tif (!isStorageType(entry)) return {\n\t\t\tcookies: [],\n\t\t\tlocalStorage: [],\n\t\t\tsessionStorage: [],\n\t\t\theaders: []\n\t\t};\n\t\tif (entry === \"cookie\") return { cookies: [createCookieEntry()] };\n\t\tif (entry === \"localStorage\") return { localStorage: [createWebStorageEntry()] };\n\t\tif (entry === \"sessionStorage\") return { sessionStorage: [createWebStorageEntry()] };\n\t\tif (entry === \"header\") return { headers: [createHeaderEntry()] };\n\t}\n\tif (typeof entry === \"object\" && entry !== null) {\n\t\tconst typedEntry = entry;\n\t\tif (isCookieEntry(typedEntry)) return { cookies: [createCookieEntry(typedEntry)] };\n\t\tif (\"type\" in typedEntry && typedEntry.type === \"localStorage\") {\n\t\t\tconst { name: name$1, ...rest$1 } = typedEntry;\n\t\t\treturn { localStorage: [createWebStorageEntry({\n\t\t\t\tname: name$1,\n\t\t\t\t...rest$1\n\t\t\t})] };\n\t\t}\n\t\tif (\"type\" in typedEntry && typedEntry.type === \"sessionStorage\") {\n\t\t\tconst { name: name$1, ...rest$1 } = typedEntry;\n\t\t\treturn { sessionStorage: [createWebStorageEntry({\n\t\t\t\tname: name$1,\n\t\t\t\t...rest$1\n\t\t\t})] };\n\t\t}\n\t\tif (\"type\" in typedEntry && typedEntry.type === \"header\") {\n\t\t\tconst { name: name$1, ...rest$1 } = typedEntry;\n\t\t\treturn { headers: [createHeaderEntry({\n\t\t\t\tname: name$1,\n\t\t\t\t...rest$1\n\t\t\t})] };\n\t\t}\n\t\tconst { name, ...rest } = typedEntry;\n\t\treturn { localStorage: [createWebStorageEntry({\n\t\t\tname,\n\t\t\t...rest\n\t\t})] };\n\t}\n\treturn {\n\t\tcookies: [],\n\t\tlocalStorage: [],\n\t\tsessionStorage: [],\n\t\theaders: []\n\t};\n};\n/**\n* Merges multiple partial storage attributes into a single result\n*/\nconst mergeStorageAttributes = (accumulated, partial) => {\n\treturn {\n\t\tcookies: [...accumulated.cookies, ...partial.cookies ?? []],\n\t\tlocalStorage: [...accumulated.localStorage, ...partial.localStorage ?? []],\n\t\tsessionStorage: [...accumulated.sessionStorage, ...partial.sessionStorage ?? []],\n\t\theaders: [...accumulated.headers, ...partial.headers ?? []]\n\t};\n};\n/**\n* Extracts and normalizes storage configuration into separate arrays for each storage type\n*\n* @param options - The storage configuration from IntlayerConfig\n* @returns An object containing arrays for cookies, localStorage, and sessionStorage\n*/\nconst getStorageAttributes = (options) => {\n\tconst emptyResult = {\n\t\tcookies: [],\n\t\tlocalStorage: [],\n\t\tsessionStorage: [],\n\t\theaders: []\n\t};\n\tif (options === false || options === void 0) return emptyResult;\n\tif (Array.isArray(options)) return options.reduce((acc, entry) => {\n\t\treturn mergeStorageAttributes(acc, processStorageEntry(entry));\n\t}, emptyResult);\n\treturn mergeStorageAttributes(emptyResult, processStorageEntry(options));\n};\n\n//#endregion\nexport { getStorageAttributes };\n//# sourceMappingURL=getStorageAttributes.mjs.map"],"mappings":";;;;;;AAMA,MAAM,qBAAqB,YAAY;CACtC,MAAM,EAAE,MAAM,MAAM,SAAS,QAAQ,QAAQ,UAAU,aAAa,WAAW,EAAE;AACjF,QAAO;EACN,MAAM,QAAQ,cAAc,QAAQ;EACpC,YAAY;GACX;GACA;GACA;GACA;GACA;GACA;GACA;EACD;;;;;AAKF,MAAM,yBAAyB,YAAY;CAC1C,MAAM,EAAE,SAAS,WAAW,EAAE;AAC9B,QAAO,EAAE,MAAM,QAAQ,cAAc,QAAQ,qBAAqB;;;;;AAKnE,MAAM,qBAAqB,YAAY;CACtC,MAAM,EAAE,SAAS,WAAW,EAAE;AAC9B,QAAO,EAAE,MAAM,QAAQ,cAAc,QAAQ,aAAa;;;;;AAK3D,MAAM,iBAAiB,UAAU;AAChC,QAAO,MAAM,SAAS,YAAY,cAAc,SAAS,cAAc,SAAS,YAAY;;;;;AAK7F,MAAM,iBAAiB,UAAU;AAChC,QAAO,UAAU,YAAY,UAAU,kBAAkB,UAAU,oBAAoB,UAAU;;;;;AAKlG,MAAM,uBAAuB,UAAU;AACtC,KAAI,OAAO,UAAU,UAAU;AAC9B,MAAI,CAAC,cAAc,MAAM,CAAE,QAAO;GACjC,SAAS,EAAE;GACX,cAAc,EAAE;GAChB,gBAAgB,EAAE;GAClB,SAAS,EAAE;GACX;AACD,MAAI,UAAU,SAAU,QAAO,EAAE,SAAS,CAAC,mBAAmB,CAAC,EAAE;AACjE,MAAI,UAAU,eAAgB,QAAO,EAAE,cAAc,CAAC,uBAAuB,CAAC,EAAE;AAChF,MAAI,UAAU,iBAAkB,QAAO,EAAE,gBAAgB,CAAC,uBAAuB,CAAC,EAAE;AACpF,MAAI,UAAU,SAAU,QAAO,EAAE,SAAS,CAAC,mBAAmB,CAAC,EAAE;;AAElE,KAAI,OAAO,UAAU,YAAY,UAAU,MAAM;EAChD,MAAM,aAAa;AACnB,MAAI,cAAc,WAAW,CAAE,QAAO,EAAE,SAAS,CAAC,kBAAkB,WAAW,CAAC,EAAE;AAClF,MAAI,UAAU,cAAc,WAAW,SAAS,gBAAgB;GAC/D,MAAM,EAAE,MAAM,QAAQ,GAAG,WAAW;AACpC,UAAO,EAAE,cAAc,CAAC,sBAAsB;IAC7C,MAAM;IACN,GAAG;IACH,CAAC,CAAC,EAAE;;AAEN,MAAI,UAAU,cAAc,WAAW,SAAS,kBAAkB;GACjE,MAAM,EAAE,MAAM,QAAQ,GAAG,WAAW;AACpC,UAAO,EAAE,gBAAgB,CAAC,sBAAsB;IAC/C,MAAM;IACN,GAAG;IACH,CAAC,CAAC,EAAE;;AAEN,MAAI,UAAU,cAAc,WAAW,SAAS,UAAU;GACzD,MAAM,EAAE,MAAM,QAAQ,GAAG,WAAW;AACpC,UAAO,EAAE,SAAS,CAAC,kBAAkB;IACpC,MAAM;IACN,GAAG;IACH,CAAC,CAAC,EAAE;;EAEN,MAAM,EAAE,MAAM,GAAG,SAAS;AAC1B,SAAO,EAAE,cAAc,CAAC,sBAAsB;GAC7C;GACA,GAAG;GACH,CAAC,CAAC,EAAE;;AAEN,QAAO;EACN,SAAS,EAAE;EACX,cAAc,EAAE;EAChB,gBAAgB,EAAE;EAClB,SAAS,EAAE;EACX;;;;;AAKF,MAAM,0BAA0B,aAAa,YAAY;AACxD,QAAO;EACN,SAAS,CAAC,GAAG,YAAY,SAAS,GAAG,QAAQ,WAAW,EAAE,CAAC;EAC3D,cAAc,CAAC,GAAG,YAAY,cAAc,GAAG,QAAQ,gBAAgB,EAAE,CAAC;EAC1E,gBAAgB,CAAC,GAAG,YAAY,gBAAgB,GAAG,QAAQ,kBAAkB,EAAE,CAAC;EAChF,SAAS,CAAC,GAAG,YAAY,SAAS,GAAG,QAAQ,WAAW,EAAE,CAAC;EAC3D;;;;;;;;AAQF,MAAM,wBAAwB,YAAY;CACzC,MAAM,cAAc;EACnB,SAAS,EAAE;EACX,cAAc,EAAE;EAChB,gBAAgB,EAAE;EAClB,SAAS,EAAE;EACX;AACD,KAAI,YAAY,SAAS,YAAY,KAAK,EAAG,QAAO;AACpD,KAAI,MAAM,QAAQ,QAAQ,CAAE,QAAO,QAAQ,QAAQ,KAAK,UAAU;AACjE,SAAO,uBAAuB,KAAK,oBAAoB,MAAM,CAAC;IAC5D,YAAY;AACf,QAAO,uBAAuB,aAAa,oBAAoB,QAAQ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import configuration from "@intlayer/config/built";
|
|
2
|
+
|
|
3
|
+
//#region dist/esm/localization/localeResolver.mjs
|
|
4
|
+
/**
|
|
5
|
+
* Resolves the most specific locale from a user-provided list,
|
|
6
|
+
* or falls back to the default locale if no match is found.
|
|
7
|
+
*/
|
|
8
|
+
const localeResolver = (selectedLocale, locales = configuration?.internationalization?.locales, defaultLocale = configuration?.internationalization?.defaultLocale) => {
|
|
9
|
+
const requestedLocales = [selectedLocale].flat();
|
|
10
|
+
const normalize = (locale) => locale.trim().toLowerCase();
|
|
11
|
+
try {
|
|
12
|
+
for (const requested of requestedLocales) {
|
|
13
|
+
const normalizedRequested = normalize(requested);
|
|
14
|
+
const exactMatch = locales.find((loc) => normalize(loc) === normalizedRequested);
|
|
15
|
+
if (exactMatch) return exactMatch;
|
|
16
|
+
const [requestedLang] = normalizedRequested.split("-");
|
|
17
|
+
const partialMatch = locales.find((loc) => normalize(loc).split("-")[0] === requestedLang);
|
|
18
|
+
if (partialMatch) return partialMatch;
|
|
19
|
+
}
|
|
20
|
+
} catch (_error) {}
|
|
21
|
+
return defaultLocale;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { localeResolver };
|
|
26
|
+
//# sourceMappingURL=localeResolver.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localeResolver.mjs","names":[],"sources":["../../../localization/localeResolver.mjs"],"sourcesContent":["import configuration from \"@intlayer/config/built\";\n\n//#region src/localization/localeResolver.ts\n/**\n* Resolves the most specific locale from a user-provided list,\n* or falls back to the default locale if no match is found.\n*/\nconst localeResolver = (selectedLocale, locales = configuration?.internationalization?.locales, defaultLocale = configuration?.internationalization?.defaultLocale) => {\n\tconst requestedLocales = [selectedLocale].flat();\n\tconst normalize = (locale) => locale.trim().toLowerCase();\n\ttry {\n\t\tfor (const requested of requestedLocales) {\n\t\t\tconst normalizedRequested = normalize(requested);\n\t\t\tconst exactMatch = locales.find((loc) => normalize(loc) === normalizedRequested);\n\t\t\tif (exactMatch) return exactMatch;\n\t\t\tconst [requestedLang] = normalizedRequested.split(\"-\");\n\t\t\tconst partialMatch = locales.find((loc) => normalize(loc).split(\"-\")[0] === requestedLang);\n\t\t\tif (partialMatch) return partialMatch;\n\t\t}\n\t} catch (_error) {}\n\treturn defaultLocale;\n};\n\n//#endregion\nexport { localeResolver };\n//# sourceMappingURL=localeResolver.mjs.map"],"mappings":";;;;;;;AAOA,MAAM,kBAAkB,gBAAgB,UAAU,eAAe,sBAAsB,SAAS,gBAAgB,eAAe,sBAAsB,kBAAkB;CACtK,MAAM,mBAAmB,CAAC,eAAe,CAAC,MAAM;CAChD,MAAM,aAAa,WAAW,OAAO,MAAM,CAAC,aAAa;AACzD,KAAI;AACH,OAAK,MAAM,aAAa,kBAAkB;GACzC,MAAM,sBAAsB,UAAU,UAAU;GAChD,MAAM,aAAa,QAAQ,MAAM,QAAQ,UAAU,IAAI,KAAK,oBAAoB;AAChF,OAAI,WAAY,QAAO;GACvB,MAAM,CAAC,iBAAiB,oBAAoB,MAAM,IAAI;GACtD,MAAM,eAAe,QAAQ,MAAM,QAAQ,UAAU,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,cAAc;AAC1F,OAAI,aAAc,QAAO;;UAElB,QAAQ;AACjB,QAAO"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region dist/esm/utils/getCookie.mjs
|
|
2
|
+
/**
|
|
3
|
+
* Retrieves a cookie by name from a cookie string or document.cookie
|
|
4
|
+
* @param name - The name of the cookie to retrieve
|
|
5
|
+
* @param cookieString - Optional cookie string to parse (defaults to document.cookie in browser)
|
|
6
|
+
* @returns The cookie value or undefined if not found
|
|
7
|
+
*/
|
|
8
|
+
const getCookie = (name, cookieString) => {
|
|
9
|
+
try {
|
|
10
|
+
const str = cookieString ?? (typeof document !== "undefined" ? document.cookie : "");
|
|
11
|
+
if (!str) return void 0;
|
|
12
|
+
const pairs = str.split(";");
|
|
13
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
14
|
+
const part = pairs[i].trim();
|
|
15
|
+
if (!part) continue;
|
|
16
|
+
const equalIndex = part.indexOf("=");
|
|
17
|
+
if ((equalIndex >= 0 ? part.substring(0, equalIndex) : part) === name) {
|
|
18
|
+
const rawValue = equalIndex >= 0 ? part.substring(equalIndex + 1) : "";
|
|
19
|
+
try {
|
|
20
|
+
return decodeURIComponent(rawValue);
|
|
21
|
+
} catch {
|
|
22
|
+
return rawValue;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch {}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { getCookie };
|
|
31
|
+
//# sourceMappingURL=getCookie.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getCookie.mjs","names":[],"sources":["../../../utils/getCookie.mjs"],"sourcesContent":["//#region src/utils/getCookie.ts\n/**\n* Retrieves a cookie by name from a cookie string or document.cookie\n* @param name - The name of the cookie to retrieve\n* @param cookieString - Optional cookie string to parse (defaults to document.cookie in browser)\n* @returns The cookie value or undefined if not found\n*/\nconst getCookie = (name, cookieString) => {\n\ttry {\n\t\tconst str = cookieString ?? (typeof document !== \"undefined\" ? document.cookie : \"\");\n\t\tif (!str) return void 0;\n\t\tconst pairs = str.split(\";\");\n\t\tfor (let i = 0; i < pairs.length; i++) {\n\t\t\tconst part = pairs[i].trim();\n\t\t\tif (!part) continue;\n\t\t\tconst equalIndex = part.indexOf(\"=\");\n\t\t\tif ((equalIndex >= 0 ? part.substring(0, equalIndex) : part) === name) {\n\t\t\t\tconst rawValue = equalIndex >= 0 ? part.substring(equalIndex + 1) : \"\";\n\t\t\t\ttry {\n\t\t\t\t\treturn decodeURIComponent(rawValue);\n\t\t\t\t} catch {\n\t\t\t\t\treturn rawValue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {}\n};\n\n//#endregion\nexport { getCookie };\n//# sourceMappingURL=getCookie.mjs.map"],"mappings":";;;;;;;AAOA,MAAM,aAAa,MAAM,iBAAiB;AACzC,KAAI;EACH,MAAM,MAAM,iBAAiB,OAAO,aAAa,cAAc,SAAS,SAAS;AACjF,MAAI,CAAC,IAAK,QAAO,KAAK;EACtB,MAAM,QAAQ,IAAI,MAAM,IAAI;AAC5B,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACtC,MAAM,OAAO,MAAM,GAAG,MAAM;AAC5B,OAAI,CAAC,KAAM;GACX,MAAM,aAAa,KAAK,QAAQ,IAAI;AACpC,QAAK,cAAc,IAAI,KAAK,UAAU,GAAG,WAAW,GAAG,UAAU,MAAM;IACtE,MAAM,WAAW,cAAc,IAAI,KAAK,UAAU,aAAa,EAAE,GAAG;AACpE,QAAI;AACH,YAAO,mBAAmB,SAAS;YAC5B;AACP,YAAO;;;;SAIH"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getStorageAttributes } from "../getStorageAttributes.mjs";
|
|
2
|
+
import { getCookie } from "./getCookie.mjs";
|
|
3
|
+
import configuration from "@intlayer/config/built";
|
|
4
|
+
|
|
5
|
+
//#region dist/esm/utils/localeStorage.mjs
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).
|
|
8
|
+
* The function checks storage locations in order of priority as defined in the configuration.
|
|
9
|
+
*
|
|
10
|
+
* @returns The locale if found in any storage, or undefined if not found
|
|
11
|
+
*/
|
|
12
|
+
const getLocaleFromStorage = (options) => {
|
|
13
|
+
const { routing, internationalization } = configuration;
|
|
14
|
+
const { locales } = internationalization;
|
|
15
|
+
const { storage } = routing;
|
|
16
|
+
if (storage === false || options?.isCookieEnabled === false) return void 0;
|
|
17
|
+
const storageAttributes = getStorageAttributes(storage);
|
|
18
|
+
const isValidLocale = (value) => {
|
|
19
|
+
if (!value) return false;
|
|
20
|
+
return locales.includes(value);
|
|
21
|
+
};
|
|
22
|
+
const readCookie = (name) => {
|
|
23
|
+
try {
|
|
24
|
+
const fromOption = options?.getCookie?.(name);
|
|
25
|
+
if (fromOption !== null && fromOption !== void 0) return fromOption;
|
|
26
|
+
} catch {}
|
|
27
|
+
return getCookie(name);
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < storageAttributes.cookies.length; i++) {
|
|
30
|
+
const { name } = storageAttributes.cookies[i];
|
|
31
|
+
const value = readCookie(name);
|
|
32
|
+
if (isValidLocale(value)) return value;
|
|
33
|
+
}
|
|
34
|
+
for (let i = 0; i < storageAttributes.localStorage.length; i++) {
|
|
35
|
+
const { name } = storageAttributes.localStorage[i];
|
|
36
|
+
try {
|
|
37
|
+
const value = options?.getLocaleStorage?.(name);
|
|
38
|
+
if (isValidLocale(value)) return value;
|
|
39
|
+
} catch {}
|
|
40
|
+
}
|
|
41
|
+
for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {
|
|
42
|
+
const { name } = storageAttributes.sessionStorage[i];
|
|
43
|
+
try {
|
|
44
|
+
const value = options?.getSessionStorage?.(name);
|
|
45
|
+
if (isValidLocale(value)) return value;
|
|
46
|
+
} catch {}
|
|
47
|
+
}
|
|
48
|
+
for (let i = 0; i < storageAttributes.headers.length; i++) {
|
|
49
|
+
const { name } = storageAttributes.headers[i];
|
|
50
|
+
try {
|
|
51
|
+
const value = options?.getHeader?.(name);
|
|
52
|
+
if (isValidLocale(value)) return value;
|
|
53
|
+
} catch {}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { getLocaleFromStorage };
|
|
59
|
+
//# sourceMappingURL=localeStorage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localeStorage.mjs","names":[],"sources":["../../../utils/localeStorage.mjs"],"sourcesContent":["import { getStorageAttributes } from \"../getStorageAttributes.mjs\";\nimport { getCookie } from \"./getCookie.mjs\";\nimport configuration from \"@intlayer/config/built\";\n\n//#region src/utils/localeStorage.ts\nconst buildCookieString = (name, value, attributes) => {\n\tconst parts = [`${name}=${encodeURIComponent(value)}`];\n\tif (attributes.path) parts.push(`Path=${attributes.path}`);\n\tif (attributes.domain) parts.push(`Domain=${attributes.domain}`);\n\tif (attributes.expires instanceof Date) parts.push(`Expires=${attributes.expires.toUTCString()}`);\n\tif (attributes.secure) parts.push(\"Secure\");\n\tif (attributes.sameSite) parts.push(`SameSite=${attributes.sameSite}`);\n\treturn parts.join(\"; \");\n};\n/**\n* Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n* The function checks storage locations in order of priority as defined in the configuration.\n*\n* @returns The locale if found in any storage, or undefined if not found\n*/\nconst getLocaleFromStorage = (options) => {\n\tconst { routing, internationalization } = configuration;\n\tconst { locales } = internationalization;\n\tconst { storage } = routing;\n\tif (storage === false || options?.isCookieEnabled === false) return void 0;\n\tconst storageAttributes = getStorageAttributes(storage);\n\tconst isValidLocale = (value) => {\n\t\tif (!value) return false;\n\t\treturn locales.includes(value);\n\t};\n\tconst readCookie = (name) => {\n\t\ttry {\n\t\t\tconst fromOption = options?.getCookie?.(name);\n\t\t\tif (fromOption !== null && fromOption !== void 0) return fromOption;\n\t\t} catch {}\n\t\treturn getCookie(name);\n\t};\n\tfor (let i = 0; i < storageAttributes.cookies.length; i++) {\n\t\tconst { name } = storageAttributes.cookies[i];\n\t\tconst value = readCookie(name);\n\t\tif (isValidLocale(value)) return value;\n\t}\n\tfor (let i = 0; i < storageAttributes.localStorage.length; i++) {\n\t\tconst { name } = storageAttributes.localStorage[i];\n\t\ttry {\n\t\t\tconst value = options?.getLocaleStorage?.(name);\n\t\t\tif (isValidLocale(value)) return value;\n\t\t} catch {}\n\t}\n\tfor (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n\t\tconst { name } = storageAttributes.sessionStorage[i];\n\t\ttry {\n\t\t\tconst value = options?.getSessionStorage?.(name);\n\t\t\tif (isValidLocale(value)) return value;\n\t\t} catch {}\n\t}\n\tfor (let i = 0; i < storageAttributes.headers.length; i++) {\n\t\tconst { name } = storageAttributes.headers[i];\n\t\ttry {\n\t\t\tconst value = options?.getHeader?.(name);\n\t\t\tif (isValidLocale(value)) return value;\n\t\t} catch {}\n\t}\n};\n/**\n* Stores the locale in various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n* The function writes to all configured storage locations according to their attributes.\n* Respects overwrite flags for localStorage and sessionStorage.\n*\n* @param locale - The locale to store\n*/\nconst setLocaleInStorage = (locale, options) => {\n\tif (configuration.routing.storage === false || options?.isCookieEnabled === false) return;\n\tconst storageAttributes = getStorageAttributes(configuration.routing.storage);\n\tfor (let i = 0; i < storageAttributes.cookies.length; i++) {\n\t\tconst { name, attributes } = storageAttributes.cookies[i];\n\t\ttry {\n\t\t\tif (options?.setCookieStore) options?.setCookieStore?.(name, locale, {\n\t\t\t\t...attributes,\n\t\t\t\texpires: attributes.expires instanceof Date ? attributes.expires.getTime() : attributes.expires\n\t\t\t});\n\t\t} catch {\n\t\t\ttry {\n\t\t\t\tif (options?.setCookieString) {\n\t\t\t\t\tconst cookieString = buildCookieString(name, locale, attributes);\n\t\t\t\t\toptions?.setCookieString?.(name, cookieString);\n\t\t\t\t}\n\t\t\t} catch {}\n\t\t}\n\t}\n\tif (options?.setLocaleStorage) for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n\t\tconst { name } = storageAttributes.localStorage[i];\n\t\ttry {\n\t\t\tif (!(options?.overwrite ?? true) && options?.getLocaleStorage) {\n\t\t\t\tif (options?.getLocaleStorage?.(name)) continue;\n\t\t\t}\n\t\t\toptions?.setLocaleStorage?.(name, locale);\n\t\t} catch {}\n\t}\n\tif (options?.setSessionStorage) for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n\t\tconst { name } = storageAttributes.sessionStorage[i];\n\t\ttry {\n\t\t\tif (!(options?.overwrite ?? true) && options?.getSessionStorage) {\n\t\t\t\tif (options?.getSessionStorage?.(name)) continue;\n\t\t\t}\n\t\t\toptions?.setSessionStorage?.(name, locale);\n\t\t} catch {}\n\t}\n\tif (options?.setHeader) for (let i = 0; i < storageAttributes.headers.length; i++) {\n\t\tconst { name } = storageAttributes.headers[i];\n\t\ttry {\n\t\t\toptions?.setHeader?.(name, locale);\n\t\t} catch {}\n\t}\n};\n/**\n* Utility object to get and set the locale in the storage by considering the configuration\n*\n* @property getLocale - Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n* Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n* The function checks storage locations in order of priority as defined in the configuration.\n*\n* @property setLocale - Stores the locale in various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n* The function writes to all configured storage locations according to their attributes.\n* Respects overwrite flags for localStorage and sessionStorage.\n*\n* @returns The locale if found in any storage, or undefined if not found\n*/\nconst LocaleStorage = (options) => ({\n\tgetLocale: () => getLocaleFromStorage(options),\n\tsetLocale: (locale) => setLocaleInStorage(locale, options)\n});\n\n//#endregion\nexport { LocaleStorage, getLocaleFromStorage, setLocaleInStorage };\n//# sourceMappingURL=localeStorage.mjs.map"],"mappings":";;;;;;;;;;;AAoBA,MAAM,wBAAwB,YAAY;CACzC,MAAM,EAAE,SAAS,yBAAyB;CAC1C,MAAM,EAAE,YAAY;CACpB,MAAM,EAAE,YAAY;AACpB,KAAI,YAAY,SAAS,SAAS,oBAAoB,MAAO,QAAO,KAAK;CACzE,MAAM,oBAAoB,qBAAqB,QAAQ;CACvD,MAAM,iBAAiB,UAAU;AAChC,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,QAAQ,SAAS,MAAM;;CAE/B,MAAM,cAAc,SAAS;AAC5B,MAAI;GACH,MAAM,aAAa,SAAS,YAAY,KAAK;AAC7C,OAAI,eAAe,QAAQ,eAAe,KAAK,EAAG,QAAO;UAClD;AACR,SAAO,UAAU,KAAK;;AAEvB,MAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,QAAQ,KAAK;EAC1D,MAAM,EAAE,SAAS,kBAAkB,QAAQ;EAC3C,MAAM,QAAQ,WAAW,KAAK;AAC9B,MAAI,cAAc,MAAM,CAAE,QAAO;;AAElC,MAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,aAAa,QAAQ,KAAK;EAC/D,MAAM,EAAE,SAAS,kBAAkB,aAAa;AAChD,MAAI;GACH,MAAM,QAAQ,SAAS,mBAAmB,KAAK;AAC/C,OAAI,cAAc,MAAM,CAAE,QAAO;UAC1B;;AAET,MAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,eAAe,QAAQ,KAAK;EACjE,MAAM,EAAE,SAAS,kBAAkB,eAAe;AAClD,MAAI;GACH,MAAM,QAAQ,SAAS,oBAAoB,KAAK;AAChD,OAAI,cAAc,MAAM,CAAE,QAAO;UAC1B;;AAET,MAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,QAAQ,KAAK;EAC1D,MAAM,EAAE,SAAS,kBAAkB,QAAQ;AAC3C,MAAI;GACH,MAAM,QAAQ,SAAS,YAAY,KAAK;AACxC,OAAI,cAAc,MAAM,CAAE,QAAO;UAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.mjs","names":["
|
|
1
|
+
{"version":3,"file":"date.mjs","names":["date"],"sources":["../../../src/formatters/date.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { LocalesValues } from '@intlayer/types';\nimport { Intl as CachedIntl } from '../utils/intl';\n\ntype DateTimePreset = 'short' | 'long' | 'dateOnly' | 'timeOnly' | 'full';\n\nconst presets: Record<DateTimePreset, Intl.DateTimeFormatOptions> = {\n short: {\n year: '2-digit',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n },\n long: {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n },\n full: {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n hour12: false,\n },\n dateOnly: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n },\n timeOnly: {\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n },\n};\n\n/**\n * Formats a date/time value into a localized string using Intl.DateTimeFormat.\n *\n * @example\n * date({ date: new Date(), options: \"short\" });\n * // \"08/02/25, 14:30\"\n *\n * @example\n * date({ date: \"2025-08-02T14:30:00Z\", locale: Locales.FRENCH, options: { month: \"long\", day: \"numeric\" } });\n * // \"2 août\"\n */\nexport const date = (\n date: Date | string | number,\n options?: Intl.DateTimeFormatOptions & { locale?: LocalesValues }\n): string => {\n const dateTime = new Date(date);\n\n const resolvedOptions =\n typeof options === 'string' ? (presets[options] ?? {}) : options;\n\n const formatter = new CachedIntl.DateTimeFormat(\n options?.locale ?? configuration?.internationalization?.defaultLocale,\n resolvedOptions\n );\n\n return formatter.format(dateTime);\n};\n"],"mappings":";;;;AAMA,MAAM,UAA8D;CAClE,OAAO;EACL,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT;CACD,MAAM;EACJ,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACT;CACD,MAAM;EACJ,MAAM;EACN,OAAO;EACP,KAAK;EACL,MAAM;EACN,QAAQ;EACR,QAAQ;EACT;CACD,UAAU;EACR,MAAM;EACN,OAAO;EACP,KAAK;EACN;CACD,UAAU;EACR,MAAM;EACN,QAAQ;EACR,QAAQ;EACT;CACF;;;;;;;;;;;;AAaD,MAAa,QACX,QACA,YACW;CACX,MAAM,WAAW,IAAI,KAAKA,OAAK;CAE/B,MAAM,kBACJ,OAAO,YAAY,WAAY,QAAQ,YAAY,EAAE,GAAI;AAO3D,QALkB,IAAI,WAAW,eAC/B,SAAS,UAAU,eAAe,sBAAsB,eACxD,gBACD,CAEgB,OAAO,SAAS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getStorageAttributes.mjs","names":["rest"
|
|
1
|
+
{"version":3,"file":"getStorageAttributes.mjs","names":["rest"],"sources":["../../src/getStorageAttributes.ts"],"sourcesContent":["import { DefaultValues } from '@intlayer/config/client';\nimport type {\n CookiesAttributes,\n IntlayerConfig,\n StorageAttributes,\n} from '@intlayer/types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype CookieEntry = {\n name: string;\n attributes: Omit<CookiesAttributes, 'type' | 'name'>;\n};\n\ntype WebStorageEntry = {\n name: string;\n};\n\ntype HeaderEntry = {\n name: string;\n};\n\nexport type ProcessedStorageAttributes = {\n cookies: CookieEntry[];\n localStorage: WebStorageEntry[];\n sessionStorage: WebStorageEntry[];\n headers: HeaderEntry[];\n};\n\ntype StorageEntry =\n | 'cookie'\n | 'localStorage'\n | 'sessionStorage'\n | 'header'\n | CookiesAttributes\n | StorageAttributes;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Creates a cookie entry with default values for missing attributes\n */\nconst createCookieEntry = (\n options?: Partial<CookiesAttributes>\n): CookieEntry => {\n const { name, path, expires, domain, secure, sameSite, httpOnly } =\n options ?? {};\n\n return {\n name: name ?? DefaultValues.Routing.COOKIE_NAME,\n attributes: {\n path,\n expires,\n domain,\n secure,\n sameSite,\n httpOnly,\n },\n };\n};\n\n/**\n * Creates a web storage entry (localStorage or sessionStorage) with default name\n */\nconst createWebStorageEntry = (\n options?: Partial<StorageAttributes>\n): WebStorageEntry => {\n const { name } = options ?? {};\n\n return {\n name: name ?? DefaultValues.Routing.LOCALE_STORAGE_NAME,\n };\n};\n\n/**\n * Creates a header entry with default name\n */\nconst createHeaderEntry = (\n options?: Partial<StorageAttributes>\n): HeaderEntry => {\n const { name } = options ?? {};\n\n return {\n name: name ?? DefaultValues.Routing.HEADER_NAME,\n };\n};\n\n/**\n * Determines if a storage entry is a cookie based on its properties\n */\nconst isCookieEntry = (entry: any): boolean => {\n return (\n entry.type === 'cookie' ||\n 'sameSite' in entry ||\n 'httpOnly' in entry ||\n 'secure' in entry\n );\n};\n\n/**\n * Determines the storage type from a string literal\n */\nconst isStorageType = (\n value: string\n): value is 'cookie' | 'localStorage' | 'sessionStorage' | 'header' => {\n return (\n value === 'cookie' ||\n value === 'localStorage' ||\n value === 'sessionStorage' ||\n value === 'header'\n );\n};\n\n// ============================================================================\n// Main Function\n// ============================================================================\n\n/**\n * Processes a single storage entry and returns the appropriate storage attributes\n */\nconst processStorageEntry = (\n entry: StorageEntry\n): Partial<ProcessedStorageAttributes> => {\n // Handle string literals\n if (typeof entry === 'string') {\n if (!isStorageType(entry)) {\n return { cookies: [], localStorage: [], sessionStorage: [], headers: [] };\n }\n\n if (entry === 'cookie') {\n return { cookies: [createCookieEntry()] };\n }\n\n if (entry === 'localStorage') {\n return { localStorage: [createWebStorageEntry()] };\n }\n\n if (entry === 'sessionStorage') {\n return { sessionStorage: [createWebStorageEntry()] };\n }\n\n if (entry === 'header') {\n return { headers: [createHeaderEntry()] };\n }\n }\n\n // Handle object entries\n if (typeof entry === 'object' && entry !== null) {\n const typedEntry = entry as CookiesAttributes | StorageAttributes;\n\n if (isCookieEntry(typedEntry)) {\n return { cookies: [createCookieEntry(typedEntry as CookiesAttributes)] };\n }\n\n // Handle localStorage\n if ('type' in typedEntry && typedEntry.type === 'localStorage') {\n const { name, ...rest } = typedEntry as StorageAttributes;\n return { localStorage: [createWebStorageEntry({ name, ...rest })] };\n }\n\n // Handle sessionStorage\n if ('type' in typedEntry && typedEntry.type === 'sessionStorage') {\n const { name, ...rest } = typedEntry as StorageAttributes;\n return { sessionStorage: [createWebStorageEntry({ name, ...rest })] };\n }\n\n // Handle header\n if ('type' in typedEntry && typedEntry.type === 'header') {\n const { name, ...rest } = typedEntry as StorageAttributes;\n return { headers: [createHeaderEntry({ name, ...rest })] };\n }\n\n // Default to localStorage for ambiguous objects\n const { name, ...rest } = typedEntry as Omit<StorageAttributes, 'type'>;\n return { localStorage: [createWebStorageEntry({ name, ...rest })] };\n }\n\n return { cookies: [], localStorage: [], sessionStorage: [], headers: [] };\n};\n\n/**\n * Merges multiple partial storage attributes into a single result\n */\nconst mergeStorageAttributes = (\n accumulated: ProcessedStorageAttributes,\n partial: Partial<ProcessedStorageAttributes>\n): ProcessedStorageAttributes => {\n return {\n cookies: [...accumulated.cookies, ...(partial.cookies ?? [])],\n localStorage: [\n ...accumulated.localStorage,\n ...(partial.localStorage ?? []),\n ],\n sessionStorage: [\n ...accumulated.sessionStorage,\n ...(partial.sessionStorage ?? []),\n ],\n headers: [...accumulated.headers, ...(partial.headers ?? [])],\n };\n};\n\n/**\n * Extracts and normalizes storage configuration into separate arrays for each storage type\n *\n * @param options - The storage configuration from IntlayerConfig\n * @returns An object containing arrays for cookies, localStorage, and sessionStorage\n */\nexport const getStorageAttributes = (\n options: IntlayerConfig['routing']['storage']\n): ProcessedStorageAttributes => {\n const emptyResult: ProcessedStorageAttributes = {\n cookies: [],\n localStorage: [],\n sessionStorage: [],\n headers: [],\n };\n\n // Storage is disabled\n if (options === false || options === undefined) {\n return emptyResult;\n }\n\n // Handle array of storage entries\n if (Array.isArray(options)) {\n return options.reduce<ProcessedStorageAttributes>((acc, entry) => {\n const partial = processStorageEntry(entry);\n return mergeStorageAttributes(acc, partial);\n }, emptyResult);\n }\n\n // Handle single storage entry\n const partial = processStorageEntry(options);\n\n return mergeStorageAttributes(emptyResult, partial);\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deepTransform.mjs","names":["node","props"
|
|
1
|
+
{"version":3,"file":"deepTransform.mjs","names":["node","props"],"sources":["../../../../src/interpreter/getContent/deepTransform.ts"],"sourcesContent":["import { type KeyPath, NodeType } from '@intlayer/types';\nimport type { NodeProps } from './plugins';\n\n/**\n * Recursively traverses a node (object/array/primitive).\n * Applies the *first* plugin that can transform a node, then stops descending further.\n * If no plugin transforms it, it recurses into its children.\n */\nexport const deepTransformNode = (node: any, props: NodeProps): any => {\n // Otherwise, if it's an object, check if any plugin can handle it:\n for (const plugin of props.plugins ?? []) {\n if (plugin.canHandle(node)) {\n // Return the transformed node => do NOT recurse further\n return plugin.transform(node, props, (node: any, props: any) =>\n deepTransformNode(node, props)\n );\n }\n }\n\n // If it's null/undefined or not an object, just return it directly:\n if (node === null || typeof node !== 'object') {\n return node;\n }\n\n // If it's an array, transform each element:\n if (Array.isArray(node)) {\n return node.map((child, index) => {\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Array, key: index } as KeyPath,\n ],\n };\n return deepTransformNode(child, childProps);\n });\n }\n\n // If no plugin transforms it, we keep traversing its properties.\n const result: Record<string, any> = {};\n for (const key in node) {\n const childProps = {\n ...props,\n children: node[key],\n keyPath: [...props.keyPath, { type: NodeType.Object, key } as KeyPath],\n };\n result[key] = deepTransformNode(node[key], childProps);\n }\n\n return result;\n};\n"],"mappings":";;;;;;;;AAQA,MAAa,qBAAqB,MAAW,UAA0B;AAErE,MAAK,MAAM,UAAU,MAAM,WAAW,EAAE,CACtC,KAAI,OAAO,UAAU,KAAK,CAExB,QAAO,OAAO,UAAU,MAAM,QAAQ,QAAW,YAC/C,kBAAkBA,QAAMC,QAAM,CAC/B;AAKL,KAAI,SAAS,QAAQ,OAAO,SAAS,SACnC,QAAO;AAIT,KAAI,MAAM,QAAQ,KAAK,CACrB,QAAO,KAAK,KAAK,OAAO,UAAU;AAShC,SAAO,kBAAkB,OARN;GACjB,GAAG;GACH,UAAU;GACV,SAAS,CACP,GAAG,MAAM,SACT;IAAE,MAAM,SAAS;IAAO,KAAK;IAAO,CACrC;GACF,CAC0C;GAC3C;CAIJ,MAAM,SAA8B,EAAE;AACtC,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,aAAa;GACjB,GAAG;GACH,UAAU,KAAK;GACf,SAAS,CAAC,GAAG,MAAM,SAAS;IAAE,MAAM,SAAS;IAAQ;IAAK,CAAY;GACvE;AACD,SAAO,OAAO,kBAAkB,KAAK,MAAM,WAAW;;AAGxD,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getContent.mjs","names":[
|
|
1
|
+
{"version":3,"file":"getContent.mjs","names":[],"sources":["../../../../src/interpreter/getContent/getContent.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type {\n ContentNode,\n DeclaredLocales,\n LocalesValues,\n} from '@intlayer/types';\nimport { deepTransformNode } from './deepTransform';\nimport {\n conditionPlugin,\n type DeepTransformContent,\n enumerationPlugin,\n filePlugin,\n type IInterpreterPluginState,\n insertionPlugin,\n type NodeProps,\n nestedPlugin,\n type Plugins,\n translationPlugin,\n} from './plugins';\n\n/**\n * Transforms a node in a single pass, applying each plugin as needed.\n *\n * @param node The node to transform.\n * @param locale The locale to use if your transformers need it (e.g. for translations).\n */\nexport const getContent = <\n T extends ContentNode,\n L extends LocalesValues = DeclaredLocales,\n>(\n node: T,\n nodeProps: NodeProps,\n locale?: L\n) => {\n const defaultLocale = configuration?.internationalization?.defaultLocale;\n\n const plugins: Plugins[] = [\n insertionPlugin,\n translationPlugin(locale ?? defaultLocale, defaultLocale),\n enumerationPlugin,\n conditionPlugin,\n nestedPlugin(locale ?? defaultLocale),\n filePlugin,\n ...(nodeProps.plugins ?? []),\n ];\n\n return deepTransformNode(node, {\n ...nodeProps,\n plugins,\n }) as DeepTransformContent<T, IInterpreterPluginState, L>;\n};\n"],"mappings":";;;;;;;;;;;AA0BA,MAAa,cAIX,MACA,WACA,WACG;CACH,MAAM,gBAAgB,eAAe,sBAAsB;CAE3D,MAAM,UAAqB;EACzB;EACA,kBAAkB,UAAU,eAAe,cAAc;EACzD;EACA;EACA,aAAa,UAAU,cAAc;EACrC;EACA,GAAI,UAAU,WAAW,EAAE;EAC5B;AAED,QAAO,kBAAkB,MAAM;EAC7B,GAAG;EACH;EACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.mjs","names":["enumerationPlugin: Plugins","conditionPlugin: Plugins","genderPlugin: Plugins","insertionPlugin: Plugins","newKeyPath: KeyPath[]","insertionStringPlugin: Plugins","node","deepTransformNode","children","filePlugin: Plugins"],"sources":["../../../../src/interpreter/getContent/plugins.ts"],"sourcesContent":["import {\n type DeclaredLocales,\n type DictionaryKeys,\n type KeyPath,\n type Locale,\n type LocalesValues,\n NodeType,\n} from '@intlayer/types';\nimport type {\n ConditionContent,\n EnumerationContent,\n FileContent,\n Gender,\n GenderContent,\n InsertionContent,\n NestedContent,\n TranslationContent,\n} from '../../transpiler';\nimport { getCondition } from '../getCondition';\nimport { getEnumeration } from '../getEnumeration';\nimport { getGender } from '../getGender';\nimport { getInsertion } from '../getInsertion';\nimport { type GetNestingResult, getNesting } from '../getNesting';\nimport { getTranslation } from '../getTranslation';\n\n/** ---------------------------------------------\n * PLUGIN DEFINITION\n * --------------------------------------------- */\n\n/**\n * A plugin/transformer that can optionally transform a node during a single DFS pass.\n * - `canHandle` decides if the node is transformable by this plugin.\n * - `transform` returns the transformed node (and does not recurse further).\n *\n * > `transformFn` is a function that can be used to deeply transform inside the plugin.\n */\nexport type Plugins = {\n id: string;\n canHandle: (node: any) => boolean;\n transform: (\n node: any,\n props: NodeProps,\n transformFn: (node: any, props: NodeProps) => any\n ) => any;\n};\n\n/** ---------------------------------------------\n * TRANSLATION PLUGIN\n * --------------------------------------------- */\n\nexport type TranslationCond<T, S, L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeType.Translation]: infer U;\n}\n ? U extends Record<PropertyKey, unknown>\n ? L extends keyof U\n ? DeepTransformContent<U[L], S>\n : DeepTransformContent<U[keyof U], S>\n : never\n : never;\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const translationPlugin = (\n locale: LocalesValues,\n fallback?: LocalesValues,\n onContentNotFound?: (\n locale: LocalesValues,\n fallback: LocalesValues,\n keyPath: KeyPath[]\n ) => void\n): Plugins => ({\n id: 'translation-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Translation,\n transform: (node: TranslationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Translation]);\n\n for (const key in result) {\n const childProps = {\n ...props,\n children: result[key as keyof typeof result],\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Translation, key } as KeyPath,\n ],\n };\n result[key as keyof typeof result] = deepTransformNode(\n result[key as keyof typeof result],\n childProps\n );\n }\n\n return getTranslation(result, locale, fallback);\n },\n});\n\n/** ---------------------------------------------\n * ENUMERATION PLUGIN\n * --------------------------------------------- */\n\nexport type EnumerationCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Enumeration]: object;\n}\n ? (\n quantity: number\n ) => DeepTransformContent<\n T[NodeType.Enumeration][keyof T[NodeType.Enumeration]],\n S\n >\n : never;\n\n/** Enumeration plugin. Replaces node with a function that takes quantity => string. */\nexport const enumerationPlugin: Plugins = {\n id: 'enumeration-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Enumeration,\n transform: (node: EnumerationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Enumeration]);\n\n for (const key in result) {\n const child = result[key as unknown as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Enumeration, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (quantity: number) => getEnumeration(result, quantity);\n },\n};\n\n/** ---------------------------------------------\n * CONDITION PLUGIN\n * --------------------------------------------- */\n\nexport type ConditionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Condition]: object;\n}\n ? (\n value: boolean\n ) => DeepTransformContent<\n T[NodeType.Condition][keyof T[NodeType.Condition]],\n S\n >\n : never;\n\n/** Condition plugin. Replaces node with a function that takes boolean => string. */\nexport const conditionPlugin: Plugins = {\n id: 'condition-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Condition,\n transform: (node: ConditionContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Condition]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Condition, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: boolean) => getCondition(result, value);\n },\n};\n\n/** ---------------------------------------------\n * GENDER PLUGIN\n * --------------------------------------------- */\n\nexport type GenderCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Gender]: object;\n}\n ? (\n value: Gender\n ) => DeepTransformContent<T[NodeType.Gender][keyof T[NodeType.Gender]], S>\n : never;\n\n/** Gender plugin. Replaces node with a function that takes gender => string. */\nexport const genderPlugin: Plugins = {\n id: 'gender-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Gender,\n transform: (node: GenderContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Gender]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [...props.keyPath, { type: NodeType.Gender, key } as KeyPath],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: Gender) => getGender(result, value);\n },\n};\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\nexport type InsertionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Insertion]: infer I;\n fields?: infer U;\n}\n ? U extends readonly string[]\n ? (data: Record<U[number], string | number>) => DeepTransformContent<I, S>\n : (data: Record<string, string | number>) => DeepTransformContent<I, S>\n : never;\n\nexport const insertionPlugin: Plugins = {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Insertion,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeType.Insertion,\n },\n ];\n\n const children = node[NodeType.Insertion];\n\n /** Insertion string plugin. Replaces string node with a component that render the insertion. */\n const insertionStringPlugin: Plugins = {\n id: 'insertion-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, subProps, deepTransformNode) => {\n const transformedResult = deepTransformNode(node, {\n ...subProps,\n children: node,\n plugins: [\n ...(props.plugins ?? ([] as Plugins[])).filter(\n (plugin) => plugin.id !== 'intlayer-node-plugin'\n ),\n ],\n });\n\n return (\n values: {\n [K in InsertionContent['fields'][number]]: string | number;\n }\n ) => {\n const children = getInsertion(transformedResult, values);\n\n return deepTransformNode(children, {\n ...subProps,\n plugins: props.plugins,\n children,\n });\n };\n },\n };\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [insertionStringPlugin, ...(props.plugins ?? [])],\n });\n },\n};\n\n/** ---------------------------------------------\n * NESTED PLUGIN\n * --------------------------------------------- */\n\nexport type NestedCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Nested]: infer U;\n}\n ? U extends {\n dictionaryKey: infer K extends DictionaryKeys;\n path?: infer P;\n }\n ? GetNestingResult<K, P, S>\n : never\n : never;\n\n/** Nested plugin. Replaces node with the result of `getNesting`. */\nexport const nestedPlugin = (locale?: LocalesValues): Plugins => ({\n id: 'nested-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Nested,\n transform: (node: NestedContent, props) =>\n getNesting(node.nested.dictionaryKey, node.nested.path, {\n ...props,\n locale: (locale ?? props.locale) as Locale,\n }),\n});\n\n// /** ---------------------------------------------\n// * FILE PLUGIN\n// * --------------------------------------------- */\n\nexport type FileCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeType.File]: string;\n content?: string;\n}\n ? string\n : never;\n\n/** File plugin. Replaces node with the result of `getNesting`. */\nexport const filePlugin: Plugins = {\n id: 'file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.File,\n transform: (node: FileContent, props, deepTransform) =>\n deepTransform(node.content, {\n ...props,\n children: node.content,\n }),\n};\n\n/**\n * PLUGIN RESULT\n */\n\n/**\n * Interface that defines the properties of a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface NodeProps {\n dictionaryKey: string;\n keyPath: KeyPath[];\n plugins?: Plugins[];\n locale?: Locale;\n dictionaryPath?: string;\n children?: any;\n}\n\n/**\n * Interface that defines the plugins that can be used to transform a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface IInterpreterPlugin<T, S, L extends LocalesValues> {\n translation: TranslationCond<T, S, L>;\n insertion: InsertionCond<T, S, L>;\n enumeration: EnumerationCond<T, S, L>;\n condition: ConditionCond<T, S, L>;\n nested: NestedCond<T, S, L>;\n // file: FileCond<T>;\n}\n\n/**\n * Allow to avoid overwriting import from `intlayer` package when `IInterpreterPlugin<T>` interface is augmented in another package, such as `react-intlayer`.\n */\nexport type IInterpreterPluginState = {\n translation: true;\n enumeration: true;\n condition: true;\n insertion: true;\n nested: true;\n // file: true;\n};\n\n/**\n * Utility type to check if a plugin can be applied to a node.\n */\ntype CheckApplyPlugin<\n T,\n K extends keyof IInterpreterPlugin<T, S, L>,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = K extends keyof S // Test if the key is a key of S.\n ? // Test if the key of S is true. Then the plugin can be applied.\n S[K] extends true\n ? // Test if the key of S exist\n IInterpreterPlugin<T, S, L>[K] extends never\n ? never\n : // Test if the plugin condition is true (if it's not, the plugin is skipped for this node)\n IInterpreterPlugin<T, S, L>[K]\n : never\n : never;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\ntype Traverse<\n T,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = T extends ReadonlyArray<infer U> // Turn any read-only array into a plain mutable array\n ? Array<DeepTransformContent<U, S, L>>\n : T extends object\n ? { [K in keyof T]: DeepTransformContent<T[K], S, L> }\n : T;\n\nexport type IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\nexport type DeepTransformContent<\n T,\n S = IInterpreterPluginState,\n L extends LocalesValues = DeclaredLocales,\n> = IsAny<T> extends true\n ? T\n : CheckApplyPlugin<T, keyof IInterpreterPlugin<T, S, L>, S> extends never // Check if there is a plugin for T:\n ? // No plugin was found, so try to transform T recursively:\n Traverse<T, S, L>\n : // A plugin was found – use the plugin’s transformation.\n IInterpreterPlugin<T, S, L>[keyof IInterpreterPlugin<T, S, L>];\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugins.mjs","names":["node","deepTransformNode","children"],"sources":["../../../../src/interpreter/getContent/plugins.ts"],"sourcesContent":["import {\n type DeclaredLocales,\n type DictionaryKeys,\n type KeyPath,\n type Locale,\n type LocalesValues,\n NodeType,\n} from '@intlayer/types';\nimport type {\n ConditionContent,\n EnumerationContent,\n FileContent,\n Gender,\n GenderContent,\n InsertionContent,\n NestedContent,\n TranslationContent,\n} from '../../transpiler';\nimport { getCondition } from '../getCondition';\nimport { getEnumeration } from '../getEnumeration';\nimport { getGender } from '../getGender';\nimport { getInsertion } from '../getInsertion';\nimport { type GetNestingResult, getNesting } from '../getNesting';\nimport { getTranslation } from '../getTranslation';\n\n/** ---------------------------------------------\n * PLUGIN DEFINITION\n * --------------------------------------------- */\n\n/**\n * A plugin/transformer that can optionally transform a node during a single DFS pass.\n * - `canHandle` decides if the node is transformable by this plugin.\n * - `transform` returns the transformed node (and does not recurse further).\n *\n * > `transformFn` is a function that can be used to deeply transform inside the plugin.\n */\nexport type Plugins = {\n id: string;\n canHandle: (node: any) => boolean;\n transform: (\n node: any,\n props: NodeProps,\n transformFn: (node: any, props: NodeProps) => any\n ) => any;\n};\n\n/** ---------------------------------------------\n * TRANSLATION PLUGIN\n * --------------------------------------------- */\n\nexport type TranslationCond<T, S, L extends LocalesValues> = T extends {\n nodeType: NodeType | string;\n [NodeType.Translation]: infer U;\n}\n ? U extends Record<PropertyKey, unknown>\n ? L extends keyof U\n ? DeepTransformContent<U[L], S>\n : DeepTransformContent<U[keyof U], S>\n : never\n : never;\n\n/** Translation plugin. Replaces node with a locale string if nodeType = Translation. */\nexport const translationPlugin = (\n locale: LocalesValues,\n fallback?: LocalesValues,\n onContentNotFound?: (\n locale: LocalesValues,\n fallback: LocalesValues,\n keyPath: KeyPath[]\n ) => void\n): Plugins => ({\n id: 'translation-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Translation,\n transform: (node: TranslationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Translation]);\n\n for (const key in result) {\n const childProps = {\n ...props,\n children: result[key as keyof typeof result],\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Translation, key } as KeyPath,\n ],\n };\n result[key as keyof typeof result] = deepTransformNode(\n result[key as keyof typeof result],\n childProps\n );\n }\n\n return getTranslation(result, locale, fallback);\n },\n});\n\n/** ---------------------------------------------\n * ENUMERATION PLUGIN\n * --------------------------------------------- */\n\nexport type EnumerationCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Enumeration]: object;\n}\n ? (\n quantity: number\n ) => DeepTransformContent<\n T[NodeType.Enumeration][keyof T[NodeType.Enumeration]],\n S\n >\n : never;\n\n/** Enumeration plugin. Replaces node with a function that takes quantity => string. */\nexport const enumerationPlugin: Plugins = {\n id: 'enumeration-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Enumeration,\n transform: (node: EnumerationContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Enumeration]);\n\n for (const key in result) {\n const child = result[key as unknown as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Enumeration, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (quantity: number) => getEnumeration(result, quantity);\n },\n};\n\n/** ---------------------------------------------\n * CONDITION PLUGIN\n * --------------------------------------------- */\n\nexport type ConditionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Condition]: object;\n}\n ? (\n value: boolean\n ) => DeepTransformContent<\n T[NodeType.Condition][keyof T[NodeType.Condition]],\n S\n >\n : never;\n\n/** Condition plugin. Replaces node with a function that takes boolean => string. */\nexport const conditionPlugin: Plugins = {\n id: 'condition-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Condition,\n transform: (node: ConditionContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Condition]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [\n ...props.keyPath,\n { type: NodeType.Condition, key } as KeyPath,\n ],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: boolean) => getCondition(result, value);\n },\n};\n\n/** ---------------------------------------------\n * GENDER PLUGIN\n * --------------------------------------------- */\n\nexport type GenderCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Gender]: object;\n}\n ? (\n value: Gender\n ) => DeepTransformContent<T[NodeType.Gender][keyof T[NodeType.Gender]], S>\n : never;\n\n/** Gender plugin. Replaces node with a function that takes gender => string. */\nexport const genderPlugin: Plugins = {\n id: 'gender-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Gender,\n transform: (node: GenderContent, props, deepTransformNode) => {\n const result = structuredClone(node[NodeType.Gender]);\n\n for (const key in result) {\n const child = result[key as keyof typeof result];\n const childProps = {\n ...props,\n children: child,\n keyPath: [...props.keyPath, { type: NodeType.Gender, key } as KeyPath],\n };\n result[key as unknown as keyof typeof result] = deepTransformNode(\n child,\n childProps\n );\n }\n\n return (value: Gender) => getGender(result, value);\n },\n};\n\n/** ---------------------------------------------\n * INSERTION PLUGIN\n * --------------------------------------------- */\n\nexport type InsertionCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Insertion]: infer I;\n fields?: infer U;\n}\n ? U extends readonly string[]\n ? (data: Record<U[number], string | number>) => DeepTransformContent<I, S>\n : (data: Record<string, string | number>) => DeepTransformContent<I, S>\n : never;\n\nexport const insertionPlugin: Plugins = {\n id: 'insertion-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Insertion,\n transform: (node: InsertionContent, props, deepTransformNode) => {\n const newKeyPath: KeyPath[] = [\n ...props.keyPath,\n {\n type: NodeType.Insertion,\n },\n ];\n\n const children = node[NodeType.Insertion];\n\n /** Insertion string plugin. Replaces string node with a component that render the insertion. */\n const insertionStringPlugin: Plugins = {\n id: 'insertion-string-plugin',\n canHandle: (node) => typeof node === 'string',\n transform: (node: string, subProps, deepTransformNode) => {\n const transformedResult = deepTransformNode(node, {\n ...subProps,\n children: node,\n plugins: [\n ...(props.plugins ?? ([] as Plugins[])).filter(\n (plugin) => plugin.id !== 'intlayer-node-plugin'\n ),\n ],\n });\n\n return (\n values: {\n [K in InsertionContent['fields'][number]]: string | number;\n }\n ) => {\n const children = getInsertion(transformedResult, values);\n\n return deepTransformNode(children, {\n ...subProps,\n plugins: props.plugins,\n children,\n });\n };\n },\n };\n\n return deepTransformNode(children, {\n ...props,\n children,\n keyPath: newKeyPath,\n plugins: [insertionStringPlugin, ...(props.plugins ?? [])],\n });\n },\n};\n\n/** ---------------------------------------------\n * NESTED PLUGIN\n * --------------------------------------------- */\n\nexport type NestedCond<T, S, L> = T extends {\n nodeType: NodeType | string;\n [NodeType.Nested]: infer U;\n}\n ? U extends {\n dictionaryKey: infer K extends DictionaryKeys;\n path?: infer P;\n }\n ? GetNestingResult<K, P, S>\n : never\n : never;\n\n/** Nested plugin. Replaces node with the result of `getNesting`. */\nexport const nestedPlugin = (locale?: LocalesValues): Plugins => ({\n id: 'nested-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.Nested,\n transform: (node: NestedContent, props) =>\n getNesting(node.nested.dictionaryKey, node.nested.path, {\n ...props,\n locale: (locale ?? props.locale) as Locale,\n }),\n});\n\n// /** ---------------------------------------------\n// * FILE PLUGIN\n// * --------------------------------------------- */\n\nexport type FileCond<T> = T extends {\n nodeType: NodeType | string;\n [NodeType.File]: string;\n content?: string;\n}\n ? string\n : never;\n\n/** File plugin. Replaces node with the result of `getNesting`. */\nexport const filePlugin: Plugins = {\n id: 'file-plugin',\n canHandle: (node) =>\n typeof node === 'object' && node?.nodeType === NodeType.File,\n transform: (node: FileContent, props, deepTransform) =>\n deepTransform(node.content, {\n ...props,\n children: node.content,\n }),\n};\n\n/**\n * PLUGIN RESULT\n */\n\n/**\n * Interface that defines the properties of a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface NodeProps {\n dictionaryKey: string;\n keyPath: KeyPath[];\n plugins?: Plugins[];\n locale?: Locale;\n dictionaryPath?: string;\n children?: any;\n}\n\n/**\n * Interface that defines the plugins that can be used to transform a node.\n * This interface can be augmented in other packages, such as `react-intlayer`.\n */\nexport interface IInterpreterPlugin<T, S, L extends LocalesValues> {\n translation: TranslationCond<T, S, L>;\n insertion: InsertionCond<T, S, L>;\n enumeration: EnumerationCond<T, S, L>;\n condition: ConditionCond<T, S, L>;\n nested: NestedCond<T, S, L>;\n // file: FileCond<T>;\n}\n\n/**\n * Allow to avoid overwriting import from `intlayer` package when `IInterpreterPlugin<T>` interface is augmented in another package, such as `react-intlayer`.\n */\nexport type IInterpreterPluginState = {\n translation: true;\n enumeration: true;\n condition: true;\n insertion: true;\n nested: true;\n // file: true;\n};\n\n/**\n * Utility type to check if a plugin can be applied to a node.\n */\ntype CheckApplyPlugin<\n T,\n K extends keyof IInterpreterPlugin<T, S, L>,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = K extends keyof S // Test if the key is a key of S.\n ? // Test if the key of S is true. Then the plugin can be applied.\n S[K] extends true\n ? // Test if the key of S exist\n IInterpreterPlugin<T, S, L>[K] extends never\n ? never\n : // Test if the plugin condition is true (if it's not, the plugin is skipped for this node)\n IInterpreterPlugin<T, S, L>[K]\n : never\n : never;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\ntype Traverse<\n T,\n S,\n L extends LocalesValues = DeclaredLocales,\n> = T extends ReadonlyArray<infer U> // Turn any read-only array into a plain mutable array\n ? Array<DeepTransformContent<U, S, L>>\n : T extends object\n ? { [K in keyof T]: DeepTransformContent<T[K], S, L> }\n : T;\n\nexport type IsAny<T> = 0 extends 1 & T ? true : false;\n\n/**\n * Traverse recursively through an object or array, applying each plugin as needed.\n */\nexport type DeepTransformContent<\n T,\n S = IInterpreterPluginState,\n L extends LocalesValues = DeclaredLocales,\n> = IsAny<T> extends true\n ? T\n : CheckApplyPlugin<T, keyof IInterpreterPlugin<T, S, L>, S> extends never // Check if there is a plugin for T:\n ? // No plugin was found, so try to transform T recursively:\n Traverse<T, S, L>\n : // A plugin was found – use the plugin’s transformation.\n IInterpreterPlugin<T, S, L>[keyof IInterpreterPlugin<T, S, L>];\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDictionary.mjs","names":[
|
|
1
|
+
{"version":3,"file":"getDictionary.mjs","names":[],"sources":["../../../src/interpreter/getDictionary.ts"],"sourcesContent":["import type {\n DeclaredLocales,\n Dictionary,\n LocalesValues,\n} from '@intlayer/types';\nimport type {\n DeepTransformContent,\n IInterpreterPluginState,\n NodeProps,\n Plugins,\n} from './getContent';\nimport { getContent } from './getContent/getContent';\n\n/**\n * Transforms a dictionary in a single pass, applying each plugin as needed.\n *\n * @param dictionary The dictionary to transform.\n * @param locale The locale to use if your transformers need it (e.g. for translations).\n * @param additionalPlugins An array of NodeTransformer that define how to transform recognized nodes.\n * If omitted, we’ll use a default set of plugins.\n */\nexport const getDictionary = <\n T extends Dictionary,\n L extends LocalesValues = DeclaredLocales,\n>(\n dictionary: T,\n locale?: L,\n plugins?: Plugins[]\n): DeepTransformContent<T['content'], IInterpreterPluginState, L> => {\n const props: NodeProps = {\n dictionaryKey: dictionary.key,\n dictionaryPath: dictionary.filePath,\n keyPath: [],\n plugins,\n };\n\n return getContent(dictionary.content, props, locale);\n};\n"],"mappings":";;;;;;;;;;;AAqBA,MAAa,iBAIX,YACA,QACA,YACmE;CACnE,MAAM,QAAmB;EACvB,eAAe,WAAW;EAC1B,gBAAgB,WAAW;EAC3B,SAAS,EAAE;EACX;EACD;AAED,QAAO,WAAW,WAAW,SAAS,OAAO,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNesting.mjs","names":[
|
|
1
|
+
{"version":3,"file":"getNesting.mjs","names":[],"sources":["../../../src/interpreter/getNesting.ts"],"sourcesContent":["import type {\n DictionaryKeys,\n DictionaryRegistryContent,\n GetSubPath,\n} from '@intlayer/types';\nimport type { ValidDotPathsFor } from '../transpiler';\nimport type {\n DeepTransformContent,\n IInterpreterPluginState,\n NodeProps,\n} from './getContent';\nimport { getIntlayer } from './getIntlayer';\n\nexport type GetNestingResult<\n K extends DictionaryKeys,\n P = undefined,\n S = IInterpreterPluginState,\n> = GetSubPath<DeepTransformContent<DictionaryRegistryContent<K>, S>, P>;\n\n/**\n * Allow to extract the content of another dictionary.\n *\n * Usage:\n * ```ts\n * const content = getNesting(\"dictionaryKey\", \"path.to.content\");\n * // 'Example content'\n * ```\n */\nexport const getNesting = <K extends DictionaryKeys, P>(\n dictionaryKey: K,\n path?: P extends ValidDotPathsFor<K> ? P : never,\n props?: NodeProps\n): GetNestingResult<K, P> => {\n const dictionary = getIntlayer(dictionaryKey, props?.locale, props?.plugins);\n\n if (typeof path === 'string') {\n const pathArray = (path as string).split('.');\n let current: any = dictionary;\n\n for (const key of pathArray) {\n // Safely traverse down the object using the path\n current = current?.[key];\n // If we cannot find the path, return the whole dictionary as a fallback\n if (current === undefined) {\n return dictionary as any;\n }\n }\n\n return current;\n }\n\n // Default or error handling if path is not a string or otherwise undefined\n return dictionary as any;\n};\n"],"mappings":";;;;;;;;;;;;AA4BA,MAAa,cACX,eACA,MACA,UAC2B;CAC3B,MAAM,aAAa,YAAY,eAAe,OAAO,QAAQ,OAAO,QAAQ;AAE5E,KAAI,OAAO,SAAS,UAAU;EAC5B,MAAM,YAAa,KAAgB,MAAM,IAAI;EAC7C,IAAI,UAAe;AAEnB,OAAK,MAAM,OAAO,WAAW;AAE3B,aAAU,UAAU;AAEpB,OAAI,YAAY,OACd,QAAO;;AAIX,SAAO;;AAIT,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getTranslation.mjs","names":[
|
|
1
|
+
{"version":3,"file":"getTranslation.mjs","names":[],"sources":["../../../src/interpreter/getTranslation.ts"],"sourcesContent":["import type { LocalesValues, StrictModeLocaleMap } from '@intlayer/types';\n\n/**\n * Check if a value is a plain object that can be safely processed.\n * Returns false for Promises, React elements, class instances, etc.\n */\nconst isPlainObject = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n // Don't process Promises (e.g., Next.js 15+ params)\n if (value instanceof Promise || typeof (value as any).then === 'function') {\n return false;\n }\n\n // Don't process React elements\n if ((value as any).$$typeof !== undefined) {\n return false;\n }\n\n // Only process plain objects and arrays\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null || Array.isArray(value);\n};\n\n/**\n * Recursively merges two objects.\n * Resembles the behavior of `defu` but respects `isPlainObject` to avoid merging React elements.\n * Arrays are replaced, not merged.\n */\nconst deepMergeObjects = (target: any, source: any): any => {\n if (target === undefined) return source;\n if (source === undefined) return target;\n\n if (Array.isArray(target)) return target;\n\n if (isPlainObject(target) && isPlainObject(source)) {\n const result = { ...target };\n for (const key of Object.keys(source)) {\n if (key === '__proto__' || key === 'constructor') continue;\n\n if (Object.hasOwn(target, key)) {\n result[key] = deepMergeObjects(target[key], source[key]);\n } else {\n result[key] = source[key];\n }\n }\n return result;\n }\n\n return target;\n};\n\n/**\n * Recursively removes undefined values from an object.\n * Handles circular references by tracking visited objects.\n */\nconst removeUndefinedValues = <T>(\n object: T,\n visited = new WeakSet<object>()\n): T => {\n if (typeof object !== 'object' || object === null) {\n return object;\n }\n\n // Handle circular references - return original to avoid infinite recursion\n if (visited.has(object)) {\n return object;\n }\n visited.add(object);\n\n // Don't process non-plain objects (Promises, React elements, etc.)\n if (!isPlainObject(object)) {\n return object;\n }\n\n if (Array.isArray(object)) {\n return object.map((item) => removeUndefinedValues(item, visited)) as T;\n }\n\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(object)) {\n if (value !== undefined) {\n result[key] = removeUndefinedValues(value, visited);\n }\n }\n return result as T;\n};\n\n/**\n *\n * Allow to pick a content based on a locale.\n * If not locale found, it will return the content related to the default locale.\n *\n * Return either the content editor, or the content itself depending on the configuration.\n *\n * Usage:\n *\n * ```ts\n * const content = getTranslation<string>({\n * en: 'Hello',\n * fr: 'Bonjour',\n * }, 'fr');\n * // 'Bonjour'\n * ```\n *\n * Using TypeScript:\n * - this function will require each locale to be defined if defined in the project configuration.\n * - If a locale is missing, it will make each existing locale optional and raise an error if the locale is not found.\n */\nexport const getTranslation = <Content = string>(\n languageContent: StrictModeLocaleMap<Content>,\n locale: LocalesValues,\n fallback?: LocalesValues\n): Content => {\n const results: Content[] = [];\n\n const getContent = (loc: string) =>\n languageContent[loc as keyof typeof languageContent];\n\n // 1. Get Target Content\n const content = getContent(locale);\n if (typeof content === 'string') {\n return content;\n } else if (content !== undefined) {\n results.push(content);\n }\n\n // 2. Get Target Generic Content (e.g. 'en' from 'en-US')\n if (locale.includes('-')) {\n const genericLocale = locale.split('-')[0];\n if (genericLocale in languageContent) {\n const genericContent = getContent(genericLocale);\n\n if (typeof genericContent === 'string') {\n // If we haven't found specific content yet, return generic string\n if (results.length === 0) return genericContent;\n } else if (genericContent !== undefined) {\n results.push(genericContent);\n }\n }\n }\n\n // 3. Get Fallback Content\n if (fallback !== undefined && fallback !== locale) {\n // 3a. Fallback Specific\n if (fallback in languageContent) {\n const fallbackContent = getContent(fallback);\n\n if (typeof fallbackContent === 'string') {\n if (results.length === 0) return fallbackContent;\n } else if (fallbackContent !== undefined) {\n results.push(fallbackContent);\n }\n }\n\n // 3b. Fallback Generic (The missing piece: e.g. 'en' from 'en-GB' fallback)\n if (fallback.includes('-')) {\n const genericFallback = fallback.split('-')[0];\n const genericLocale = locale.split('-')[0];\n\n // Only add if it's different from the target generic (to avoid duplication)\n // and exists in the dictionary\n if (\n genericFallback !== genericLocale &&\n genericFallback in languageContent\n ) {\n const genericFallbackContent = getContent(genericFallback);\n\n if (typeof genericFallbackContent === 'string') {\n if (results.length === 0) return genericFallbackContent;\n } else if (genericFallbackContent !== undefined) {\n results.push(genericFallbackContent);\n }\n }\n }\n }\n\n if (results.length === 0) {\n return undefined as Content;\n }\n\n // Clean undefined values so they don't overwrite fallbacks\n // Order: [Target, Generic, Fallback, FallbackGeneric]\n // defu first argument takes precedence, so Target wins\n const cleanResults = results.map((item) => removeUndefinedValues(item));\n\n // If only one result, return it directly (no merging needed)\n if (cleanResults.length === 1) {\n return cleanResults[0];\n }\n\n // If the first result is an array, return it directly (arrays replace, don't merge)\n // defu would incorrectly convert arrays to objects with numeric keys\n if (Array.isArray(cleanResults[0])) {\n return cleanResults[0];\n }\n\n // Merge objects with custom merge - first argument takes precedence\n // Cast to object[] since by this point we've already returned early for strings, arrays, and single results\n return (cleanResults as object[]).reduce((acc, curr) =>\n deepMergeObjects(acc, curr)\n ) as Content;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBrowserLocale.mjs","names":[
|
|
1
|
+
{"version":3,"file":"getBrowserLocale.mjs","names":[],"sources":["../../../src/localization/getBrowserLocale.tsx"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport { type Locale, Locales } from '@intlayer/types';\nimport {\n getLocaleFromStorage,\n type LocaleStorageOptions,\n} from '../utils/localeStorage';\nimport { localeDetector } from './localeDetector';\n\nexport enum LanguageDetector {\n Querystring = 'querystring',\n Storage = 'storage',\n Navigator = 'navigator',\n HtmlTag = 'htmlTag',\n}\n\nexport const localeStorageOptions: LocaleStorageOptions = {\n getCookie: (name: string) =>\n document.cookie\n .split(';')\n .find((c) => c.trim().startsWith(`${name}=`))\n ?.split('=')[1],\n getLocaleStorage: (name: string) => localStorage.getItem(name),\n getSessionStorage: (name: string) => sessionStorage.getItem(name),\n isCookieEnabled: true,\n setCookieStore: (name, value, attributes) =>\n cookieStore.set({\n name,\n value,\n path: attributes.path,\n domain: attributes.domain,\n expires: attributes.expires,\n sameSite: attributes.sameSite,\n }),\n setCookieString: (cookie) => {\n // biome-ignore lint/suspicious/noDocumentCookie: set cookie fallback\n document.cookie = cookie;\n },\n setSessionStorage: (name, value) => sessionStorage.setItem(name, value),\n setLocaleStorage: (name, value) => localStorage.setItem(name, value),\n};\n\n// Default settings for the language detector\ntype LanguageDetectorOptions = {\n order?: LanguageDetector[];\n lookupQuerystring?: string;\n htmlTag?: HTMLElement | null;\n};\n\nconst getDefaultsOptions = (): LanguageDetectorOptions => {\n return {\n order: [\n LanguageDetector.Querystring,\n LanguageDetector.Storage,\n LanguageDetector.Navigator,\n LanguageDetector.HtmlTag,\n ],\n lookupQuerystring: 'locale',\n htmlTag: typeof document !== 'undefined' ? document.documentElement : null,\n };\n};\n\nconst detectLanguage = (\n order: string[],\n options: LanguageDetectorOptions\n): Record<LanguageDetector, Locale | undefined> => {\n const detected: Record<LanguageDetector, Locale | undefined> = {} as Record<\n LanguageDetector,\n Locale | undefined\n >;\n\n const queryStringDetector = () => {\n if (typeof window === 'undefined') return;\n const search = window.location.search || '';\n const params = new URLSearchParams(search);\n const value = params.get(options.lookupQuerystring ?? '');\n if (value) {\n detected[LanguageDetector.Querystring] = value as Locale;\n }\n };\n\n const storageDetector = () => {\n if (typeof window === 'undefined') return;\n\n const locale = getLocaleFromStorage({\n getCookie: (name: string) => {\n try {\n const cookies = document.cookie.split(';');\n const cookieName = `${name}=`;\n const cookie = cookies.find((c) => c.trim().startsWith(cookieName));\n if (cookie) {\n return cookie.split('=')[1].trim();\n }\n } catch {}\n return undefined;\n },\n getSessionStorage: (name: string) => {\n try {\n return window.sessionStorage.getItem(name) ?? undefined;\n } catch {}\n return undefined;\n },\n getLocaleStorage: (name: string) => {\n try {\n return window.localStorage.getItem(name) ?? undefined;\n } catch {}\n return undefined;\n },\n });\n\n if (locale) {\n detected[LanguageDetector.Storage] = locale;\n }\n };\n\n const navigatorDetector = () => {\n if (typeof navigator === 'undefined') return;\n\n const { internationalization } = configuration;\n const languages = navigator.languages ?? [navigator.language];\n\n // Use localeDetector to find the best matching locale\n const locale = localeDetector(\n { 'accept-language': languages.join(',') },\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n if (locale) {\n detected[LanguageDetector.Navigator] = locale;\n }\n };\n\n const htmlTagDetector = () => {\n const htmlTag = options.htmlTag;\n if (htmlTag && typeof htmlTag.getAttribute === 'function') {\n const lang = htmlTag.getAttribute('lang');\n if (lang) {\n const { internationalization } = configuration;\n\n // Validate and resolve the locale\n const locale = localeDetector(\n { 'accept-language': lang },\n internationalization.locales,\n internationalization.defaultLocale\n );\n\n detected[LanguageDetector.HtmlTag] = locale;\n }\n }\n };\n\n // Map detector names to their corresponding functions\n const detectors: Record<string, () => void> = {\n [LanguageDetector.Querystring]: queryStringDetector,\n [LanguageDetector.Storage]: storageDetector,\n [LanguageDetector.Navigator]: navigatorDetector,\n [LanguageDetector.HtmlTag]: htmlTagDetector,\n };\n\n // Use the provided order to run each detector\n order.forEach((detectorName) => {\n detectors[detectorName]?.();\n });\n\n return detected;\n};\n\nconst getFirstAvailableLocale = (\n locales: Record<LanguageDetector, Locale | undefined>,\n order: LanguageDetector[]\n): Locale => {\n const { internationalization } = configuration;\n\n for (const detector of order) {\n const locale = locales[detector];\n\n if (locale && internationalization.locales.includes(locale)) {\n return locale;\n }\n }\n\n return internationalization?.defaultLocale ?? Locales.ENGLISH;\n};\n\n/**\n * Core language detector function for browser environments.\n *\n * Detects the user's preferred locale by checking multiple sources in order:\n * 1. Query string parameter\n * 2. Storage (cookies, localStorage, sessionStorage) - uses getLocaleFromStorage\n * 3. Navigator languages - uses localeDetector\n * 4. HTML lang attribute - uses localeDetector\n *\n * @param userOptions - Optional configuration for detection order and lookup keys\n * @returns The detected locale or the default locale\n *\n * @example\n * const locale = getBrowserLocale({ order: [LanguageDetector.Storage, LanguageDetector.Navigator] });\n */\nexport const getBrowserLocale = (\n userOptions: LanguageDetectorOptions | undefined = {}\n): Locale => {\n const options = { ...getDefaultsOptions(), ...userOptions };\n\n const locales = detectLanguage(options.order ?? [], options);\n\n return getFirstAvailableLocale(locales, options.order ?? []);\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { localeResolver } from "../dist/esm/localization/localeResolver.mjs";
|
|
2
|
+
import { getLocaleFromStorage } from "../dist/esm/utils/localeStorage.mjs";
|
|
1
3
|
import { getPreferredLanguages } from "./localeDetector.mjs";
|
|
2
4
|
import { DefaultValues } from "@intlayer/config/client";
|
|
3
5
|
import configuration from "@intlayer/config/built";
|
|
4
|
-
import { getLocaleFromStorage, localeResolver } from "@intlayer/core";
|
|
5
6
|
|
|
6
7
|
//#region src/localization/getLocale.ts
|
|
7
8
|
const getLocale = async (ctx = {}) => {
|