- fix:
$t()nesting options blocks that span multiple lines are now parsed.nest()decided where the nested key ends by testingmatch[1]with/{.*}/, whose dot does not cross line breaks — so a$t(key, { ... })options object containing a newline was treated as having no options, mis-split as formatters, and the nested lookup ran without its options (placeholders stayed unresolved). The nesting regexp itself already matches newlines inside$t(...); adding thes(dotAll) flag makes multiline options behave like the single-line form. Thanks @spokodev (#2440). - fix:
getUsedParamsDetails(thereturnDetails: truepath) no longer mutates the passedreplaceobject. It wrotecountstraight ontooptions.replaceso the returnedusedParamswould include it — a caller reusing onereplaceobject acrosst()calls then carried a stalecountinto later interpolations (e.g. a previous call'scount: 5rendered instead of the current call's value). The details are now built from a copy;usedParamsstill includescount. Thanks @spokodev (#2441). - fix: with the default
skipOnVariables: true+escapeValue: true, a{{placeholder}}carried inside an interpolated value now stays literal even when the value contains escapable characters. The skip logic advanced the regexlastIndexby the raw value length, but the escaped text written into the string is longer, solastIndexlanded inside the inserted value and a trailing{{placeholder}}in it got interpolated — leaking another in-scope variable that should have stayed literal (values without escapable characters were already skipped correctly). The advance now uses the escaped length that is actually written, and the regex-safe$-doubling is applied only at theString.replacecall so it can't distort the length arithmetic. Thanks @spokodev (#2442).