mirror of
https://github.com/element-hq/element-web
synced 2024-11-26 19:26:04 +03:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
5b31390435
1 changed files with 75 additions and 0 deletions
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
import request from 'browser-request';
|
||||
import counterpart from 'counterpart';
|
||||
import q from 'q';
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
|
||||
import UserSettingsStore from './UserSettingsStore';
|
||||
|
||||
|
@ -37,6 +38,80 @@ export function _t(...args) {
|
|||
return counterpart.translate(...args);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translates stringified JSX into translated JSX. E.g
|
||||
* _tJsx(
|
||||
* "click <a href=''>here</a> now",
|
||||
* /<a href=''>(.*?)<\/a>/,
|
||||
* (sub) => { return <a href=''>{ sub }</a>; }
|
||||
* );
|
||||
*
|
||||
* @param {string} jsxText The untranslated stringified JSX e.g "click <a href=''>here</a> now".
|
||||
* This will be translated by passing the string through to _t(...)
|
||||
*
|
||||
* @param {RegExp|RegExp[]} patterns A regexp to match against the translated text.
|
||||
* The captured groups from the regexp will be fed to 'sub'.
|
||||
* Only the captured groups will be included in the output, the match itself is discarded.
|
||||
* If multiple RegExps are provided, the function at the same position will be called. The
|
||||
* match will always be done from left to right, so the 2nd RegExp will be matched against the
|
||||
* remaining text from the first RegExp.
|
||||
*
|
||||
* @param {Function|Function[]} subs A function which will be called
|
||||
* with multiple args, each arg representing a captured group of the matching regexp.
|
||||
* This function must return a JSX node.
|
||||
*
|
||||
* @return A list of strings/JSX nodes.
|
||||
*/
|
||||
export function _tJsx(jsxText, patterns, subs) {
|
||||
// convert everything to arrays
|
||||
if (patterns instanceof RegExp) {
|
||||
patterns = [patterns];
|
||||
}
|
||||
if (subs instanceof Function) {
|
||||
subs = [subs];
|
||||
}
|
||||
// sanity checks
|
||||
if (subs.length !== patterns.length || subs.length < 1) {
|
||||
throw new Error(`_tJsx: programmer error. expected number of RegExps == number of Functions: ${subs.length} != ${patterns.length}`);
|
||||
}
|
||||
for (let i = 0; i < subs.length; i++) {
|
||||
if (!patterns[i] instanceof RegExp) {
|
||||
throw new Error(`_tJsx: programmer error. expected RegExp for text: ${jsxText}`);
|
||||
}
|
||||
if (!subs[i] instanceof Function) {
|
||||
throw new Error(`_tJsx: programmer error. expected Function for text: ${jsxText}`);
|
||||
}
|
||||
}
|
||||
|
||||
// tJsxText may be unsafe if malicious translators try to inject HTML.
|
||||
// Run this through sanitize-html and bail if the output isn't identical
|
||||
const tJsxText = _t(jsxText);
|
||||
const sanitized = sanitizeHtml(tJsxText, { allowedTags: sanitizeHtml.defaults.allowedTags.concat([ 'span' ]) });
|
||||
if (tJsxText !== sanitized) {
|
||||
throw new Error(`_tJsx: translator error. untrusted HTML supplied. '${tJsxText}' != '${sanitized}'`);
|
||||
}
|
||||
|
||||
let output = [tJsxText];
|
||||
for (let i = 0; i < patterns.length; i++) {
|
||||
// convert the last element in 'output' into 3 elements (pre-text, sub function, post-text).
|
||||
// Rinse and repeat for other patterns (using post-text).
|
||||
let inputText = output.pop();
|
||||
let match = inputText.match(patterns[i]);
|
||||
if (!match) {
|
||||
throw new Error(`_tJsx: translator error. expected translation to match regexp: ${patterns[i]}`);
|
||||
}
|
||||
let capturedGroups = match.slice(1);
|
||||
|
||||
// Return the raw translation before the *match* followed by the return value of sub() followed
|
||||
// by the raw translation after the *match* (not captured group).
|
||||
output.push(inputText.substr(0, match.index));
|
||||
output.push(subs[i].apply(null, capturedGroups));
|
||||
output.push(inputText.substr(match.index + match[0].length));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Allow overriding the text displayed when no translation exists
|
||||
// Currently only use din unit tests to avoid having to load
|
||||
// the translations in riot-web
|
||||
|
|
Loading…
Reference in a new issue