@@ -34,9 +34,11 @@ import {
3434 isEmptyObject ,
3535 generateFormatCacheKey ,
3636 generateCodeFrame ,
37+ escapeHtml ,
3738 inBrowser ,
3839 mark ,
39- measure
40+ measure ,
41+ isObject
4042} from '../utils'
4143import { DevToolsTimelineEvents } from '../debugger/constants'
4244
@@ -83,6 +85,9 @@ const isMessageFunction = <T>(val: unknown): val is MessageFunction<T> =>
8385 *
8486 * // suppress localize fallback warning option, override context.fallbackWarn
8587 * translate(context, 'foo.bar', { name: 'kazupon' }, { fallbackWarn: false })
88+ *
89+ * // escape parameter option, override context.escapeParameter
90+ * translate(context, 'foo.bar', { name: 'kazupon' }, { escapeParameter: true })
8691 */
8792
8893/** @internal */
@@ -94,6 +99,7 @@ export type TranslateOptions = {
9499 locale ?: Locale
95100 missingWarn ?: boolean
96101 fallbackWarn ?: boolean
102+ escapeParameter ?: boolean
97103}
98104
99105// `translate` function overloads
@@ -210,6 +216,10 @@ export function translate<Messages, Message = string>(
210216 ? options . fallbackWarn
211217 : context . fallbackWarn
212218
219+ const escapeParameter = isBoolean ( options . escapeParameter )
220+ ? options . escapeParameter
221+ : context . escapeParameter
222+
213223 // prettier-ignore
214224 const defaultMsgOrKey : string =
215225 isString ( options . default ) || isBoolean ( options . default ) // default by function option
@@ -222,6 +232,9 @@ export function translate<Messages, Message = string>(
222232 const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== ''
223233 const locale = isString ( options . locale ) ? options . locale : context . locale
224234
235+ // escape params
236+ escapeParameter && escapeParams ( options )
237+
225238 // resolve message format
226239 // eslint-disable-next-line prefer-const
227240 let [ format , targetLocale , message ] = resolveMessageFormat (
@@ -289,6 +302,20 @@ export function translate<Messages, Message = string>(
289302 return postTranslation ? postTranslation ( messaged ) : messaged
290303}
291304
305+ function escapeParams ( options : TranslateOptions ) {
306+ if ( isArray ( options . list ) ) {
307+ options . list = options . list . map ( item =>
308+ isString ( item ) ? escapeHtml ( item ) : item
309+ )
310+ } else if ( isObject ( options . named ) ) {
311+ Object . keys ( options . named ) . forEach ( key => {
312+ if ( isString ( options . named ! [ key ] ) ) {
313+ options . named ! [ key ] = escapeHtml ( options . named ! [ key ] as string )
314+ }
315+ } )
316+ }
317+ }
318+
292319function resolveMessageFormat < Messages , Message > (
293320 context : RuntimeTranslationContext < Messages , Message > ,
294321 key : string ,
0 commit comments