i18next 26.1.0 → 26.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +29 -0
- package/README.md +1 -1
- package/dist/esm/package.json +1 -1
- package/index.d.ts +1 -0
- package/package.json +1 -1
- package/typescript/options.d.ts +247 -128
- package/typescript/t.d.ts +20 -14
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(gh pr *)",
|
|
5
|
+
"Read(//Users/adrai/Projects/i18next/react-i18next/**)",
|
|
6
|
+
"Bash(git add *)",
|
|
7
|
+
"Bash(git commit *)",
|
|
8
|
+
"Read(//Users/adrai/Projects/i18next/**)",
|
|
9
|
+
"Bash(gh issue *)",
|
|
10
|
+
"Read(//tmp/**)",
|
|
11
|
+
"WebFetch(domain:github.com)",
|
|
12
|
+
"Bash(grep -n '$PreservedValue\\\\b' /Users/adrai/Projects/i18next/i18next/typescript/helpers.d.ts)",
|
|
13
|
+
"Bash(npm run *)",
|
|
14
|
+
"Bash(cat > *)",
|
|
15
|
+
"Bash(python3 -c \"import json,sys; print\\(json.load\\(sys.stdin\\)['version']\\)\")",
|
|
16
|
+
"Bash(npm test *)",
|
|
17
|
+
"Bash(git pull *)",
|
|
18
|
+
"Bash(git push *)",
|
|
19
|
+
"Bash(gh api *)",
|
|
20
|
+
"Bash(curl -s \"https://raw.githubusercontent.com/GabenGar/todos/d6d77cef716fcdc5a3991f84605176f85a69cdc8/apps/frontend/src/lib/internationalization/augs.d.ts\")"
|
|
21
|
+
],
|
|
22
|
+
"additionalDirectories": [
|
|
23
|
+
"/Users/adrai/Projects/i18next/react-i18next",
|
|
24
|
+
"/tmp",
|
|
25
|
+
"/Users/adrai/Projects/i18next/i18next-gitbook/overview",
|
|
26
|
+
"/Users/adrai/Projects/i18next/i18next-icu"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ i18next provides:
|
|
|
23
23
|
- Extensibility: eg. [sprintf](https://www.i18next.com/overview/plugins-and-utils#post-processors)
|
|
24
24
|
- ...
|
|
25
25
|
|
|
26
|
-
> **Pro Tip:** Looking for a way to manage your translations? Locize is the official service by i18next's creators and
|
|
26
|
+
> **Pro Tip:** Looking for a way to manage your translations? [Locize](https://www.locize.com?utm_source=i18next_readme&utm_medium=github&utm_campaign=readme) is the official service by i18next's creators — drop in [`i18next-locize-backend`](https://github.com/locize/i18next-locize-backend) for CDN delivery, AI translation, and no redeploys for copy changes. **[Free plan](https://www.locize.com/pricing?utm_source=i18next_readme&utm_medium=github&utm_campaign=readme)** available for small projects.
|
|
27
27
|
|
|
28
28
|
For more information visit the website:
|
|
29
29
|
|
package/dist/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"26.
|
|
1
|
+
{"type":"module","version":"26.3.0"}
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
package/typescript/options.d.ts
CHANGED
|
@@ -27,140 +27,246 @@ import type { $MergeBy, $PreservedValue, $Dictionary } from './helpers.js';
|
|
|
27
27
|
*/
|
|
28
28
|
export interface CustomTypeOptions {}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Per-package namespace types for monorepos. Augment this in each package's
|
|
32
|
+
* `i18next.d.ts` instead of `CustomTypeOptions.resources` when several packages
|
|
33
|
+
* need their own namespaces — otherwise TypeScript reports TS2717 on merge.
|
|
34
|
+
*
|
|
35
|
+
* Works alongside the legacy `CustomTypeOptions.resources` field; both end up
|
|
36
|
+
* in `TypeOptions['resources']`.
|
|
37
|
+
*
|
|
38
|
+
* Scalar type options like `defaultNS`, `returnNull`, `enableSelector`, etc.,
|
|
39
|
+
* still belong on `CustomTypeOptions` — this interface is for namespace
|
|
40
|
+
* resource types only.
|
|
41
|
+
*
|
|
42
|
+
* @see https://github.com/i18next/i18next/issues/2409
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // packages/ui/i18next.d.ts
|
|
47
|
+
* declare module 'i18next' {
|
|
48
|
+
* interface ResourceNamespaceMap {
|
|
49
|
+
* '@repo/ui': typeof uiTranslations;
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export interface ResourceNamespaceMap {}
|
|
55
|
+
|
|
30
56
|
/**
|
|
31
57
|
* This interface can be augmented by users to add types to `i18next` default PluginOptions.
|
|
32
58
|
*/
|
|
33
59
|
export interface CustomPluginOptions {}
|
|
34
60
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
type _LegacyResources = CustomTypeOptions extends { resources: infer R } ? R : object;
|
|
62
|
+
|
|
63
|
+
// Per-property merge of two object types. Unlike `L & R`, which TypeScript
|
|
64
|
+
// collapses to `never` whenever ANY property has incompatible literals (so a
|
|
65
|
+
// single same-key/different-literal conflict wipes out the whole namespace),
|
|
66
|
+
// this iterates keys and intersects them individually — the conflicting key
|
|
67
|
+
// becomes `never`, the rest survive.
|
|
68
|
+
type _PerPropMerge<L, R> = {
|
|
69
|
+
[K in keyof L | keyof R]: K extends keyof L
|
|
70
|
+
? K extends keyof R
|
|
71
|
+
? L[K] & R[K]
|
|
72
|
+
: L[K]
|
|
73
|
+
: K extends keyof R
|
|
74
|
+
? R[K]
|
|
75
|
+
: never;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Drop properties whose value resolved to `never`. Without this, the
|
|
79
|
+
// conflict key would leak into `keyof Resources[ns]`, then poison
|
|
80
|
+
// `KeysBuilder` recursion (it tries to walk a `never` value) and break
|
|
81
|
+
// `t()` overload resolution for the entire namespace.
|
|
82
|
+
// NOTE: must use the `Pick<T, NonNeverKeys>` form. A `[K in keyof T as ...]`
|
|
83
|
+
// remap does NOT eagerly evaluate `T[K]` for intersection types, so conflict
|
|
84
|
+
// keys would survive the filter.
|
|
85
|
+
type _NonNeverKeys<T> = {
|
|
86
|
+
[K in keyof T]: [T[K]] extends [never] ? never : K;
|
|
87
|
+
}[keyof T];
|
|
88
|
+
type _DropConflictKeys<T> = Pick<T, _NonNeverKeys<T>>;
|
|
89
|
+
|
|
90
|
+
// When the same namespace exists on both sides, deep-merge per property and
|
|
91
|
+
// strip same-key/different-literal conflicts. Otherwise pick from whichever
|
|
92
|
+
// side has it.
|
|
93
|
+
type _MergeNamespaces<L, R> = {
|
|
94
|
+
[K in keyof L | keyof R]: K extends keyof L
|
|
95
|
+
? K extends keyof R
|
|
96
|
+
? _DropConflictKeys<_PerPropMerge<L[K], R[K]>>
|
|
97
|
+
: L[K]
|
|
98
|
+
: K extends keyof R
|
|
99
|
+
? R[K]
|
|
100
|
+
: never;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// NOTE: empty legacy + empty registry must stay `object` so unconfigured projects
|
|
104
|
+
// still get `$IsResourcesDefined === false`.
|
|
105
|
+
type _MergedResources = [keyof _LegacyResources] extends [never]
|
|
106
|
+
? [keyof ResourceNamespaceMap] extends [never]
|
|
107
|
+
? object
|
|
108
|
+
: ResourceNamespaceMap
|
|
109
|
+
: [keyof ResourceNamespaceMap] extends [never]
|
|
110
|
+
? _LegacyResources
|
|
111
|
+
: _MergeNamespaces<_LegacyResources, ResourceNamespaceMap>;
|
|
54
112
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
113
|
+
export type TypeOptions = $MergeBy<
|
|
114
|
+
$MergeBy<
|
|
115
|
+
{
|
|
116
|
+
/** @see {InitOptions.returnNull} */
|
|
117
|
+
returnNull: false;
|
|
118
|
+
|
|
119
|
+
/** @see {InitOptions.returnEmptyString} */
|
|
120
|
+
returnEmptyString: true;
|
|
121
|
+
|
|
122
|
+
/** @see {InitOptions.returnObjects} */
|
|
123
|
+
returnObjects: false;
|
|
124
|
+
|
|
125
|
+
/** @see {InitOptions.keySeparator} */
|
|
126
|
+
keySeparator: '.';
|
|
127
|
+
|
|
128
|
+
/** @see {InitOptions.nsSeparator} */
|
|
129
|
+
nsSeparator: ':';
|
|
130
|
+
|
|
131
|
+
/** @see {InitOptions.pluralSeparator} */
|
|
132
|
+
pluralSeparator: '_';
|
|
133
|
+
|
|
134
|
+
/** @see {InitOptions.contextSeparator} */
|
|
135
|
+
contextSeparator: '_';
|
|
136
|
+
|
|
137
|
+
/** @see {InitOptions.defaultNS} */
|
|
138
|
+
defaultNS: 'translation';
|
|
139
|
+
|
|
140
|
+
/** @see {InitOptions.fallbackNS} */
|
|
141
|
+
fallbackNS: false;
|
|
142
|
+
|
|
143
|
+
/** @see {InitOptions.compatibilityJSON} */
|
|
144
|
+
compatibilityJSON: 'v4';
|
|
145
|
+
|
|
146
|
+
/** @see {InitOptions.resources} */
|
|
147
|
+
resources: object;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Flag that allows HTML elements to receive objects. This is only useful for React applications
|
|
151
|
+
* where you pass objects to HTML elements so they can be replaced to their respective interpolation
|
|
152
|
+
* values (mostly with Trans component)
|
|
153
|
+
*/
|
|
154
|
+
allowObjectInHTMLChildren: false;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Flag that enables strict key checking even if a `defaultValue` has been provided.
|
|
158
|
+
* This ensures all calls of `t` function don't accidentally use implicitly missing keys.
|
|
159
|
+
*/
|
|
160
|
+
strictKeyChecks: false;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Prefix for interpolation
|
|
164
|
+
*/
|
|
165
|
+
interpolationPrefix: '{{';
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Suffix for interpolation
|
|
169
|
+
*/
|
|
170
|
+
interpolationSuffix: '}}';
|
|
171
|
+
|
|
172
|
+
/** @see {InterpolationOptions.unescapePrefix} */
|
|
173
|
+
unescapePrefix: '-';
|
|
174
|
+
|
|
175
|
+
/** @see {InterpolationOptions.unescapeSuffix} */
|
|
176
|
+
unescapeSuffix: '';
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Whether to extract interpolation variables from translation strings at
|
|
180
|
+
* the type level. When `true` (default), the type system parses each
|
|
181
|
+
* resource value for `{{variable}}` patterns and types the `t()` options
|
|
182
|
+
* accordingly.
|
|
183
|
+
*
|
|
184
|
+
* Set to `false` when your translation strings use a different
|
|
185
|
+
* interpolation syntax that the i18next type extractor cannot understand
|
|
186
|
+
* — e.g. ICU MessageFormat plurals like `{count, plural, one {{count} row}
|
|
187
|
+
* other {{count} rows}}` would otherwise produce phantom variable names
|
|
188
|
+
* because the default extractor naively matches the outermost `{{` …
|
|
189
|
+
* `}}`. This flag is type-only; runtime interpolation is governed by
|
|
190
|
+
* `InterpolationOptions` and is unaffected.
|
|
191
|
+
*
|
|
192
|
+
* Required by `i18next-icu` users — see that package's docs for the
|
|
193
|
+
* recommended `CustomTypeOptions` augmentation.
|
|
194
|
+
*
|
|
195
|
+
* @default true
|
|
196
|
+
*/
|
|
197
|
+
parseInterpolation: true;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Use a proxy-based selector to select a translation.
|
|
201
|
+
*
|
|
202
|
+
* Enables features like go-to definition, and better DX/faster autocompletion
|
|
203
|
+
* for TypeScript developers.
|
|
204
|
+
*
|
|
205
|
+
* If you're working with an especially large set of translations and aren't
|
|
206
|
+
* using context, you set `enableSelector` to `"optimize"` and i18next won't do
|
|
207
|
+
* any type-level processing of your translations at all.
|
|
208
|
+
*
|
|
209
|
+
* With `enableSelector` set to `"optimize"`, i18next is capable of supporting
|
|
210
|
+
* arbitrarily large/deep translation sets without causing any IDE slowdown
|
|
211
|
+
* whatsoever.
|
|
212
|
+
*
|
|
213
|
+
* Set `enableSelector` to `"strict"` to require an explicit namespace as the
|
|
214
|
+
* first selector path segment in every call. The selector proxy stops
|
|
215
|
+
* exposing the primary namespace's keys flat on `$` — even
|
|
216
|
+
* `useTranslation('only')` must use `$.only.foo`, never `$.foo`. At runtime,
|
|
217
|
+
* a leading segment matching the scope's namespace list (primary included)
|
|
218
|
+
* is always rewritten as a namespace prefix, fully decoupling selector
|
|
219
|
+
* shape from resolution scope. Use this when you want a single mental model
|
|
220
|
+
* for selector paths regardless of how many namespaces a hook was created
|
|
221
|
+
* with, and to remove the silent miss that flat-primary paths can otherwise
|
|
222
|
+
* cause in multi-ns hooks (see [#2429](https://github.com/i18next/i18next/issues/2429)).
|
|
223
|
+
*
|
|
224
|
+
* `"strict"` mode is incompatible with the `"optimize"` shortcut. If you
|
|
225
|
+
* have keys whose names match sibling namespaces (the
|
|
226
|
+
* [#2405](https://github.com/i18next/i18next/issues/2405) pattern), do not
|
|
227
|
+
* enable strict mode — the leading-segment rewrite would route those keys
|
|
228
|
+
* into the wrong namespace.
|
|
229
|
+
*
|
|
230
|
+
* @default false
|
|
231
|
+
*/
|
|
232
|
+
enableSelector: false;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Maps interpolation format specifiers to their expected value types.
|
|
236
|
+
*
|
|
237
|
+
* By default, i18next infers types from built-in formatter names:
|
|
238
|
+
* - `number`, `currency` → `number`
|
|
239
|
+
* - `datetime` → `Date`
|
|
240
|
+
* - `relativetime` → `number`
|
|
241
|
+
* - `list` → `readonly string[]`
|
|
242
|
+
* - No format specifier → `string | number` (since i18next stringifies values at runtime)
|
|
243
|
+
*
|
|
244
|
+
* Use this option to add mappings for custom formatters or to override
|
|
245
|
+
* the built-in defaults.
|
|
246
|
+
*
|
|
247
|
+
* @default {} (empty — built-in defaults apply)
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* interface CustomTypeOptions {
|
|
252
|
+
* interpolationFormatTypeMap: {
|
|
253
|
+
* // custom formatter
|
|
254
|
+
* uppercase: string;
|
|
255
|
+
* // override built-in
|
|
256
|
+
* currency: string;
|
|
257
|
+
* };
|
|
258
|
+
* }
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
interpolationFormatTypeMap: {};
|
|
262
|
+
},
|
|
263
|
+
CustomTypeOptions
|
|
264
|
+
>,
|
|
265
|
+
// HACK: apply merged resources *after* CustomTypeOptions so registry contributions
|
|
266
|
+
// survive when CustomTypeOptions.resources is also defined. Without this
|
|
267
|
+
// second step, the inner $MergeBy would replace the default `resources: object`
|
|
268
|
+
// with CustomTypeOptions['resources'] alone, dropping the registry namespaces.
|
|
269
|
+
{ resources: _MergedResources }
|
|
164
270
|
>;
|
|
165
271
|
|
|
166
272
|
export type PluginOptions<T> = $MergeBy<
|
|
@@ -641,6 +747,19 @@ export interface InitOptions<T = object> extends PluginOptions<T> {
|
|
|
641
747
|
*/
|
|
642
748
|
nsSeparator?: false | string;
|
|
643
749
|
|
|
750
|
+
/**
|
|
751
|
+
* Selector-API mode. Mirrors `CustomTypeOptions['enableSelector']`.
|
|
752
|
+
*
|
|
753
|
+
* - `false` (default): selector API disabled.
|
|
754
|
+
* - `true` / `'optimize'`: selector resolution enabled.
|
|
755
|
+
* - `'strict'`: require an explicit namespace as the first selector
|
|
756
|
+
* path segment in every call. The resolver always rewrites a leading
|
|
757
|
+
* namespace-matching segment as a namespace prefix.
|
|
758
|
+
*
|
|
759
|
+
* @default false
|
|
760
|
+
*/
|
|
761
|
+
enableSelector?: false | true | 'optimize' | 'strict';
|
|
762
|
+
|
|
644
763
|
/**
|
|
645
764
|
* Char to split plural from key
|
|
646
765
|
* @default '_'
|
package/typescript/t.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ type _UnescapePrefix = TypeOptions['unescapePrefix'];
|
|
|
36
36
|
type _UnescapeSuffix = TypeOptions['unescapeSuffix'];
|
|
37
37
|
type _StrictKeyChecks = TypeOptions['strictKeyChecks'];
|
|
38
38
|
type _EnableSelector = TypeOptions['enableSelector'];
|
|
39
|
+
type _ParseInterpolation = TypeOptions['parseInterpolation'];
|
|
39
40
|
type _InterpolationFormatTypeMap = TypeOptions['interpolationFormatTypeMap'];
|
|
40
41
|
|
|
41
42
|
type $IsResourcesDefined = [keyof _Resources] extends [never] ? false : true;
|
|
@@ -76,19 +77,23 @@ interface Branded<Ns extends Namespace> {
|
|
|
76
77
|
/** ****************************************************
|
|
77
78
|
* Build all keys and key prefixes based on Resources *
|
|
78
79
|
***************************************************** */
|
|
79
|
-
type KeysBuilderWithReturnObjects<Res, Key = keyof Res> =
|
|
80
|
-
?
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
type KeysBuilderWithReturnObjects<Res, Key = keyof Res> = [Res] extends [never]
|
|
81
|
+
? never
|
|
82
|
+
: Key extends keyof Res
|
|
83
|
+
? Res[Key] extends $Dictionary | readonly unknown[]
|
|
84
|
+
?
|
|
85
|
+
| JoinKeys<Key, WithOrWithoutPlural<keyof $OmitArrayKeys<Res[Key]>>>
|
|
86
|
+
| JoinKeys<Key, KeysBuilderWithReturnObjects<Res[Key]>>
|
|
87
|
+
: never
|
|
88
|
+
: never;
|
|
86
89
|
|
|
87
|
-
type KeysBuilderWithoutReturnObjects<Res, Key = keyof $OmitArrayKeys<Res>> =
|
|
88
|
-
?
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
type KeysBuilderWithoutReturnObjects<Res, Key = keyof $OmitArrayKeys<Res>> = [Res] extends [never]
|
|
91
|
+
? never
|
|
92
|
+
: Key extends keyof Res
|
|
93
|
+
? Res[Key] extends $Dictionary | readonly unknown[]
|
|
94
|
+
? JoinKeys<Key, KeysBuilderWithoutReturnObjects<Res[Key]>>
|
|
95
|
+
: Key
|
|
96
|
+
: never;
|
|
92
97
|
|
|
93
98
|
type KeysBuilder<Res, WithReturnObjects> = $IsResourcesDefined extends true
|
|
94
99
|
? WithReturnObjects extends true
|
|
@@ -168,8 +173,9 @@ type ParseActualValue<Ret> = Ret extends `${_UnescapePrefix}${infer ActualValue}
|
|
|
168
173
|
: Ret;
|
|
169
174
|
|
|
170
175
|
/** Parses interpolation entries as `[variableName, formatSpecifier | never]` tuples. */
|
|
171
|
-
type ParseInterpolationEntries<Ret> =
|
|
172
|
-
|
|
176
|
+
type ParseInterpolationEntries<Ret> = [_ParseInterpolation] extends [false]
|
|
177
|
+
? never
|
|
178
|
+
: Ret extends `${string}${_InterpolationPrefix}${infer Value}${_InterpolationSuffix}${infer Rest}`
|
|
173
179
|
?
|
|
174
180
|
| (Value extends `${infer ActualValue},${infer Format}`
|
|
175
181
|
? [ParseActualValue<ActualValue>, TrimSpaces<Format>]
|