Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit bb030da

Browse files
committed
Add _tJsx()
1 parent de1cacf commit bb030da

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

src/languageHandler.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ limitations under the License.
1818
import request from 'browser-request';
1919
import counterpart from 'counterpart';
2020
import q from 'q';
21+
import sanitizeHtml from "sanitize-html";
2122

2223
import UserSettingsStore from './UserSettingsStore';
2324

@@ -37,6 +38,56 @@ export function _t(...args) {
3738
return counterpart.translate(...args);
3839
}
3940

41+
/*
42+
* Translates stringified JSX into translated JSX. E.g
43+
* _tJsx(
44+
* "click <a href=''>here</a> now",
45+
* /<a href=''>(.*?)<\/a>/,
46+
* (sub) => { return <a href=''>{ sub }</a>; }
47+
* );
48+
*
49+
* @param {string} jsxText The untranslated stringified JSX e.g "click <a href=''>here</a> now".
50+
* This will be translated by passing the string through to _t(...)
51+
*
52+
* @param {RegExp} pattern A regexp to match against the translated text.
53+
* The captured groups from the regexp will be fed to 'sub'.
54+
* Only the captured groups will be included in the output, the match itself is discarded.
55+
*
56+
* @param {Function} sub A function which will be called
57+
* with multiple args, each arg representing a captured group of the matching regexp.
58+
* This function must return a JSX node.
59+
*
60+
* @return A list of strings/JSX nodes.
61+
*/
62+
export function _tJsx(jsxText, pattern, sub) {
63+
if (!pattern instanceof RegExp) {
64+
throw new Error(`_tJsx: programmer error. expected RegExp for text: ${jsxText}`);
65+
}
66+
if (!sub instanceof Function) {
67+
throw new Error(`_tJsx: programmer error. expected Function for text: ${jsxText}`);
68+
}
69+
70+
// tJsxText may be unsafe if malicious translators try to inject HTML.
71+
// Run this through sanitize-html and bail if the output isn't identical
72+
const tJsxText = _t(jsxText);
73+
const sanitized = sanitizeHtml(tJsxText);
74+
if (tJsxText !== sanitized) {
75+
throw new Error(`_tJsx: translator error. untrusted HTML supplied. '${tJsxText}' != '${sanitized}'`);
76+
}
77+
let match = tJsxText.match(pattern);
78+
if (!match) {
79+
throw new Error(`_tJsx: translator error. expected translation to match regexp: ${pattern}`);
80+
}
81+
let capturedGroups = match.slice(1);
82+
// Return the raw translation before the *match* followed by the return value of sub() followed
83+
// by the raw translation after the *match* (not captured group).
84+
return [
85+
tJsxText.substr(0, match.index),
86+
sub.apply(null, capturedGroups),
87+
tJsxText.substr(match.index + match[0].length),
88+
];
89+
}
90+
4091
// Allow overriding the text displayed when no translation exists
4192
// Currently only use din unit tests to avoid having to load
4293
// the translations in riot-web

0 commit comments

Comments
 (0)