Merge pull request #3314 from overleaf/jpa-i18n-safe-html-substitute
[misc] i18n: safe html substitute GitOrigin-RevId: be74605d24084b419324509a403933cf71ed1c8a
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
const pug = require('pug-runtime')
|
||||
|
||||
const SPLIT_REGEX = /<(\d+)>(.*?)<\/\1>/g
|
||||
|
||||
function render(locale, components) {
|
||||
const output = []
|
||||
function addPlainText(text) {
|
||||
if (!text) return
|
||||
output.push(pug.escape(text))
|
||||
}
|
||||
|
||||
// 'PRE<0>INNER</0>POST' -> ['PRE', '0', 'INNER', 'POST']
|
||||
// '<0>INNER</0>' -> ['', '0', 'INNER', '']
|
||||
// '<0></0>' -> ['', '0', '', '']
|
||||
// '<0>INNER</0><0>INNER2</0>' -> ['', '0', 'INNER', '', '0', 'INNER2', '']
|
||||
// '<0><1>INNER</1></0>' -> ['', '0', '<1>INNER</1>', '']
|
||||
// 'PLAIN TEXT' -> ['PLAIN TEXT']
|
||||
// NOTE: a test suite is verifying these cases: SafeHTMLSubstituteTests
|
||||
const chunks = locale.split(SPLIT_REGEX)
|
||||
|
||||
// extract the 'PRE' chunk
|
||||
addPlainText(chunks.shift())
|
||||
|
||||
while (chunks.length) {
|
||||
// each batch consists of three chunks: ['0', 'INNER', 'POST']
|
||||
const [idx, innerChunk, intermediateChunk] = chunks.splice(0, 3)
|
||||
|
||||
const component = components[idx]
|
||||
const componentName =
|
||||
typeof component === 'string' ? component : component.name
|
||||
// pug is doing any necessary escaping on attribute values
|
||||
const attributes = (component.attrs && pug.attrs(component.attrs)) || ''
|
||||
output.push(
|
||||
`<${componentName + attributes}>`,
|
||||
...render(innerChunk, components),
|
||||
`</${componentName}>`
|
||||
)
|
||||
addPlainText(intermediateChunk)
|
||||
}
|
||||
return output.join('')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SPLIT_REGEX,
|
||||
render
|
||||
}
|
||||
@@ -12,6 +12,7 @@ const Features = require('./Features')
|
||||
const AuthenticationController = require('../Features/Authentication/AuthenticationController')
|
||||
const PackageVersions = require('./PackageVersions')
|
||||
const Modules = require('./Modules')
|
||||
const SafeHTMLSubstitute = require('../Features/Helpers/SafeHTMLSubstitution')
|
||||
|
||||
let webpackManifest
|
||||
if (!IS_DEV_ENV) {
|
||||
@@ -176,10 +177,15 @@ module.exports = function(webRouter, privateApiRouter, publicApiRouter) {
|
||||
})
|
||||
|
||||
webRouter.use(function(req, res, next) {
|
||||
res.locals.translate = function(key, vars) {
|
||||
res.locals.translate = function(key, vars, components) {
|
||||
vars = vars || {}
|
||||
vars.appName = Settings.appName
|
||||
return req.i18n.translate(key, vars)
|
||||
const locale = req.i18n.translate(key, vars)
|
||||
if (components) {
|
||||
return SafeHTMLSubstitute.render(locale, components)
|
||||
} else {
|
||||
return locale
|
||||
}
|
||||
}
|
||||
// Don't include the query string parameters, otherwise Google
|
||||
// treats ?nocdn=true as the canonical version
|
||||
|
||||
Reference in New Issue
Block a user