Merge branch 'develop' into luke/groups-are-communities

pull/21833/head
Luke Barnard 2017-10-19 11:31:00 +01:00 committed by GitHub
commit c3f143acc3
3 changed files with 73 additions and 26 deletions

View File

@ -28,11 +28,13 @@
"test" "test"
], ],
"bin": { "bin": {
"reskindex": "scripts/reskindex.js" "reskindex": "scripts/reskindex.js",
"matrix-gen-i18n": "scripts/gen-i18n.js"
}, },
"scripts": { "scripts": {
"reskindex": "node scripts/reskindex.js -h header", "reskindex": "node scripts/reskindex.js -h header",
"reskindex:watch": "node scripts/reskindex.js -h header -w", "reskindex:watch": "node scripts/reskindex.js -h header -w",
"i18n": "matrix-gen-i18n",
"build": "npm run reskindex && babel src -d lib --source-maps --copy-files", "build": "npm run reskindex && babel src -d lib --source-maps --copy-files",
"build:watch": "babel src -w -d lib --source-maps --copy-files", "build:watch": "babel src -w -d lib --source-maps --copy-files",
"emoji-data-strip": "node scripts/emoji-data-strip.js", "emoji-data-strip": "node scripts/emoji-data-strip.js",

47
scripts/gen-i18n.js Normal file → Executable file
View File

@ -1,3 +1,5 @@
#!/usr/bin/env node
/* /*
Copyright 2017 New Vector Ltd Copyright 2017 New Vector Ltd
@ -34,6 +36,13 @@ const TRANSLATIONS_FUNCS = ['_t', '_td', '_tJsx'];
const INPUT_TRANSLATIONS_FILE = 'src/i18n/strings/en_EN.json'; const INPUT_TRANSLATIONS_FILE = 'src/i18n/strings/en_EN.json';
// NB. The sync version of walk is broken for single files so we walk
// all of res rather than just res/home.html.
// https://git.daplie.com/Daplie/node-walk/merge_requests/1 fixes it,
// or if we get bored waiting for it to be merged, we could switch
// to a project that's actively maintained.
const SEARCH_PATHS = ['src', 'res'];
const FLOW_PARSER_OPTS = { const FLOW_PARSER_OPTS = {
esproposal_class_instance_fields: true, esproposal_class_instance_fields: true,
esproposal_class_static_fields: true, esproposal_class_static_fields: true,
@ -64,7 +73,7 @@ function getTKey(arg) {
return null; return null;
} }
function getTranslations(file) { function getTranslationsJs(file) {
const tree = flowParser.parse(fs.readFileSync(file, { encoding: 'utf8' }), FLOW_PARSER_OPTS); const tree = flowParser.parse(fs.readFileSync(file, { encoding: 'utf8' }), FLOW_PARSER_OPTS);
const trs = new Set(); const trs = new Set();
@ -106,6 +115,20 @@ function getTranslations(file) {
return trs; return trs;
} }
function getTranslationsOther(file) {
const contents = fs.readFileSync(file, { encoding: 'utf8' });
const trs = new Set();
// Taken from riot-web src/components/structures/HomePage.js
const translationsRegex = /_t\(['"]([\s\S]*?)['"]\)/mg;
let matches;
while (matches = translationsRegex.exec(contents)) {
trs.add(matches[1]);
}
return trs;
}
// gather en_EN plural strings from the input translations file: // gather en_EN plural strings from the input translations file:
// the en_EN strings are all in the source with the exception of // the en_EN strings are all in the source with the exception of
// pluralised strings, which we need to pull in from elsewhere. // pluralised strings, which we need to pull in from elsewhere.
@ -123,20 +146,32 @@ for (const key of Object.keys(inputTranslationsRaw)) {
const translatables = new Set(); const translatables = new Set();
walk.walkSync("src", { const walkOpts = {
listeners: { listeners: {
file: function(root, fileStats, next) { file: function(root, fileStats, next) {
if (!fileStats.name.endsWith('.js')) return;
const fullPath = path.join(root, fileStats.name); const fullPath = path.join(root, fileStats.name);
const trs = getTranslations(fullPath);
let ltrs;
if (fileStats.name.endsWith('.js')) {
trs = getTranslationsJs(fullPath);
} else if (fileStats.name.endsWith('.html')) {
trs = getTranslationsOther(fullPath);
} else {
return;
}
console.log(`${fullPath} (${trs.size} strings)`); console.log(`${fullPath} (${trs.size} strings)`);
for (const tr of trs.values()) { for (const tr of trs.values()) {
translatables.add(tr); translatables.add(tr);
} }
}, },
} }
}); };
for (const path of SEARCH_PATHS) {
if (fs.existsSync(path)) {
walk.walkSync(path, walkOpts);
}
}
const trObj = {}; const trObj = {};
for (const tr of translatables) { for (const tr of translatables) {

View File

@ -490,15 +490,15 @@ export default React.createClass({
}); });
}, },
_onNameChange: function(e) { _onNameChange: function(value) {
const newProfileForm = Object.assign(this.state.profileForm, { name: e.target.value }); const newProfileForm = Object.assign(this.state.profileForm, { name: value });
this.setState({ this.setState({
profileForm: newProfileForm, profileForm: newProfileForm,
}); });
}, },
_onShortDescChange: function(e) { _onShortDescChange: function(value) {
const newProfileForm = Object.assign(this.state.profileForm, { short_description: e.target.value }); const newProfileForm = Object.assign(this.state.profileForm, { short_description: value });
this.setState({ this.setState({
profileForm: newProfileForm, profileForm: newProfileForm,
}); });
@ -878,18 +878,28 @@ export default React.createClass({
</div> </div>
</div> </div>
); );
nameNode = <input type="text"
value={this.state.profileForm.name} const EditableText = sdk.getComponent("elements.EditableText");
onChange={this._onNameChange}
placeholder={_t('Community Name')} nameNode = <EditableText ref="nameEditor"
tabIndex="1" className="mx_GroupView_editable"
/>; placeholderClassName="mx_GroupView_placeholder"
shortDescNode = <input type="text" placeholder={_t('Community Name')}
value={this.state.profileForm.short_description} blurToCancel={false}
onChange={this._onShortDescChange} initialValue={this.state.profileForm.name}
placeholder={_t('Description')} onValueChanged={this._onNameChange}
tabIndex="2" tabIndex="1"
/>; dir="auto" />;
shortDescNode = <EditableText ref="descriptionEditor"
className="mx_GroupView_editable"
placeholderClassName="mx_GroupView_placeholder"
placeholder={_t("Description")}
blurToCancel={false}
initialValue={this.state.profileForm.short_description}
onValueChanged={this._onShortDescChange}
tabIndex="2"
dir="auto" />;
rightButtons.push( rightButtons.push(
<AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton" <AccessibleButton className="mx_GroupView_textButton mx_RoomHeader_textButton"
onClick={this._onSaveClick} key="_saveButton" onClick={this._onSaveClick} key="_saveButton"
@ -911,17 +921,17 @@ export default React.createClass({
width={48} height={48} width={48} height={48}
/>; />;
if (summary.profile && summary.profile.name) { if (summary.profile && summary.profile.name) {
nameNode = <div> nameNode = <div onClick={this._onEditClick}>
<span>{ summary.profile.name }</span> <span>{ summary.profile.name }</span>
<span className="mx_GroupView_header_groupid"> <span className="mx_GroupView_header_groupid">
({ this.props.groupId }) ({ this.props.groupId })
</span> </span>
</div>; </div>;
} else { } else {
nameNode = <span>{ this.props.groupId }</span>; nameNode = <span onClick={this._onEditClick}>{ this.props.groupId }</span>;
} }
if (summary.profile && summary.profile.short_description) { if (summary.profile && summary.profile.short_description) {
shortDescNode = <span>{ summary.profile.short_description }</span>; shortDescNode = <span onClick={this._onEditClick}>{ summary.profile.short_description }</span>;
} }
rightButtons.push( rightButtons.push(
<AccessibleButton className="mx_GroupHeader_button" <AccessibleButton className="mx_GroupHeader_button"