From 8774100508cc36b5b0b96a4d78001543cdbe2f9f Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 28 Apr 2017 13:22:55 +0100 Subject: [PATCH 001/275] Initial implementation: SetDisplayName -> SetMxIdDialog - Replaces SetDisplayNameDialog with SetMxIdDialog. This new dialog will use InteractiveAuth to authenticate a user with their chosen mxid. De-scoped: - style tweaks for the InteractiveAuth in the dialog (capcha) and error message. - checking for mxid availability --- src/component-index.js | 4 +- src/components/structures/LoggedInView.js | 5 + src/components/structures/MatrixChat.js | 1 + src/components/structures/RoomView.js | 53 +++--- .../views/dialogs/SetDisplayNameDialog.js | 87 ---------- src/components/views/dialogs/SetMxIdDialog.js | 153 ++++++++++++++++++ 6 files changed, 182 insertions(+), 121 deletions(-) delete mode 100644 src/components/views/dialogs/SetDisplayNameDialog.js create mode 100644 src/components/views/dialogs/SetMxIdDialog.js diff --git a/src/component-index.js b/src/component-index.js index d6873c6dfd..2e55ad14cc 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -95,8 +95,8 @@ import views$dialogs$QuestionDialog from './components/views/dialogs/QuestionDia views$dialogs$QuestionDialog && (module.exports.components['views.dialogs.QuestionDialog'] = views$dialogs$QuestionDialog); import views$dialogs$SessionRestoreErrorDialog from './components/views/dialogs/SessionRestoreErrorDialog'; views$dialogs$SessionRestoreErrorDialog && (module.exports.components['views.dialogs.SessionRestoreErrorDialog'] = views$dialogs$SessionRestoreErrorDialog); -import views$dialogs$SetDisplayNameDialog from './components/views/dialogs/SetDisplayNameDialog'; -views$dialogs$SetDisplayNameDialog && (module.exports.components['views.dialogs.SetDisplayNameDialog'] = views$dialogs$SetDisplayNameDialog); +import views$dialogs$SetMxIdDialog from './components/views/dialogs/SetMxIdDialog'; +views$dialogs$SetMxIdDialog && (module.exports.components['views.dialogs.SetMxIdDialog'] = views$dialogs$SetMxIdDialog); import views$dialogs$TextInputDialog from './components/views/dialogs/TextInputDialog'; views$dialogs$TextInputDialog && (module.exports.components['views.dialogs.TextInputDialog'] = views$dialogs$TextInputDialog); import views$dialogs$UnknownDeviceDialog from './components/views/dialogs/UnknownDeviceDialog'; diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index c4eeb03d5f..6514b32f79 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -43,6 +43,10 @@ export default React.createClass({ onRoomCreated: React.PropTypes.func, onUserSettingsClose: React.PropTypes.func, + // Called with the credentials of a registered user (if they were a ROU that + // transitioned to PWLU) + onRegistered: React.PropTypes.func, + teamToken: React.PropTypes.string, // and lots and lots of other stuff. @@ -184,6 +188,7 @@ export default React.createClass({ roomAddress={this.props.currentRoomAlias || this.props.currentRoomId} autoJoin={this.props.autoJoin} onRoomIdResolved={this.props.onRoomIdResolved} + onRegistered={this.props.onRegistered} eventId={this.props.initialEventId} thirdPartyInvite={this.props.thirdPartyInvite} oobData={this.props.roomOobData} diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 9b8aa3426a..0fe2d6a52f 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1166,6 +1166,7 @@ module.exports = React.createClass({ onRoomIdResolved={this.onRoomIdResolved} onRoomCreated={this.onRoomCreated} onUserSettingsClose={this.onUserSettingsClose} + onRegistered={this.onRegistered} teamToken={this._teamToken} {...this.props} {...this.state} diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a0c36374b6..83b446597c 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -69,6 +69,10 @@ module.exports = React.createClass({ // once it has been resolved. onRoomIdResolved: React.PropTypes.func, + // Called with the credentials of a registered user (if they were a ROU that + // transitioned to PWLU) + onRegistered: React.PropTypes.func, + // An object representing a third party invite to join this room // Fields: // * inviteSignUrl (string) The URL used to join this room from an email invite @@ -764,38 +768,27 @@ module.exports = React.createClass({ var self = this; var cli = MatrixClientPeg.get(); - var display_name_promise = q(); - // if this is the first room we're joining, check the user has a display name - // and if they don't, prompt them to set one. - // NB. This unfortunately does not re-use the ChangeDisplayName component because - // it doesn't behave quite as desired here (we want an input field here rather than - // content-editable, and we want a default). - if (cli.getRooms().filter((r) => { - return r.hasMembershipState(cli.credentials.userId, "join"); - })) { - display_name_promise = cli.getProfileInfo(cli.credentials.userId).then((result) => { - if (!result.displayname) { - var SetDisplayNameDialog = sdk.getComponent('views.dialogs.SetDisplayNameDialog'); - var dialog_defer = q.defer(); - Modal.createDialog(SetDisplayNameDialog, { - currentDisplayName: result.displayname, - onFinished: (submitted, newDisplayName) => { - if (submitted) { - cli.setDisplayName(newDisplayName).done(() => { - dialog_defer.resolve(); - }); - } - else { - dialog_defer.reject(); - } - } - }); - return dialog_defer.promise; + var mxIdPromise = q(); + + // If the user is a ROU, allow them to transition to a PWLU + if (cli.isGuest()) { + const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); + mxIdPromise = q.defer(); + Modal.createDialog(SetMxIdDialog, { + onFinished: (submitted, credentials) => { + if (!submitted) { + mxIdPromise.reject(); + } + this.props.onRegistered(credentials); + mxIdPromise.resolve(); } }); } - display_name_promise.then(() => { + mxIdPromise.then(() => { + this.setState({ + joining: true + }); // if this is an invite and has the 'direct' hint set, mark it as a DM room now. if (this.state.room) { const me = this.state.room.getMember(MatrixClientPeg.get().credentials.userId); @@ -870,10 +863,6 @@ module.exports = React.createClass({ }); } }).done(); - - this.setState({ - joining: true - }); }, onMessageListScroll: function(ev) { diff --git a/src/components/views/dialogs/SetDisplayNameDialog.js b/src/components/views/dialogs/SetDisplayNameDialog.js deleted file mode 100644 index 1047e05c26..0000000000 --- a/src/components/views/dialogs/SetDisplayNameDialog.js +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import sdk from '../../../index'; -import MatrixClientPeg from '../../../MatrixClientPeg'; - -/** - * Prompt the user to set a display name. - * - * On success, `onFinished(true, newDisplayName)` is called. - */ -export default React.createClass({ - displayName: 'SetDisplayNameDialog', - propTypes: { - onFinished: React.PropTypes.func.isRequired, - currentDisplayName: React.PropTypes.string, - }, - - getInitialState: function() { - if (this.props.currentDisplayName) { - return { value: this.props.currentDisplayName }; - } - - if (MatrixClientPeg.get().isGuest()) { - return { value : "Guest " + MatrixClientPeg.get().getUserIdLocalpart() }; - } - else { - return { value : MatrixClientPeg.get().getUserIdLocalpart() }; - } - }, - - componentDidMount: function() { - this.refs.input_value.select(); - }, - - onValueChange: function(ev) { - this.setState({ - value: ev.target.value - }); - }, - - onFormSubmit: function(ev) { - ev.preventDefault(); - this.props.onFinished(true, this.state.value); - return false; - }, - - render: function() { - const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); - return ( - -
- Your display name is how you'll appear to others when you speak in rooms.
- What would you like it to be? -
-
-
- -
-
- -
-
-
- ); - }, -}); diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js new file mode 100644 index 0000000000..78737e4ac4 --- /dev/null +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -0,0 +1,153 @@ +/* +Copyright 2016 OpenMarket Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import q from 'q'; +import React from 'react'; +import sdk from '../../../index'; +import MatrixClientPeg from '../../../MatrixClientPeg'; + +/** + * Prompt the user to set a display name. + * + * On success, `onFinished(true, newDisplayName)` is called. + */ +export default React.createClass({ + displayName: 'SetMxIdDialog', + propTypes: { + onFinished: React.PropTypes.func.isRequired, + }, + + getInitialState: function() { + return { + username : '', + doingUIAuth: false, + } + }, + + componentDidMount: function() { + this.refs.input_value.select(); + + this._matrixClient = MatrixClientPeg.get(); + }, + + onValueChange: function(ev) { + this.setState({ + username: ev.target.value + }); + }, + + onSubmit: function(ev) { + this.setState({ + doingUIAuth: true, + }); + }, + + _generateAndCachePassword: function() { + const pass = Math.random().toString(36).slice(2); + if (localStorage) { + localStorage.setItem('mx_pass', pass); + } + return pass; + }, + + _makeRegisterRequest: function(auth) { + // Not upgrading - changing mxids + const guestAccessToken = null; + + return this._matrixClient.register( + this.state.username, + this._generateAndCachePassword(), + undefined, // session id: included in the auth dict already + auth, + {}, + guestAccessToken, + ); + }, + + _onUIAuthFinished: function(success, response) { + this.setState({ + doingUIAuth: false, + }); + console.info('Auth Finsihed', arguments); + + if (!success) { + this.setState({ errorText : response.message }); + return; + } + + // XXX Implement RTS /register here + const teamToken = null; + + this.props.onFinished(true, { + userId: response.user_id, + deviceId: response.device_id, + homeserverUrl: this._matrixClient.getHomeserverUrl(), + identityServerUrl: this._matrixClient.getIdentityServerUrl(), + accessToken: response.access_token, + teamToken: teamToken, + }); + }, + + render: function() { + const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); + const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth'); + const Spinner = sdk.getComponent('elements.Spinner'); + let auth; + if (this.state.doingUIAuth) { + auth = ; + } + return ( + +
+

+ Beyond this point you're going to need to pick a username - your + unique identifire in Riot. +

+

+ + You can't change your username, but you can always choose how you + appear to other people in Riot by changing your display name. + +

+ + { auth } +
+ { this.state.errorText } +
+
+
+ +
+
+ ); + }, +}); From 6dff4a44157bd8006a4ee6ccc97efa534bbf5b36 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 28 Apr 2017 13:28:34 +0100 Subject: [PATCH 002/275] Return early after cancelled mxid dialog --- src/components/structures/RoomView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 83b446597c..d06c2c2226 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -778,6 +778,7 @@ module.exports = React.createClass({ onFinished: (submitted, credentials) => { if (!submitted) { mxIdPromise.reject(); + return; } this.props.onRegistered(credentials); mxIdPromise.resolve(); From d12b1903f2b528426931271c6256aa016082c00d Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 28 Apr 2017 13:29:30 +0100 Subject: [PATCH 003/275] Fix defer promise logic --- src/components/structures/RoomView.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index d06c2c2226..569c4e46f0 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -773,15 +773,16 @@ module.exports = React.createClass({ // If the user is a ROU, allow them to transition to a PWLU if (cli.isGuest()) { const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); - mxIdPromise = q.defer(); + const defered = q.defer(); + mxIdPromise = defered.promise; Modal.createDialog(SetMxIdDialog, { onFinished: (submitted, credentials) => { if (!submitted) { - mxIdPromise.reject(); + defered.reject(); return; } this.props.onRegistered(credentials); - mxIdPromise.resolve(); + defered.resolve(); } }); } From 5a5768a4ecc9033f64e98e146ad8628a61cf079c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 28 Apr 2017 13:38:35 +0100 Subject: [PATCH 004/275] Try to fix tests --- src/components/structures/RoomView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 569c4e46f0..848a8cc7ba 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -771,7 +771,7 @@ module.exports = React.createClass({ var mxIdPromise = q(); // If the user is a ROU, allow them to transition to a PWLU - if (cli.isGuest()) { + if (cli && cli.isGuest()) { const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const defered = q.defer(); mxIdPromise = defered.promise; From a887af9f92c8f9c9b58bcff8190eb42f1e7f6bb3 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 2 May 2017 09:56:14 +0100 Subject: [PATCH 005/275] copyright --- src/component-index.js | 1 + src/components/views/dialogs/SetMxIdDialog.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/component-index.js b/src/component-index.js index 2e55ad14cc..aa65cabbec 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 78737e4ac4..c8083371de 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -1,5 +1,6 @@ /* Copyright 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 4f71f4c331bb36d19ccdd92d2d92425bc7cf3138 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 2 May 2017 10:07:06 +0100 Subject: [PATCH 006/275] Store mx_pass at the same point as access_token So that we don't overwrite the existing one every time we try to register. --- src/Lifecycle.js | 6 ++++++ src/components/views/dialogs/SetMxIdDialog.js | 12 +++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index f20716cae6..7fba0a0298 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -303,6 +303,12 @@ export function setLoggedIn(credentials) { localStorage.setItem("mx_device_id", credentials.deviceId); } + // The user registered as a PWLU (PassWord-Less User), the generated password + // is cached here such that the user can change it at a later time. + if (credentials.password) { + localStorage.setItem("mx_pass", credentials.password); + } + console.log("Session persisted for %s", credentials.userId); } catch (e) { console.warn("Error using local storage: can't persist session!", e); diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index c8083371de..db88c3304b 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -56,21 +56,18 @@ export default React.createClass({ }); }, - _generateAndCachePassword: function() { - const pass = Math.random().toString(36).slice(2); - if (localStorage) { - localStorage.setItem('mx_pass', pass); - } - return pass; + _generatePassword: function() { + return Math.random().toString(36).slice(2); }, _makeRegisterRequest: function(auth) { // Not upgrading - changing mxids const guestAccessToken = null; + this._generatedPassword = this._generatePassword(); return this._matrixClient.register( this.state.username, - this._generateAndCachePassword(), + this._generatedPassword, undefined, // session id: included in the auth dict already auth, {}, @@ -98,6 +95,7 @@ export default React.createClass({ homeserverUrl: this._matrixClient.getHomeserverUrl(), identityServerUrl: this._matrixClient.getIdentityServerUrl(), accessToken: response.access_token, + password: this._generatedPassword, teamToken: teamToken, }); }, From 13d37e43ff85605ba74a06c146a0ab11086421d8 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 2 May 2017 10:14:54 +0100 Subject: [PATCH 007/275] Mock isGuest --- test/test-utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test-utils.js b/test/test-utils.js index 5209465362..9f404f98eb 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -133,6 +133,7 @@ export function createTestClient() { sendHtmlMessage: () => q({}), getSyncState: () => "SYNCING", generateClientSecret: () => "t35tcl1Ent5ECr3T", + isGuest: () => false, }; } From 18ba5d3e49319c4c47d70a8c0ec1ec9ca84a5fd9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Wed, 3 May 2017 12:39:24 +0100 Subject: [PATCH 008/275] fix typo made in #849 --- src/components/views/dialogs/SetMxIdDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index db88c3304b..d139a4ae3b 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -122,7 +122,7 @@ export default React.createClass({

Beyond this point you're going to need to pick a username - your - unique identifire in Riot. + unique identifier in Riot.

From 6f4eb9d8b1809c6419945f472d0455978274751f Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 5 May 2017 16:31:33 +0100 Subject: [PATCH 009/275] Show password nag bar when user is PWLU --- src/Lifecycle.js | 6 ++++-- src/components/structures/LoggedInView.js | 13 +++++++++---- src/components/structures/MatrixChat.js | 12 ++++++++++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 7fba0a0298..43a46e2d7d 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -284,6 +284,7 @@ export function setLoggedIn(credentials) { // Resolves by default let teamPromise = Promise.resolve(null); + let isPasswordStored = false; // persist the session if (localStorage) { @@ -307,6 +308,7 @@ export function setLoggedIn(credentials) { // is cached here such that the user can change it at a later time. if (credentials.password) { localStorage.setItem("mx_pass", credentials.password); + isPasswordStored = true; } console.log("Session persisted for %s", credentials.userId); @@ -332,10 +334,10 @@ export function setLoggedIn(credentials) { MatrixClientPeg.replaceUsingCreds(credentials); teamPromise.then((teamToken) => { - dis.dispatch({action: 'on_logged_in', teamToken: teamToken}); + dis.dispatch({action: 'on_logged_in', teamToken: teamToken, isPasswordStored}); }, (err) => { console.warn("Failed to get team token on login", err); - dis.dispatch({action: 'on_logged_in', teamToken: null}); + dis.dispatch({action: 'on_logged_in', teamToken: null, isPasswordStored}); }); startMatrixClient(); diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 6514b32f79..4001227355 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -49,6 +49,10 @@ export default React.createClass({ teamToken: React.PropTypes.string, + // Has the user generated a password that is stored in local storage? + // (are they a PWLU?) + userHasGeneratedPassword: React.PropTypes.boolean, + // and lots and lots of other stuff. }, @@ -177,6 +181,7 @@ export default React.createClass({ const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar'); const GuestWarningBar = sdk.getComponent('globals.GuestWarningBar'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); + const PasswordNagBar = sdk.getComponent('globals.PasswordNagBar'); let page_element; let right_panel = ''; @@ -250,11 +255,11 @@ export default React.createClass({ topBar = ; - } - else if (this.props.matrixClient.isGuest()) { + } else if (this.props.matrixClient.isGuest()) { topBar = ; - } - else if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { + } else if (this.props.userHasGeneratedPassword) { + topBar = ; + } else if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { topBar = ; } diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 0fe2d6a52f..26f89079f7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -138,6 +138,9 @@ module.exports = React.createClass({ register_hs_url: null, register_is_url: null, register_id_sid: null, + + // Initially, use localStorage as source of truth + userHasGeneratedPassword: localStorage && localStorage.getItem('mx_pass'), }; return s; }, @@ -569,7 +572,7 @@ module.exports = React.createClass({ this.setState({loggingIn: true}); break; case 'on_logged_in': - this._onLoggedIn(payload.teamToken); + this._onLoggedIn(payload.teamToken, payload.isPasswordStored); break; case 'on_logged_out': this._onLoggedOut(); @@ -755,11 +758,15 @@ module.exports = React.createClass({ /** * Called when a new logged in session has started */ - _onLoggedIn: function(teamToken) { + _onLoggedIn: function(teamToken, isPasswordStored) { this.setState({ guestCreds: null, loggedIn: true, loggingIn: false, + // isPasswordStored only true when ROU sets a username and becomes PWLU. + // (the password was randomly generated and stored in localStorage). + userHasGeneratedPassword: + this.state.userHasGeneratedPassword || isPasswordStored, }); if (teamToken) { @@ -1168,6 +1175,7 @@ module.exports = React.createClass({ onUserSettingsClose={this.onUserSettingsClose} onRegistered={this.onRegistered} teamToken={this._teamToken} + userHasGeneratedPassword={this.state.userHasGeneratedPassword} {...this.props} {...this.state} /> From ad2ed129800bbcc79544c66426f2fd70a5708dfa Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 10 May 2017 14:22:17 +0100 Subject: [PATCH 010/275] Redesign mxID chooser, add availability checking Requires https://github.com/matrix-org/matrix-js-sdk/pull/432 for availability checking. Changes: - Redesign the dialog to look more like https://github.com/vector-im/riot-web/issues/3604#issuecomment-299226875 - Attempt to fix wrong password being stored by generating one per SetMxIdDialog (there's no issue tracking this for now, I shall open one if it persists) - Backwards compatible with servers that don't support register/availability - a spinner will appear the first time a username is checked because server support can only be determined after a request. - Rate-limited by a 2s debounce - General style improvements --- src/components/structures/RoomView.js | 11 +- src/components/views/dialogs/SetMxIdDialog.js | 154 +++++++++++++++--- 2 files changed, 137 insertions(+), 28 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 848a8cc7ba..710f333322 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -775,7 +775,8 @@ module.exports = React.createClass({ const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const defered = q.defer(); mxIdPromise = defered.promise; - Modal.createDialog(SetMxIdDialog, { + const close = Modal.createDialog(SetMxIdDialog, { + homeserverUrl: cli.getHomeserverUrl(), onFinished: (submitted, credentials) => { if (!submitted) { defered.reject(); @@ -783,8 +784,12 @@ module.exports = React.createClass({ } this.props.onRegistered(credentials); defered.resolve(); - } - }); + }, + onDifferentServerClicked: (ev) => { + dis.dispatch({action: 'start_registration'}); + close(); + }, + }).close; } mxIdPromise.then(() => { diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index d139a4ae3b..445b7eb77f 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -19,6 +19,11 @@ import q from 'q'; import React from 'react'; import sdk from '../../../index'; import MatrixClientPeg from '../../../MatrixClientPeg'; +import classnames from 'classnames'; + +// The amount of time to wait for further changes to the input username before +// sending a request to the server +const USERNAME_CHECK_DEBOUNCE_MS = 2000; /** * Prompt the user to set a display name. @@ -33,9 +38,20 @@ export default React.createClass({ getInitialState: function() { return { - username : '', + // The entered username + username: '', + // Indicate ongoing work on the username + usernameBusy: false, + // Indicate error with username + usernameError: '', + // Assume the homeserver supports username checking until "M_UNRECOGNIZED" + usernameCheckSupport: true, + + // Whether the auth UI is currently being used doingUIAuth: false, - } + // Indicate error with auth + authError: '', + }; }, componentDidMount: function() { @@ -46,7 +62,28 @@ export default React.createClass({ onValueChange: function(ev) { this.setState({ - username: ev.target.value + username: ev.target.value, + usernameBusy: true, + usernameError: '', + }, () => { + if (!this.state.username || !this.state.usernameCheckSupport) { + this.setState({ + usernameBusy: false, + }); + return; + } + + // Debounce the username check to limit number of requests sent + if (this._usernameCheckTimeout) { + clearTimeout(this._usernameCheckTimeout); + } + this._usernameCheckTimeout = setTimeout(() => { + this._doUsernameCheck().finally(() => { + this.setState({ + usernameBusy: false, + }); + }); + }, USERNAME_CHECK_DEBOUNCE_MS); }); }, @@ -56,6 +93,40 @@ export default React.createClass({ }); }, + _doUsernameCheck: function() { + // Check if username is available + return this._matrixClient.isUsernameAvailable(this.state.username).then( + (isAvailable) => { + if (isAvailable) { + this.setState({usernameError: ''}); + } + }, + (err) => { + // Indicate whether the homeserver supports username checking + const newState = { + usernameCheckSupport: err.errcode !== "M_UNRECOGNIZED", + }; + switch (err.errcode) { + case "M_USER_IN_USE": + newState.usernameError = 'Username not available'; + break; + case "M_INVALID_USERNAME": + newState.usernameError = 'Username invalid: ' + err.message; + break; + case "M_UNRECOGNIZED": + // This homeserver doesn't support username checking, assume it's + // fine and rely on the error appearing in registration step. + newState.usernameError = ''; + break; + default: + newState.usernameError = 'An error occurred' + err.message; + break; + } + this.setState(newState); + }, + ); + }, + _generatePassword: function() { return Math.random().toString(36).slice(2); }, @@ -63,8 +134,9 @@ export default React.createClass({ _makeRegisterRequest: function(auth) { // Not upgrading - changing mxids const guestAccessToken = null; - this._generatedPassword = this._generatePassword(); - + if (!this._generatedPassword) { + this._generatedPassword = this._generatePassword(); + } return this._matrixClient.register( this.state.username, this._generatedPassword, @@ -79,10 +151,9 @@ export default React.createClass({ this.setState({ doingUIAuth: false, }); - console.info('Auth Finsihed', arguments); if (!success) { - this.setState({ errorText : response.message }); + this.setState({ authError: response.message }); return; } @@ -104,6 +175,7 @@ export default React.createClass({ const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); const InteractiveAuth = sdk.getComponent('structures.InteractiveAuth'); const Spinner = sdk.getComponent('elements.Spinner'); + let auth; if (this.state.doingUIAuth) { auth = ; } + const inputClasses = classnames({ + "mx_SetMxIdDialog_input": true, + "error": Boolean(this.state.usernameError), + }); + + let usernameIndicator = null; + let usernameBusyIndicator = null; + if (this.state.usernameBusy) { + usernameBusyIndicator = ; + } else { + const usernameAvailable = this.state.username && + this.state.usernameCheckSupport && !this.state.usernameError; + const usernameIndicatorClasses = classnames({ + "error": Boolean(this.state.usernameError), + "success": usernameAvailable, + }); + usernameIndicator =

+ { usernameAvailable ? 'Username available' : this.state.usernameError } +
; + } + + let authErrorIndicator = null; + if (this.state.authError) { + authErrorIndicator =
+ { this.state.authError } +
; + } + const canContinue = this.state.username && + !this.state.usernameError && + !this.state.usernameBusy; + return (
-

- Beyond this point you're going to need to pick a username - your - unique identifier in Riot. -

-

- - You can't change your username, but you can always choose how you - appear to other people in Riot by changing your display name. - -

- - { auth } -
- { this.state.errorText } +
+ + { usernameBusyIndicator }
+ { usernameIndicator } +

+ This will be your account name on + the {this.props.homeserverUrl} homeserver, + or you can pick a  + + different server + . +

+ { auth } + { authErrorIndicator }
From 6257bfcd87828610159d07c29cf7c277aafcd640 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 10 May 2017 14:28:48 +0100 Subject: [PATCH 011/275] Add prop type for onDifferentServerClicked --- src/components/views/dialogs/SetMxIdDialog.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 445b7eb77f..86b5fccbc2 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -34,6 +34,8 @@ export default React.createClass({ displayName: 'SetMxIdDialog', propTypes: { onFinished: React.PropTypes.func.isRequired, + // Called when the user requests to register with a different homeserver + onDifferentServerClicked: React.PropTypes.func.isRequired, }, getInitialState: function() { From 6326a95b39f335d3da3b66bb48a53a9d456c208c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 11 May 2017 17:04:11 +0100 Subject: [PATCH 012/275] Prevent ROUs from creating new chats/new rooms Spawn a SetMxIdDialog instead and do nothing. --- src/components/structures/MatrixChat.js | 38 +++++++++++++++++++++---- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 0c8c60ba5c..eeab10b326 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -502,21 +502,23 @@ module.exports = React.createClass({ this.notifyNewScreen('settings'); break; case 'view_create_room': - //this._setPage(PageTypes.CreateRoom); - //this.notifyNewScreen('new'); + if (MatrixClientPeg.get().isGuest()) { + dis.dispatch({action: 'view_set_mxid'}); + break; + } var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog"); Modal.createDialog(TextInputDialog, { title: "Create Room", description: "Room name (optional)", button: "Create Room", - onFinished: (should_create, name) => { - if (should_create) { + onFinished: (shouldCreate, name) => { + if (shouldCreate) { const createOpts = {}; if (name) createOpts.name = name; createRoom({createOpts}).done(); } - } + }, }); break; case 'view_room_directory': @@ -531,6 +533,9 @@ module.exports = React.createClass({ this._setPage(PageTypes.HomePage); this.notifyNewScreen('home'); break; + case 'view_set_mxid': + this._setMxId(); + break; case 'view_create_chat': this._createChat(); break; @@ -679,8 +684,29 @@ module.exports = React.createClass({ }); }, + _setMxId: function() { + const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); + const close = Modal.createDialog(SetMxIdDialog, { + homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(), + onFinished: (submitted, credentials) => { + if (!submitted) { + return; + } + this.onRegistered(credentials); + }, + onDifferentServerClicked: (ev) => { + dis.dispatch({action: 'start_registration'}); + close(); + }, + }).close; + }, + _createChat: function() { - var ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog"); + if (MatrixClientPeg.get().isGuest()) { + dis.dispatch({action: 'view_set_mxid'}); + return; + } + const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog"); Modal.createDialog(ChatInviteDialog, { title: "Start a new chat", }); From cfa108a28c80a8f68311c00cdc8183b5be3b750c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 11 May 2017 17:07:03 +0100 Subject: [PATCH 013/275] No need to dispatch, just call setMxId --- src/components/structures/MatrixChat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index eeab10b326..d63bf897c9 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -703,7 +703,7 @@ module.exports = React.createClass({ _createChat: function() { if (MatrixClientPeg.get().isGuest()) { - dis.dispatch({action: 'view_set_mxid'}); + this._setMxId(); return; } const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog"); From 8725ef38639573bf6f0b36d6ee6cac305e5ef70a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 11 May 2017 17:47:45 +0100 Subject: [PATCH 014/275] Remove "Current Password" input if mx_pass exists If the user is PWLU, do not show "Current Password" field in ChangePassword and when setting a new password, use the cached password. --- src/components/structures/LoggedInView.js | 1 + src/components/structures/MatrixChat.js | 9 ++++- src/components/structures/UserSettings.js | 5 +++ .../views/settings/ChangePassword.js | 38 +++++++++++-------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 4001227355..2afb43bf47 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -216,6 +216,7 @@ export default React.createClass({ enableLabs={this.props.config.enableLabs} referralBaseUrl={this.props.config.referralBaseUrl} teamToken={this.props.teamToken} + cachedPassword={this.props.cachedPassword} />; if (!this.props.collapse_rhs) right_panel = ; break; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 0c8c60ba5c..b3fa6e9040 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -590,6 +590,12 @@ module.exports = React.createClass({ payload.releaseNotes ); break; + case 'password_changed': + this.setState({ + userHasGeneratedPassword: false, + }); + localStorage.removeItem("mx_pass"); + break; } }, @@ -1176,7 +1182,8 @@ module.exports = React.createClass({ onUserSettingsClose={this.onUserSettingsClose} onRegistered={this.onRegistered} teamToken={this._teamToken} - userHasGeneratedPassword={this.state.userHasGeneratedPassword} + cachedPassword={this.state.userHasGeneratedPassword ? + localStorage.getItem('mx_pass') : null} {...this.props} {...this.state} /> diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 46dce8bd2e..fa0fcadf0e 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -139,6 +139,9 @@ module.exports = React.createClass({ // Team token for the referral link. If falsy, the referral section will // not appear teamToken: React.PropTypes.string, + + // the user is a PWLU (/w password stashed in localStorage 'mx_pass') + cachedPassword: React.PropTypes.string, }, getDefaultProps: function() { @@ -331,6 +334,7 @@ module.exports = React.createClass({ receive push notifications on other devices until you log back in to them.`, }); + dis.dispatch({action: 'password_changed'}); }, onUpgradeClicked: function() { @@ -894,6 +898,7 @@ module.exports = React.createClass({ rowLabelClassName="mx_UserSettings_profileLabelCell" rowInputClassName="mx_UserSettings_profileInputCell" buttonClassName="mx_UserSettings_button mx_UserSettings_changePasswordButton" + cachedPassword={this.props.cachedPassword} onError={this.onPasswordChangeError} onFinished={this.onPasswordChanged} /> ); diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index 20ce45e5dd..bbb5d14219 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -31,7 +31,10 @@ module.exports = React.createClass({ rowClassName: React.PropTypes.string, rowLabelClassName: React.PropTypes.string, rowInputClassName: React.PropTypes.string, - buttonClassName: React.PropTypes.string + buttonClassName: React.PropTypes.string, + + // user is a PWLU (/w password stashed in localStorage 'mx_pass') + cachedPassword: React.PropTypes.string, }, Phases: { @@ -121,10 +124,10 @@ module.exports = React.createClass({ matrixClient: MatrixClientPeg.get(), } ); - }, + }, onClickChange: function() { - var old_password = this.refs.old_input.value; + var old_password = this.props.cachedPassword || this.refs.old_input.value; var new_password = this.refs.new_input.value; var confirm_password = this.refs.confirm_input.value; var err = this.props.onCheckPassword( @@ -139,23 +142,28 @@ module.exports = React.createClass({ }, render: function() { - var rowClassName = this.props.rowClassName; - var rowLabelClassName = this.props.rowLabelClassName; - var rowInputClassName = this.props.rowInputClassName; - var buttonClassName = this.props.buttonClassName; + const rowClassName = this.props.rowClassName; + const rowLabelClassName = this.props.rowLabelClassName; + const rowInputClassName = this.props.rowInputClassName; + const buttonClassName = this.props.buttonClassName; + + let currentPassword = null; + if (!this.props.cachedPassword) { + currentPassword =
+
+ +
+
+ +
+
; + } switch (this.state.phase) { case this.Phases.Edit: return (
-
-
- -
-
- -
-
+ { currentPassword }
From 1176573f39b3c2531887e36a2d6c79b3136c5ab5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 12 May 2017 12:02:45 +0100 Subject: [PATCH 015/275] Implement SessionStore This wraps session-related state into a basic flux store. The localStorage item 'mx_pass' is the only thing managed by this store for now but it could easily be extended to track other items (like the teamToken which is passed around through props a lot) --- src/Lifecycle.js | 12 ++-- src/components/structures/LoggedInView.js | 3 +- src/components/structures/MatrixChat.js | 29 +++++---- src/components/structures/UserSettings.js | 4 -- .../views/settings/ChangePassword.js | 25 ++++++-- src/stores/SessionStore.js | 63 +++++++++++++++++++ 6 files changed, 104 insertions(+), 32 deletions(-) create mode 100644 src/stores/SessionStore.js diff --git a/src/Lifecycle.js b/src/Lifecycle.js index a7a06401da..decb544b3c 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -289,7 +289,6 @@ export function setLoggedIn(credentials) { // Resolves by default let teamPromise = Promise.resolve(null); - let isPasswordStored = false; // persist the session if (localStorage) { @@ -312,8 +311,11 @@ export function setLoggedIn(credentials) { // The user registered as a PWLU (PassWord-Less User), the generated password // is cached here such that the user can change it at a later time. if (credentials.password) { - localStorage.setItem("mx_pass", credentials.password); - isPasswordStored = true; + // Update SessionStore + dis.dispatch({ + action: 'cached_password', + cachedPassword: credentials.password, + }); } console.log("Session persisted for %s", credentials.userId); @@ -339,10 +341,10 @@ export function setLoggedIn(credentials) { MatrixClientPeg.replaceUsingCreds(credentials); teamPromise.then((teamToken) => { - dis.dispatch({action: 'on_logged_in', teamToken: teamToken, isPasswordStored}); + dis.dispatch({action: 'on_logged_in', teamToken: teamToken}); }, (err) => { console.warn("Failed to get team token on login", err); - dis.dispatch({action: 'on_logged_in', teamToken: null, isPasswordStored}); + dis.dispatch({action: 'on_logged_in', teamToken: null}); }); startMatrixClient(); diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 2afb43bf47..0851c01a18 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -51,7 +51,7 @@ export default React.createClass({ // Has the user generated a password that is stored in local storage? // (are they a PWLU?) - userHasGeneratedPassword: React.PropTypes.boolean, + userHasGeneratedPassword: React.PropTypes.bool, // and lots and lots of other stuff. }, @@ -216,7 +216,6 @@ export default React.createClass({ enableLabs={this.props.config.enableLabs} referralBaseUrl={this.props.config.referralBaseUrl} teamToken={this.props.teamToken} - cachedPassword={this.props.cachedPassword} />; if (!this.props.collapse_rhs) right_panel = ; break; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b3fa6e9040..d7e24c019a 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -40,6 +40,8 @@ var PageTypes = require('../../PageTypes'); var createRoom = require("../../createRoom"); import * as UDEHandler from '../../UnknownDeviceErrorHandler'; +import getSessionStore from '../../stores/SessionStore'; + module.exports = React.createClass({ displayName: 'MatrixChat', @@ -139,8 +141,7 @@ module.exports = React.createClass({ register_is_url: null, register_id_sid: null, - // Initially, use localStorage as source of truth - userHasGeneratedPassword: localStorage && localStorage.getItem('mx_pass'), + userHasGeneratedPassword: false, }; return s; }, @@ -249,6 +250,10 @@ module.exports = React.createClass({ register_hs_url: paramHs, }); } + + this._sessionStore = getSessionStore(); + this._sessionStore.on('update', this._setStateFromSessionStore); + this._setStateFromSessionStore(); }, componentDidMount: function() { @@ -590,12 +595,6 @@ module.exports = React.createClass({ payload.releaseNotes ); break; - case 'password_changed': - this.setState({ - userHasGeneratedPassword: false, - }); - localStorage.removeItem("mx_pass"); - break; } }, @@ -765,15 +764,11 @@ module.exports = React.createClass({ /** * Called when a new logged in session has started */ - _onLoggedIn: function(teamToken, isPasswordStored) { + _onLoggedIn: function(teamToken) { this.setState({ guestCreds: null, loggedIn: true, loggingIn: false, - // isPasswordStored only true when ROU sets a username and becomes PWLU. - // (the password was randomly generated and stored in localStorage). - userHasGeneratedPassword: - this.state.userHasGeneratedPassword || isPasswordStored, }); if (teamToken) { @@ -902,6 +897,12 @@ module.exports = React.createClass({ }); }, + _setStateFromSessionStore() { + this.setState({ + userHasGeneratedPassword: Boolean(this._sessionStore.getCachedPassword()), + }); + }, + onFocus: function(ev) { dis.dispatch({action: 'focus_composer'}); }, @@ -1182,8 +1183,6 @@ module.exports = React.createClass({ onUserSettingsClose={this.onUserSettingsClose} onRegistered={this.onRegistered} teamToken={this._teamToken} - cachedPassword={this.state.userHasGeneratedPassword ? - localStorage.getItem('mx_pass') : null} {...this.props} {...this.state} /> diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index fa0fcadf0e..d352d5cae8 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -139,9 +139,6 @@ module.exports = React.createClass({ // Team token for the referral link. If falsy, the referral section will // not appear teamToken: React.PropTypes.string, - - // the user is a PWLU (/w password stashed in localStorage 'mx_pass') - cachedPassword: React.PropTypes.string, }, getDefaultProps: function() { @@ -898,7 +895,6 @@ module.exports = React.createClass({ rowLabelClassName="mx_UserSettings_profileLabelCell" rowInputClassName="mx_UserSettings_profileInputCell" buttonClassName="mx_UserSettings_button mx_UserSettings_changePasswordButton" - cachedPassword={this.props.cachedPassword} onError={this.onPasswordChangeError} onFinished={this.onPasswordChanged} /> ); diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index bbb5d14219..3a1c777cd9 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -22,6 +22,8 @@ var Modal = require("../../../Modal"); var sdk = require("../../../index"); import AccessibleButton from '../elements/AccessibleButton'; +import getSessionStore from '../../../stores/SessionStore'; + module.exports = React.createClass({ displayName: 'ChangePassword', propTypes: { @@ -32,9 +34,6 @@ module.exports = React.createClass({ rowLabelClassName: React.PropTypes.string, rowInputClassName: React.PropTypes.string, buttonClassName: React.PropTypes.string, - - // user is a PWLU (/w password stashed in localStorage 'mx_pass') - cachedPassword: React.PropTypes.string, }, Phases: { @@ -63,10 +62,24 @@ module.exports = React.createClass({ getInitialState: function() { return { - phase: this.Phases.Edit + phase: this.Phases.Edit, + cachedPassword: null, }; }, + componentWillMount: function() { + this.sessionStore = getSessionStore(); + this.sessionStore.on('update', this.setStateFromSessionStore); + + this.setStateFromSessionStore(); + }, + + setStateFromSessionStore: function() { + this.setState({ + cachedPassword: this.sessionStore.getCachedPassword(), + }); + }, + changePassword: function(old_password, new_password) { var cli = MatrixClientPeg.get(); @@ -127,7 +140,7 @@ module.exports = React.createClass({ }, onClickChange: function() { - var old_password = this.props.cachedPassword || this.refs.old_input.value; + var old_password = this.state.cachedPassword || this.refs.old_input.value; var new_password = this.refs.new_input.value; var confirm_password = this.refs.confirm_input.value; var err = this.props.onCheckPassword( @@ -148,7 +161,7 @@ module.exports = React.createClass({ const buttonClassName = this.props.buttonClassName; let currentPassword = null; - if (!this.props.cachedPassword) { + if (!this.state.cachedPassword) { currentPassword =
diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js new file mode 100644 index 0000000000..1c19494e23 --- /dev/null +++ b/src/stores/SessionStore.js @@ -0,0 +1,63 @@ +import dis from '../dispatcher'; +import EventEmitter from 'events'; + +/** + * A class for storing application state to do with the session. This is a simple flux + * store that listens for actions and updates its state accordingly, informing any + * listeners (views) of state changes via the 'update' event. + */ +function SessionStore() { + // Initialise state + this._state = { + cachedPassword: localStorage.getItem('mx_pass'), + }; + + dis.register(this._onAction.bind(this)); +} + +// Inherit from EventEmitter +SessionStore.prototype = EventEmitter.prototype; + +SessionStore.prototype._update = function() { + // Persist state to localStorage + if (this._state.cachedPassword) { + localStorage.setItem('mx_pass', this._state.cachedPassword); + } else { + localStorage.removeItem('mx_pass', this._state.cachedPassword); + } + + this.emit('update'); +}; + +SessionStore.prototype._setState = function(newState) { + this._state = Object.assign(this._state, newState); + this._update(); +}; + +SessionStore.prototype._onAction = function(payload) { + switch (payload.action) { + case 'cached_password': + this._setState({ + cachedPassword: payload.cachedPassword, + }); + break; + case 'password_changed': + this._setState({ + cachedPassword: null, + }); + break; + } +}; + +SessionStore.prototype.getCachedPassword = function() { + return this._state.cachedPassword; +}; + +// Export singleton getter +let singletonSessionStore = null; +export default function getSessionStore() { + if (!singletonSessionStore) { + singletonSessionStore = new SessionStore(); + } + return singletonSessionStore; +} From 5c8187dc8f9804e01ad4d01af27d07801caebc2c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 12 May 2017 15:47:37 +0100 Subject: [PATCH 016/275] Explicitly pass thru userHasGeneratedPassword --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index d7e24c019a..5975d6cf5f 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1183,6 +1183,7 @@ module.exports = React.createClass({ onUserSettingsClose={this.onUserSettingsClose} onRegistered={this.onRegistered} teamToken={this._teamToken} + userHasGeneratedPassword={this.state.userHasGeneratedPassword} {...this.props} {...this.state} /> From 6ffe7ef9b2aabcb41c10043fe762c529f80617dc Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 12 May 2017 15:50:01 +0100 Subject: [PATCH 017/275] Use same singleton impl as MatrixClientPeg for SessionStore --- src/stores/SessionStore.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 1c19494e23..7be3885fde 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -55,9 +55,7 @@ SessionStore.prototype.getCachedPassword = function() { // Export singleton getter let singletonSessionStore = null; -export default function getSessionStore() { - if (!singletonSessionStore) { - singletonSessionStore = new SessionStore(); - } - return singletonSessionStore; +if (!singletonSessionStore) { + singletonSessionStore = new SessionStore(); } +module.exports = singletonSessionStore; From 536724e7c5b6f55352311ad2856e95ece60ab5cb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 12 May 2017 15:58:44 +0100 Subject: [PATCH 018/275] ES6 SessionStore --- src/components/structures/MatrixChat.js | 4 +- .../views/settings/ChangePassword.js | 4 +- src/stores/SessionStore.js | 89 ++++++++++--------- 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 5975d6cf5f..b8b3f51422 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -40,7 +40,7 @@ var PageTypes = require('../../PageTypes'); var createRoom = require("../../createRoom"); import * as UDEHandler from '../../UnknownDeviceErrorHandler'; -import getSessionStore from '../../stores/SessionStore'; +import sessionStore from '../../stores/SessionStore'; module.exports = React.createClass({ displayName: 'MatrixChat', @@ -251,7 +251,7 @@ module.exports = React.createClass({ }); } - this._sessionStore = getSessionStore(); + this._sessionStore = sessionStore; this._sessionStore.on('update', this._setStateFromSessionStore); this._setStateFromSessionStore(); }, diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index 3a1c777cd9..c20bc47152 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -22,7 +22,7 @@ var Modal = require("../../../Modal"); var sdk = require("../../../index"); import AccessibleButton from '../elements/AccessibleButton'; -import getSessionStore from '../../../stores/SessionStore'; +import sessionStore from '../../../stores/SessionStore'; module.exports = React.createClass({ displayName: 'ChangePassword', @@ -68,7 +68,7 @@ module.exports = React.createClass({ }, componentWillMount: function() { - this.sessionStore = getSessionStore(); + this.sessionStore = sessionStore; this.sessionStore.on('update', this.setStateFromSessionStore); this.setStateFromSessionStore(); diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 7be3885fde..bf605d7f07 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -6,53 +6,54 @@ import EventEmitter from 'events'; * store that listens for actions and updates its state accordingly, informing any * listeners (views) of state changes via the 'update' event. */ -function SessionStore() { - // Initialise state - this._state = { - cachedPassword: localStorage.getItem('mx_pass'), - }; +class SessionStore extends EventEmitter { + constructor() { + super(); - dis.register(this._onAction.bind(this)); + // Initialise state + this._state = { + cachedPassword: localStorage.getItem('mx_pass'), + }; + + dis.register(this._onAction.bind(this)); + } + + _update() { + // Persist state to localStorage + if (this._state.cachedPassword) { + localStorage.setItem('mx_pass', this._state.cachedPassword); + } else { + localStorage.removeItem('mx_pass', this._state.cachedPassword); + } + + this.emit('update'); + } + + _setState(newState) { + this._state = Object.assign(this._state, newState); + this._update(); + } + + _onAction(payload) { + switch (payload.action) { + case 'cached_password': + this._setState({ + cachedPassword: payload.cachedPassword, + }); + break; + case 'password_changed': + this._setState({ + cachedPassword: null, + }); + break; + } + } + + getCachedPassword() { + return this._state.cachedPassword; + } } -// Inherit from EventEmitter -SessionStore.prototype = EventEmitter.prototype; - -SessionStore.prototype._update = function() { - // Persist state to localStorage - if (this._state.cachedPassword) { - localStorage.setItem('mx_pass', this._state.cachedPassword); - } else { - localStorage.removeItem('mx_pass', this._state.cachedPassword); - } - - this.emit('update'); -}; - -SessionStore.prototype._setState = function(newState) { - this._state = Object.assign(this._state, newState); - this._update(); -}; - -SessionStore.prototype._onAction = function(payload) { - switch (payload.action) { - case 'cached_password': - this._setState({ - cachedPassword: payload.cachedPassword, - }); - break; - case 'password_changed': - this._setState({ - cachedPassword: null, - }); - break; - } -}; - -SessionStore.prototype.getCachedPassword = function() { - return this._state.cachedPassword; -}; - // Export singleton getter let singletonSessionStore = null; if (!singletonSessionStore) { From 2b4c87aca6eac0d32081624093a1f25fd0683621 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 12 May 2017 16:02:38 +0100 Subject: [PATCH 019/275] Remove useless comment --- src/stores/SessionStore.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index bf605d7f07..d3370d2df3 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -54,7 +54,6 @@ class SessionStore extends EventEmitter { } } -// Export singleton getter let singletonSessionStore = null; if (!singletonSessionStore) { singletonSessionStore = new SessionStore(); From 683f1b8a1ac2cd108d61413414431776d3f10517 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 12 May 2017 17:39:38 +0100 Subject: [PATCH 020/275] Invite the welcome user after registration if configured This will shift focus to the welcome user DM. We probably don't want to do this for teams, but I shall leave that for another PR that fixes teams WRT to new-guest-access. --- src/components/structures/MatrixChat.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index d63bf897c9..ee3c601146 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -578,7 +578,7 @@ module.exports = React.createClass({ this.setState({loggingIn: true}); break; case 'on_logged_in': - this._onLoggedIn(payload.teamToken, payload.isPasswordStored); + this._onLoggedIn(payload.teamToken); break; case 'on_logged_out': this._onLoggedOut(); @@ -801,8 +801,12 @@ module.exports = React.createClass({ this._teamToken = teamToken; dis.dispatch({action: 'view_home_page'}); } else if (this._is_registered) { + if (this.props.config.welcomeUserId) { + createRoom({dmUserId: this.props.config.welcomeUserId}); + return; + } // The user has just logged in after registering - dis.dispatch({action: 'view_user_settings'}); + dis.dispatch({action: 'view_room_directory'}); } else { this._showScreenAfterLogin(); } From da3cb0ee48aaea420a31fd9e060e159dfd7e910f Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 15 May 2017 14:52:19 +0100 Subject: [PATCH 021/275] SessionStore extends flux.Store --- src/components/structures/MatrixChat.js | 2 +- .../views/settings/ChangePassword.js | 10 ++++----- src/stores/SessionStore.js | 21 ++++++++++++------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b8b3f51422..4556148986 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -252,7 +252,7 @@ module.exports = React.createClass({ } this._sessionStore = sessionStore; - this._sessionStore.on('update', this._setStateFromSessionStore); + this._sessionStore.addListener(this._setStateFromSessionStore); this._setStateFromSessionStore(); }, diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index c20bc47152..4d8373bc52 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -68,15 +68,15 @@ module.exports = React.createClass({ }, componentWillMount: function() { - this.sessionStore = sessionStore; - this.sessionStore.on('update', this.setStateFromSessionStore); + this._sessionStore = sessionStore; + this._sessionStore.addListener(this._setStateFromSessionStore); - this.setStateFromSessionStore(); + this._setStateFromSessionStore(); }, - setStateFromSessionStore: function() { + _setStateFromSessionStore: function() { this.setState({ - cachedPassword: this.sessionStore.getCachedPassword(), + cachedPassword: this._sessionStore.getCachedPassword(), }); }, diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index d3370d2df3..1570f58688 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -1,21 +1,26 @@ import dis from '../dispatcher'; -import EventEmitter from 'events'; +import {Store} from 'flux/utils'; /** * A class for storing application state to do with the session. This is a simple flux * store that listens for actions and updates its state accordingly, informing any - * listeners (views) of state changes via the 'update' event. + * listeners (views) of state changes. + * + * Usage: + * ``` + * sessionStore.addListener(() => { + * this.setState({ cachedPassword: sessionStore.getCachedPassword() }) + * }) + * ``` */ -class SessionStore extends EventEmitter { +class SessionStore extends Store { constructor() { - super(); + super(dis); // Initialise state this._state = { cachedPassword: localStorage.getItem('mx_pass'), }; - - dis.register(this._onAction.bind(this)); } _update() { @@ -26,7 +31,7 @@ class SessionStore extends EventEmitter { localStorage.removeItem('mx_pass', this._state.cachedPassword); } - this.emit('update'); + this.__emitChange(); } _setState(newState) { @@ -34,7 +39,7 @@ class SessionStore extends EventEmitter { this._update(); } - _onAction(payload) { + __onDispatch(payload) { switch (payload.action) { case 'cached_password': this._setState({ From f73cf772fb83db136cd44fd3cc40e50aec83905e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 15 May 2017 14:56:05 +0100 Subject: [PATCH 022/275] Move sessionStore ref from MatrixChat to LoggedInView MatrixChat didn't actually use the sessionStore, so this is one less prop to pass. --- src/components/structures/LoggedInView.js | 17 ++++++++++++----- src/components/structures/MatrixChat.js | 12 ------------ 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 0851c01a18..240a3499a2 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -23,6 +23,7 @@ import Notifier from '../../Notifier'; import PageTypes from '../../PageTypes'; import sdk from '../../index'; import dis from '../../dispatcher'; +import sessionStore from '../../stores/SessionStore'; /** * This is what our MatrixChat shows when we are logged in. The precise view is @@ -49,10 +50,6 @@ export default React.createClass({ teamToken: React.PropTypes.string, - // Has the user generated a password that is stored in local storage? - // (are they a PWLU?) - userHasGeneratedPassword: React.PropTypes.bool, - // and lots and lots of other stuff. }, @@ -80,6 +77,10 @@ export default React.createClass({ this._scrollStateMap = {}; document.addEventListener('keydown', this._onKeyDown); + + this._sessionStore = sessionStore; + this._sessionStore.addListener(this._setStateFromSessionStore); + this._setStateFromSessionStore(); }, componentWillUnmount: function() { @@ -97,6 +98,12 @@ export default React.createClass({ return this.refs.roomView.canResetTimeline(); }, + _setStateFromSessionStore() { + this.setState({ + userHasGeneratedPassword: Boolean(this._sessionStore.getCachedPassword()), + }); + }, + _onKeyDown: function(ev) { /* // Remove this for now as ctrl+alt = alt-gr so this breaks keyboards which rely on alt-gr for numbers @@ -257,7 +264,7 @@ export default React.createClass({ />; } else if (this.props.matrixClient.isGuest()) { topBar = ; - } else if (this.props.userHasGeneratedPassword) { + } else if (this.state.userHasGeneratedPassword) { topBar = ; } else if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { topBar = ; diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 4556148986..45b4d07055 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -40,8 +40,6 @@ var PageTypes = require('../../PageTypes'); var createRoom = require("../../createRoom"); import * as UDEHandler from '../../UnknownDeviceErrorHandler'; -import sessionStore from '../../stores/SessionStore'; - module.exports = React.createClass({ displayName: 'MatrixChat', @@ -250,10 +248,6 @@ module.exports = React.createClass({ register_hs_url: paramHs, }); } - - this._sessionStore = sessionStore; - this._sessionStore.addListener(this._setStateFromSessionStore); - this._setStateFromSessionStore(); }, componentDidMount: function() { @@ -897,12 +891,6 @@ module.exports = React.createClass({ }); }, - _setStateFromSessionStore() { - this.setState({ - userHasGeneratedPassword: Boolean(this._sessionStore.getCachedPassword()), - }); - }, - onFocus: function(ev) { dis.dispatch({action: 'focus_composer'}); }, From eb0041d21ab603e3b0d1f0474068ded68f09dba7 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 15 May 2017 17:03:54 +0100 Subject: [PATCH 023/275] Remove redundant state --- src/components/structures/MatrixChat.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 45b4d07055..c5b58c3285 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -138,8 +138,6 @@ module.exports = React.createClass({ register_hs_url: null, register_is_url: null, register_id_sid: null, - - userHasGeneratedPassword: false, }; return s; }, @@ -1171,7 +1169,6 @@ module.exports = React.createClass({ onUserSettingsClose={this.onUserSettingsClose} onRegistered={this.onRegistered} teamToken={this._teamToken} - userHasGeneratedPassword={this.state.userHasGeneratedPassword} {...this.props} {...this.state} /> From 269fd511300bc001604d70a02e96e6e8bef1c283 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 15 May 2017 17:17:32 +0100 Subject: [PATCH 024/275] Remove SessionStore listener on unmount --- src/components/structures/LoggedInView.js | 7 ++++++- src/components/views/settings/ChangePassword.js | 10 +++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 240a3499a2..bbbf6dff0e 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -79,12 +79,17 @@ export default React.createClass({ document.addEventListener('keydown', this._onKeyDown); this._sessionStore = sessionStore; - this._sessionStore.addListener(this._setStateFromSessionStore); + this._removeSSListener = this._sessionStore.addListener( + this._setStateFromSessionStore, + ).remove; this._setStateFromSessionStore(); }, componentWillUnmount: function() { document.removeEventListener('keydown', this._onKeyDown); + if (this._removeSSListener) { + this._removeSSListener(); + } }, getScrollStateForRoom: function(roomId) { diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index 4d8373bc52..07680818df 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -69,11 +69,19 @@ module.exports = React.createClass({ componentWillMount: function() { this._sessionStore = sessionStore; - this._sessionStore.addListener(this._setStateFromSessionStore); + this._removeSSListener = this._sessionStore.addListener( + this._setStateFromSessionStore, + ).remove; this._setStateFromSessionStore(); }, + componentWillUnmount: function() { + if (this._removeSSListener) { + this._removeSSListener(); + } + }, + _setStateFromSessionStore: function() { this.setState({ cachedPassword: this._sessionStore.getCachedPassword(), From f199f3599ea8231a3d68ef1dd1b6adeac28e7329 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 15 May 2017 17:31:26 +0100 Subject: [PATCH 025/275] Replace NeedToRegisterDialog /w SetMxIdDialog This uses MatrixChat's `view_set_mxid` --- src/components/structures/RoomView.js | 12 +-- src/components/structures/UserSettings.js | 12 +-- .../views/dialogs/ChatInviteDialog.js | 6 +- .../views/dialogs/NeedToRegisterDialog.js | 78 ------------------- .../views/room_settings/ColorSettings.js | 8 +- src/components/views/rooms/MemberInfo.js | 6 +- src/components/views/rooms/MessageComposer.js | 6 +- src/createRoom.js | 7 +- 8 files changed, 11 insertions(+), 124 deletions(-) delete mode 100644 src/components/views/dialogs/NeedToRegisterDialog.js diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 3cbe76b289..92049bb113 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -869,11 +869,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().isGuest() ) ) { - var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Failed to join the room", - description: "This room is private or inaccessible to guests. You may be able to join if you register." - }); + dis.dispatch({action: 'view_set_mxid'}); } else { var msg = error.message ? error.message : JSON.stringify(error); var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); @@ -933,11 +929,7 @@ module.exports = React.createClass({ uploadFile: function(file) { if (MatrixClientPeg.get().isGuest()) { - var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Guest users can't upload files. Please register to upload." - }); + dis.dispatch({action: 'view_set_mxid'}); return; } diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 46dce8bd2e..96c60d7cd8 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -245,11 +245,7 @@ module.exports = React.createClass({ onAvatarPickerClick: function(ev) { if (MatrixClientPeg.get().isGuest()) { - const NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Guests can't set avatars. Please register.", - }); + dis.dispatch({action: 'view_set_mxid'}); return; } @@ -700,11 +696,7 @@ module.exports = React.createClass({ onChange={(e) => { if (MatrixClientPeg.get().isGuest()) { e.target.checked = false; - const NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Guests can't use labs features. Please register.", - }); + dis.dispatch({action: 'view_set_mxid'}); return; } diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index 7ba503099a..06c029287f 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -284,11 +284,7 @@ module.exports = React.createClass({ _startChat: function(addrs) { if (MatrixClientPeg.get().isGuest()) { - var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Guest users can't invite users. Please register." - }); + dis.dispatch({action: 'view_set_mxid'}); return; } diff --git a/src/components/views/dialogs/NeedToRegisterDialog.js b/src/components/views/dialogs/NeedToRegisterDialog.js deleted file mode 100644 index f4df5913d5..0000000000 --- a/src/components/views/dialogs/NeedToRegisterDialog.js +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/* - * Usage: - * Modal.createDialog(NeedToRegisterDialog, { - * title: "some text", (default: "Registration required") - * description: "some more text", - * onFinished: someFunction, - * }); - */ - -import React from 'react'; -import dis from '../../../dispatcher'; -import sdk from '../../../index'; - -module.exports = React.createClass({ - displayName: 'NeedToRegisterDialog', - propTypes: { - title: React.PropTypes.string, - description: React.PropTypes.oneOfType([ - React.PropTypes.element, - React.PropTypes.string, - ]), - onFinished: React.PropTypes.func.isRequired, - }, - - getDefaultProps: function() { - return { - title: "Registration required", - description: "A registered account is required for this action", - }; - }, - - onRegisterClicked: function() { - dis.dispatch({ - action: "start_upgrade_registration", - }); - if (this.props.onFinished) { - this.props.onFinished(); - } - }, - - render: function() { - const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); - return ( - -
- {this.props.description} -
-
- - -
-
- ); - }, -}); diff --git a/src/components/views/room_settings/ColorSettings.js b/src/components/views/room_settings/ColorSettings.js index 6a455d9c3c..5fc845a541 100644 --- a/src/components/views/room_settings/ColorSettings.js +++ b/src/components/views/room_settings/ColorSettings.js @@ -21,6 +21,8 @@ var Tinter = require('../../../Tinter'); var MatrixClientPeg = require("../../../MatrixClientPeg"); var Modal = require("../../../Modal"); +import dis from '../../../dispatcher'; + var ROOM_COLORS = [ // magic room default values courtesy of Ribot ["#76cfa6", "#eaf5f0"], @@ -86,11 +88,7 @@ module.exports = React.createClass({ } ).catch(function(err) { if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') { - var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Saving room color settings is only available to registered users" - }); + dis.dispatch({action: 'view_set_mxid'}); } }); } diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 1a9a8d5e0f..1f286e9e12 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -374,11 +374,7 @@ module.exports = WithMatrixClient(React.createClass({ console.log("Mod toggle success"); }, function(err) { if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') { - var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "This action cannot be performed by a guest user. Please register to be able to do this." - }); + dis.dispatch({action: 'view_set_mxid'}); } else { console.error("Toggle moderator error:" + err); Modal.createDialog(ErrorDialog, { diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 0ee3c2082d..df7d0c3640 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -90,11 +90,7 @@ export default class MessageComposer extends React.Component { onUploadClick(ev) { if (MatrixClientPeg.get().isGuest()) { - let NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Guest users can't upload files. Please register to upload.", - }); + dis.dispatch({action: 'view_set_mxid'}); return; } diff --git a/src/createRoom.js b/src/createRoom.js index 674fe23d28..72f4016502 100644 --- a/src/createRoom.js +++ b/src/createRoom.js @@ -41,12 +41,7 @@ function createRoom(opts) { const client = MatrixClientPeg.get(); if (client.isGuest()) { - setTimeout(()=>{ - Modal.createDialog(NeedToRegisterDialog, { - title: "Please Register", - description: "Guest users can't create new rooms. Please register to create room and start a chat." - }); - }, 0); + dis.dispatch({action: 'view_set_mxid'}); return q(null); } From 93ecdc90a9741dbdc5ad9aa6e70ed4d3743217fb Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 11:45:01 +0100 Subject: [PATCH 026/275] Make confirmation optional on ChangePassword Add option to disable password change confirmation (`disabledConfirmation`). Style fixes, use `
+ onClick={this.onClickChange} + element="button"> Change Password
From f7e6a996c5e6720eadfc7065ef81e9e959d774d3 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 11:51:09 +0100 Subject: [PATCH 027/275] Add proptype --- src/components/views/settings/ChangePassword.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index a5e695a1ff..e8a07fd225 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -31,7 +31,8 @@ module.exports = React.createClass({ rowClassName: React.PropTypes.string, rowLabelClassName: React.PropTypes.string, rowInputClassName: React.PropTypes.string, - buttonClassName: React.PropTypes.string + buttonClassName: React.PropTypes.string, + disableConfirmation: React.PropTypes.bool, }, Phases: { From eb36e979c2591f252fb007bc2460b9d1b2dcbd6a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 11:52:51 +0100 Subject: [PATCH 028/275] Reference store token, call .remove on it on unmount --- src/components/structures/LoggedInView.js | 8 ++++---- src/components/views/settings/ChangePassword.js | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index bbbf6dff0e..a64ae0a25c 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -79,16 +79,16 @@ export default React.createClass({ document.addEventListener('keydown', this._onKeyDown); this._sessionStore = sessionStore; - this._removeSSListener = this._sessionStore.addListener( + this._sessionStoreToken = this._sessionStore.addListener( this._setStateFromSessionStore, - ).remove; + ); this._setStateFromSessionStore(); }, componentWillUnmount: function() { document.removeEventListener('keydown', this._onKeyDown); - if (this._removeSSListener) { - this._removeSSListener(); + if (this._sessionStoreToken) { + this._sessionStoreToken.remove(); } }, diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index 07680818df..e3845390de 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -69,16 +69,16 @@ module.exports = React.createClass({ componentWillMount: function() { this._sessionStore = sessionStore; - this._removeSSListener = this._sessionStore.addListener( + this._sessionStoreToken = this._sessionStore.addListener( this._setStateFromSessionStore, - ).remove; + ); this._setStateFromSessionStore(); }, componentWillUnmount: function() { - if (this._removeSSListener) { - this._removeSSListener(); + if (this._sessionStoreToken) { + this._sessionStoreToken.remove(); } }, From 633c6b39f6a1dd98613898287499ec7696a95099 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 11:58:37 +0100 Subject: [PATCH 029/275] Add comment to Lifecycle --- src/Lifecycle.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index decb544b3c..20d5836dae 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -185,6 +185,14 @@ function _registerAsGuest(hsUrl, isUrl, defaultDeviceDisplayName) { // returns a promise which resolves to true if a session is found in // localstorage +// +// N.B. Lifecycle.js should not maintain any further localStorage state, we +// are moving towards using SessionStore to keep track of state related +// to the current session (which is typically backed by localStorage). +// +// The plan is to gradually move the localStorage access done here into +// SessionStore to avoid bugs where the view becomes out-of-sync with +// localStorage (e.g. teamToken, isGuest etc.) function _restoreFromLocalStorage() { if (!localStorage) { return q(false); From 5a3c32044e764bb56ec4d4bf1dd413e4bd9bd2f9 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 12:45:14 +0100 Subject: [PATCH 030/275] disableConfirmation -> confirm --- src/components/views/settings/ChangePassword.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index e8a07fd225..257e0ac056 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -32,7 +32,7 @@ module.exports = React.createClass({ rowLabelClassName: React.PropTypes.string, rowInputClassName: React.PropTypes.string, buttonClassName: React.PropTypes.string, - disableConfirmation: React.PropTypes.bool, + confirm: React.PropTypes.bool, }, Phases: { @@ -55,7 +55,8 @@ module.exports = React.createClass({ error: "Passwords can't be empty" }; } - } + }, + confirm: true, }; }, @@ -68,7 +69,7 @@ module.exports = React.createClass({ changePassword: function(oldPassword, newPassword) { const cli = MatrixClientPeg.get(); - if (this.props.disableConfirmation) { + if (!this.props.confirm) { this._changePassword(cli, oldPassword, newPassword); return; } From 2c5fb01f03b9ac5e98f2e488c1a6acb26c7e5d22 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 14:13:22 +0100 Subject: [PATCH 031/275] Fix bugs introduced by dodgy merge --- src/components/views/settings/ChangePassword.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index 422761601d..601b774932 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -90,7 +90,7 @@ module.exports = React.createClass({ }); }, - changePassword: function(old_password, new_password) { + changePassword: function(oldPassword, newPassword) { const cli = MatrixClientPeg.get(); if (!this.props.confirm) { @@ -158,7 +158,7 @@ module.exports = React.createClass({ }, onClickChange: function() { - const oldPassword = this.refs.old_input.value; + const oldPassword = this.state.cachedPassword || this.refs.old_input.value; const newPassword = this.refs.new_input.value; const confirmPassword = this.refs.confirm_input.value; const err = this.props.onCheckPassword( From ca907f42dc980e97c764b2f535dd26e8615ec066 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 16 May 2017 14:24:24 +0100 Subject: [PATCH 032/275] Fix redundant getComponent --- src/createRoom.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/createRoom.js b/src/createRoom.js index 72f4016502..e18f9cf032 100644 --- a/src/createRoom.js +++ b/src/createRoom.js @@ -36,7 +36,6 @@ function createRoom(opts) { opts = opts || {}; const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - const NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); const Loader = sdk.getComponent("elements.Spinner"); const client = MatrixClientPeg.get(); From e1089574ae02bee6036cb745513c026381558f43 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 17 May 2017 09:46:17 +0100 Subject: [PATCH 033/275] Write some tests for the RTS UI Add tests that make assertions about the UI during registration when registration is done with a user recognised as a team member (by the mock rtsClient). --- .../structures/login/Registration.js | 3 +- .../structures/login/Registration-test.js | 105 ++++++++++++++++++ .../views/login/RegistrationForm-test.js | 86 ++++++++++++++ test/test-utils.js | 14 +++ 4 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 test/components/structures/login/Registration-test.js create mode 100644 test/components/views/login/RegistrationForm-test.js diff --git a/src/components/structures/login/Registration.js b/src/components/structures/login/Registration.js index 5501a39b58..5eecfa5ff6 100644 --- a/src/components/structures/login/Registration.js +++ b/src/components/structures/login/Registration.js @@ -98,7 +98,7 @@ module.exports = React.createClass({ this.props.teamServerConfig.teamServerURL && !this._rtsClient ) { - this._rtsClient = new RtsClient(this.props.teamServerConfig.teamServerURL); + this._rtsClient = this.props.rtsClient || new RtsClient(this.props.teamServerConfig.teamServerURL); this.setState({ teamServerBusy: true, @@ -221,7 +221,6 @@ module.exports = React.createClass({ } trackPromise.then((teamToken) => { - console.info('Team token promise',teamToken); this.props.onLoggedIn({ userId: response.user_id, deviceId: response.device_id, diff --git a/test/components/structures/login/Registration-test.js b/test/components/structures/login/Registration-test.js new file mode 100644 index 0000000000..b4b54a6315 --- /dev/null +++ b/test/components/structures/login/Registration-test.js @@ -0,0 +1,105 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const React = require('react'); +const ReactDOM = require('react-dom'); +const ReactTestUtils = require('react-addons-test-utils'); +const expect = require('expect'); + +const testUtils = require('test-utils'); + +const sdk = require('matrix-react-sdk'); +const Registration = sdk.getComponent('structures.login.Registration'); + +let rtsClient; +let client; + +const TEAM_CONFIG = { + supportEmail: 'support@some.domain', + teamServerURL: 'http://someteamserver.bla', +}; + +const CREDENTIALS = {userId: '@me:here'}; +const MOCK_REG_RESPONSE = { + user_id: CREDENTIALS.userId, + device_id: 'mydevice', + access_token: '2234569864534231', +}; + +describe('Registration', function() { + beforeEach(function() { + testUtils.beforeEach(this); + client = testUtils.createTestClient(); + client.credentials = CREDENTIALS; + + // Mock an RTS client that supports one team and naively returns team tokens when + // tracking by mapping email SIDs to team tokens. This is fine because we only + // want to assert the client behaviour such that a user recognised by the + // rtsClient (which would normally talk to the RTS server) as a team member is + // correctly logged in as one (and other such assertions). + rtsClient = testUtils.createTestRtsClient( + { + 'myawesometeam123': { + name: 'Team Awesome', + domain: 'team.awesome.net', + }, + }, + {'someEmailSid1234': 'myawesometeam123'}, + ); + }); + + it('should track a referral following successful registration of a team member', function(done) { + const expectedCreds = { + userId: MOCK_REG_RESPONSE.user_id, + deviceId: MOCK_REG_RESPONSE.device_id, + homeserverUrl: client.getHomeserverUrl(), + identityServerUrl: client.getIdentityServerUrl(), + accessToken: MOCK_REG_RESPONSE.access_token, + }; + const onLoggedIn = function(creds, teamToken) { + expect(creds).toEqual(expectedCreds); + expect(teamToken).toBe('myawesometeam123'); + done(); + }; + + const res = ReactTestUtils.renderIntoDocument( + , + ); + + res._onUIAuthFinished(true, MOCK_REG_RESPONSE, {emailSid: 'someEmailSid1234'}); + }); + + it('should NOT track a referral following successful registration of a non-team member', function(done) { + const onLoggedIn = expect.createSpy().andCall(function(creds, teamToken) { + expect(teamToken).toNotExist(); + done(); + }); + + const res = ReactTestUtils.renderIntoDocument( + , + ); + + res._onUIAuthFinished(true, MOCK_REG_RESPONSE, {emailSid: 'someOtherEmailSid11'}); + }); +}); diff --git a/test/components/views/login/RegistrationForm-test.js b/test/components/views/login/RegistrationForm-test.js new file mode 100644 index 0000000000..81db5b487b --- /dev/null +++ b/test/components/views/login/RegistrationForm-test.js @@ -0,0 +1,86 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const React = require('react'); +const ReactDOM = require("react-dom"); +const ReactTestUtils = require('react-addons-test-utils'); +const expect = require('expect'); + +const testUtils = require('test-utils'); + +const sdk = require('matrix-react-sdk'); +const RegistrationForm = sdk.getComponent('views.login.RegistrationForm'); + +const TEAM_CONFIG = { + supportEmail: "support@some.domain", + teams: [ + { name: "The Team Org.", domain: "team.ac.uk" }, + { name: "The Super Team", domain: "superteam.ac.uk" }, + ], +}; + +function doInputEmail(inputEmail, onTeamSelected) { + const res = ReactTestUtils.renderIntoDocument( + , + ); + + const teamInput = res.refs.email; + teamInput.value = inputEmail; + + ReactTestUtils.Simulate.change(teamInput); + ReactTestUtils.Simulate.blur(teamInput); + + return res; +} + +function expectTeamSelectedFromEmailInput(inputEmail, expectedTeam) { + const onTeamSelected = expect.createSpy(); + doInputEmail(inputEmail, onTeamSelected); + + expect(onTeamSelected).toHaveBeenCalledWith(expectedTeam); +} + +function expectSupportFromEmailInput(inputEmail, isSupportShown) { + const onTeamSelected = expect.createSpy(); + const res = doInputEmail(inputEmail, onTeamSelected); + + expect(res.state.showSupportEmail).toBe(isSupportShown); +} + +describe('RegistrationForm', function() { + beforeEach(function() { + testUtils.beforeEach(this); + }); + + it('should select a team when a team email is entered', function() { + expectTeamSelectedFromEmailInput("member@team.ac.uk", TEAM_CONFIG.teams[0]); + }); + + it('should not select a team when an unrecognised team email is entered', function() { + expectTeamSelectedFromEmailInput("member@someunknownteam.ac.uk", null); + }); + + it('should show support when an unrecognised team email is entered', function() { + expectSupportFromEmailInput("member@someunknownteam.ac.uk", true); + }); + + it('should NOT show support when an unrecognised non-team email is entered', function() { + expectSupportFromEmailInput("someone@yahoo.com", false); + }); +}); diff --git a/test/test-utils.js b/test/test-utils.js index 9f404f98eb..2c866d345c 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -137,6 +137,20 @@ export function createTestClient() { }; } +export function createTestRtsClient(teamMap, sidMap) { + return { + getTeamsConfig() { + return q(Object.keys(teamMap).map((token) => teamMap[token])); + }, + trackReferral(referrer, emailSid, clientSecret) { + return q({team_token: sidMap[emailSid]}); + }, + getTeam(teamToken) { + return q(teamMap[teamToken]); + }, + }; +} + /** * Create an Event. * @param {Object} opts Values for the event. From 96c3bf56f8dbbbcd242bee9292ef87085414c63e Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 19 May 2017 09:43:56 +0100 Subject: [PATCH 034/275] Implement warm-fuzzy success dialog for SetMxIdDialog --- src/components/views/dialogs/SetMxIdDialog.js | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 86b5fccbc2..d9d07d517b 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -53,6 +53,9 @@ export default React.createClass({ doingUIAuth: false, // Indicate error with auth authError: '', + + // Indicate success of setting mxid + success: false, }; }, @@ -95,6 +98,10 @@ export default React.createClass({ }); }, + onSuccessContinue: function() { + this.props.onFinished(true, this._registeredCreds); + }, + _doUsernameCheck: function() { // Check if username is available return this._matrixClient.isUsernameAvailable(this.state.username).then( @@ -162,7 +169,7 @@ export default React.createClass({ // XXX Implement RTS /register here const teamToken = null; - this.props.onFinished(true, { + this._registeredCreds = { userId: response.user_id, deviceId: response.device_id, homeserverUrl: this._matrixClient.getHomeserverUrl(), @@ -170,6 +177,11 @@ export default React.createClass({ accessToken: response.access_token, password: this._generatedPassword, teamToken: teamToken, + }; + + // Before continuing, show a warm-fuzzy success and only submit onSuccessContinue + this.setState({ + success: true, }); }, @@ -219,6 +231,30 @@ export default React.createClass({ !this.state.usernameError && !this.state.usernameBusy; + if (this.state.success) { + return ( + +
+

+ You have successfully + picked { this.state.username } as your + username and you now have access to the full + set of features on Riot. +

+
+
+ +
+
+ ); + } + return ( Date: Mon, 22 May 2017 14:46:49 +0100 Subject: [PATCH 035/275] Add prop to toggle whether new password input is autoFocused --- src/components/views/settings/ChangePassword.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index 601b774932..bfc9ac264e 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -35,6 +35,8 @@ module.exports = React.createClass({ rowInputClassName: React.PropTypes.string, buttonClassName: React.PropTypes.string, confirm: React.PropTypes.bool, + // Whether to autoFocus the new password input + autoFocusNewPasswordInput: React.PropTypes.bool, }, Phases: { @@ -199,7 +201,7 @@ module.exports = React.createClass({
- +
From b0a824c94190c317f6c18a238d6f3e04727d58a6 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Mon, 22 May 2017 16:28:23 +0100 Subject: [PATCH 036/275] Remove double declaration of TextInputDialog --- src/components/structures/MatrixChat.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 85c12979f6..59ce1b622d 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -439,7 +439,6 @@ module.exports = React.createClass({ break; } - var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog"); Modal.createDialog(TextInputDialog, { title: "Create Room", description: "Room name (optional)", From 298c5e4df32d87b0707b9f71ff489e12b800fe15 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 24 May 2017 16:56:13 +0100 Subject: [PATCH 037/275] Implement a store for RoomView This allows for a truely flux-y way of storing the currently viewed room, making some callbacks (like onRoomIdResolved) redundant and making sure that the currently viewed room (ID) is only stored in one place as opposed to the previous many places. This was required for the `join_room` action which can be dispatched to join the currently viewed room. Another change was to introduce `LifeCycleStore` which is a start at encorporating state related to the lifecycle of the app into a flux store. Currently it only contains an action which will be dispatched when the sync state has become PREPARED. This was necessary to do a deferred dispatch of `join_room` following the registration of a PWLU (PassWord-Less User). The following actions are introduced: - RoomViewStore: - `view_room`: dispatch to change the currently viewed room ID - `join_room`: dispatch to join the currently viewed room - LifecycleStore: - `do_after_sync_prepared`: dispatch to store an action which will be dispatched when `sync_state` is dispatched with `state = 'PREPARED'` - MatrixChat: - `sync_state`: dispatched when the sync state changes. Ideally there'd be a SyncStateStore that emitted an `update` upon receiving this, but for now the `LifecycleStore` will listen for `sync_state` directly. --- src/components/structures/LoggedInView.js | 5 +- src/components/structures/MatrixChat.js | 38 ++-- src/components/structures/RoomView.js | 212 ++++++------------ src/components/views/dialogs/SetMxIdDialog.js | 1 + src/createRoom.js | 15 +- src/stores/LifecycleStore.js | 73 ++++++ src/stores/RoomViewStore.js | 145 ++++++++++++ src/stores/SessionStore.js | 15 ++ test/components/structures/RoomView-test.js | 67 ------ test/stores/RoomViewStore-test.js | 56 +++++ test/test-utils.js | 13 +- 11 files changed, 399 insertions(+), 241 deletions(-) create mode 100644 src/stores/LifecycleStore.js create mode 100644 src/stores/RoomViewStore.js delete mode 100644 test/components/structures/RoomView-test.js create mode 100644 test/stores/RoomViewStore-test.js diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index e559a21e1a..df24fbb33b 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -40,7 +40,6 @@ export default React.createClass({ propTypes: { matrixClient: React.PropTypes.instanceOf(Matrix.MatrixClient).isRequired, page_type: React.PropTypes.string.isRequired, - onRoomIdResolved: React.PropTypes.func, onRoomCreated: React.PropTypes.func, onUserSettingsClose: React.PropTypes.func, @@ -190,16 +189,14 @@ export default React.createClass({ case PageTypes.RoomView: page_element = { modal.close(); - if (this.currentRoomId === roomId) { + if (this.state.currentRoomId === roomId) { dis.dispatch({action: 'view_next_room'}); } }, (err) => { @@ -807,8 +808,12 @@ module.exports = React.createClass({ this._teamToken = teamToken; dis.dispatch({action: 'view_home_page'}); } else if (this._is_registered) { + this._is_registered = false; if (this.props.config.welcomeUserId) { - createRoom({dmUserId: this.props.config.welcomeUserId}); + createRoom({ + dmUserId: this.props.config.welcomeUserId, + andView: false, + }); return; } // The user has just logged in after registering @@ -853,7 +858,6 @@ module.exports = React.createClass({ ready: false, collapse_lhs: false, collapse_rhs: false, - currentRoomAlias: null, currentRoomId: null, page_type: PageTypes.RoomDirectory, }); @@ -891,6 +895,7 @@ module.exports = React.createClass({ }); cli.on('sync', function(state, prevState) { + dis.dispatch({action: 'sync_state', prevState, state}); self.updateStatusIndicator(state, prevState); if (state === "SYNCING" && prevState === "SYNCING") { return; @@ -1102,6 +1107,8 @@ module.exports = React.createClass({ }, onRegistered: function(credentials, teamToken) { + // XXX: These both should be in state or ideally store(s) because we risk not + // rendering the most up-to-date view of state otherwise. // teamToken may not be truthy this._teamToken = teamToken; this._is_registered = true; @@ -1163,13 +1170,6 @@ module.exports = React.createClass({ } }, - onRoomIdResolved: function(roomId) { - // It's the RoomView's resposibility to look up room aliases, but we need the - // ID to pass into things like the Member List, so the Room View tells us when - // its done that resolution so we can display things that take a room ID. - this.setState({currentRoomId: roomId}); - }, - _makeRegistrationUrl: function(params) { if (this.props.startingFragmentQueryParams.referrer) { params.referrer = this.props.startingFragmentQueryParams.referrer; @@ -1211,10 +1211,10 @@ module.exports = React.createClass({ const LoggedInView = sdk.getComponent('structures.LoggedInView'); return ( { this.forceUpdate(); - } + }, }); - if (this.props.roomAddress[0] == '#') { - // we always look up the alias from the directory server: - // we want the room that the given alias is pointing to - // right now. We may have joined that alias before but there's - // no guarantee the alias hasn't subsequently been remapped. - MatrixClientPeg.get().getRoomIdForAlias(this.props.roomAddress).done((result) => { - if (this.props.onRoomIdResolved) { - this.props.onRoomIdResolved(result.room_id); - } - var room = MatrixClientPeg.get().getRoom(result.room_id); - this.setState({ - room: room, - roomId: result.room_id, - roomLoading: !room, - unsentMessageError: this._getUnsentMessageError(room), - }, this._onHaveRoom); - }, (err) => { - this.setState({ - roomLoading: false, - roomLoadError: err, - }); - }); - } else { - var room = MatrixClientPeg.get().getRoom(this.props.roomAddress); - this.setState({ - roomId: this.props.roomAddress, - room: room, - roomLoading: !room, - unsentMessageError: this._getUnsentMessageError(room), - }, this._onHaveRoom); + // Start listening for RoomViewStore updates + RoomViewStore.addListener(this._onRoomViewStoreUpdate); + this._onRoomViewStoreUpdate(true); + }, + + _onRoomViewStoreUpdate: function(initial) { + if (this.unmounted) { + return; } + this.setState({ + roomId: RoomViewStore.getRoomId(), + roomAlias: RoomViewStore.getRoomAlias(), + joining: RoomViewStore.isJoining(), + joinError: RoomViewStore.getJoinError(), + }, () => { + this._onHaveRoom(); + this.onRoom(MatrixClientPeg.get().getRoom(this.state.roomId)); + }); }, _onHaveRoom: function() { @@ -224,17 +202,17 @@ module.exports = React.createClass({ // NB. We peek if we are not in the room, although if we try to peek into // a room in which we have a member event (ie. we've left) synapse will just // send us the same data as we get in the sync (ie. the last events we saw). - var user_is_in_room = null; - if (this.state.room) { - user_is_in_room = this.state.room.hasMembershipState( - MatrixClientPeg.get().credentials.userId, 'join' + const room = MatrixClientPeg.get().getRoom(this.state.roomId); + let isUserJoined = null; + if (room) { + isUserJoined = room.hasMembershipState( + MatrixClientPeg.get().credentials.userId, 'join', ); - this._updateAutoComplete(); - this.tabComplete.loadEntries(this.state.room); + this._updateAutoComplete(room); + this.tabComplete.loadEntries(room); } - - if (!user_is_in_room && this.state.roomId) { + if (!isUserJoined && !this.state.joining && this.state.roomId) { if (this.props.autoJoin) { this.onJoinButtonClicked(); } else if (this.state.roomId) { @@ -260,9 +238,12 @@ module.exports = React.createClass({ } }).done(); } - } else if (user_is_in_room) { + } else if (isUserJoined) { MatrixClientPeg.get().stopPeeking(); - this._onRoomLoaded(this.state.room); + this.setState({ + unsentMessageError: this._getUnsentMessageError(room), + }); + this._onRoomLoaded(room); } }, @@ -299,10 +280,6 @@ module.exports = React.createClass({ }, componentWillReceiveProps: function(newProps) { - if (newProps.roomAddress != this.props.roomAddress) { - throw new Error("changing room on a RoomView is not supported"); - } - if (newProps.eventId != this.props.eventId) { // when we change focussed event id, hide the search results. this.setState({searchResults: null}); @@ -523,7 +500,7 @@ module.exports = React.createClass({ this._updatePreviewUrlVisibility(room); }, - _warnAboutEncryption: function (room) { + _warnAboutEncryption: function(room) { if (!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) { return; } @@ -604,20 +581,14 @@ module.exports = React.createClass({ }, onRoom: function(room) { - // This event is fired when the room is 'stored' by the JS SDK, which - // means it's now a fully-fledged room object ready to be used, so - // set it in our state and start using it (ie. init the timeline) - // This will happen if we start off viewing a room we're not joined, - // then join it whilst RoomView is looking at that room. - if (!this.state.room && room.roomId == this._joiningRoomId) { - this._joiningRoomId = undefined; - this.setState({ - room: room, - joining: false, - }); - - this._onRoomLoaded(room); + if (!room || room.roomId !== this.state.roomId) { + return; } + this.setState({ + room: room, + }, () => { + this._onRoomLoaded(room); + }); }, updateTint: function() { @@ -683,7 +654,7 @@ module.exports = React.createClass({ // refresh the tab complete list this.tabComplete.loadEntries(this.state.room); - this._updateAutoComplete(); + this._updateAutoComplete(this.state.room); // if we are now a member of the room, where we were not before, that // means we have finished joining a room we were previously peeking @@ -778,37 +749,43 @@ module.exports = React.createClass({ }, onJoinButtonClicked: function(ev) { - var self = this; - - var cli = MatrixClientPeg.get(); - var mxIdPromise = q(); + const cli = MatrixClientPeg.get(); // If the user is a ROU, allow them to transition to a PWLU if (cli && cli.isGuest()) { + // Join this room once the user has registered and logged in + dis.dispatch({ + action: 'do_after_sync_prepared', + deferred_action: { + action: 'join_room', + room_id: this.state.roomId, + }, + }); + const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); - const defered = q.defer(); - mxIdPromise = defered.promise; const close = Modal.createDialog(SetMxIdDialog, { homeserverUrl: cli.getHomeserverUrl(), onFinished: (submitted, credentials) => { - if (!submitted) { - defered.reject(); - return; + if (submitted) { + this.props.onRegistered(credentials); } - this.props.onRegistered(credentials); - defered.resolve(); }, onDifferentServerClicked: (ev) => { dis.dispatch({action: 'start_registration'}); close(); }, }).close; + return; } - mxIdPromise.then(() => { - this.setState({ - joining: true + q().then(() => { + const signUrl = this.props.thirdPartyInvite ? + this.props.thirdPartyInvite.inviteSignUrl : undefined; + dis.dispatch({ + action: 'join_room', + opts: { inviteSignUrl: signUrl }, }); + // if this is an invite and has the 'direct' hint set, mark it as a DM room now. if (this.state.room) { const me = this.state.room.getMember(MatrixClientPeg.get().credentials.userId); @@ -820,65 +797,8 @@ module.exports = React.createClass({ } } } - return q(); - }).then(() => { - var sign_url = this.props.thirdPartyInvite ? this.props.thirdPartyInvite.inviteSignUrl : undefined; - return MatrixClientPeg.get().joinRoom(this.props.roomAddress, - { inviteSignUrl: sign_url } ); - }).then(function(resp) { - var roomId = resp.roomId; - - // It is possible that there is no Room yet if state hasn't come down - // from /sync - joinRoom will resolve when the HTTP request to join succeeds, - // NOT when it comes down /sync. If there is no room, we'll keep the - // joining flag set until we see it. - - // We'll need to initialise the timeline when joining, but due to - // the above, we can't do it here: we do it in onRoom instead, - // once we have a useable room object. - var room = MatrixClientPeg.get().getRoom(roomId); - if (!room) { - // wait for the room to turn up in onRoom. - self._joiningRoomId = roomId; - } else { - // we've got a valid room, but that might also just mean that - // it was peekable (so we had one before anyway). If we are - // not yet a member of the room, we will need to wait for that - // to happen, in onRoomStateMember. - var me = MatrixClientPeg.get().credentials.userId; - self.setState({ - joining: !room.hasMembershipState(me, "join"), - room: room - }); - } - }).catch(function(error) { - self.setState({ - joining: false, - joinError: error - }); - - if (!error) return; - - // https://matrix.org/jira/browse/SYN-659 - // Need specific error message if joining a room is refused because the user is a guest and guest access is not allowed - if ( - error.errcode == 'M_GUEST_ACCESS_FORBIDDEN' || - ( - error.errcode == 'M_FORBIDDEN' && - MatrixClientPeg.get().isGuest() - ) - ) { - dis.dispatch({action: 'view_set_mxid'}); - } else { - var msg = error.message ? error.message : JSON.stringify(error); - var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - Modal.createDialog(ErrorDialog, { - title: "Failed to join room", - description: msg - }); - } - }).done(); + }); }, onMessageListScroll: function(ev) { @@ -1451,9 +1371,9 @@ module.exports = React.createClass({ } }, - _updateAutoComplete: function() { + _updateAutoComplete: function(room) { const myUserId = MatrixClientPeg.get().credentials.userId; - const members = this.state.room.getJoinedMembers().filter(function(member) { + const members = room.getJoinedMembers().filter(function(member) { if (member.userId !== myUserId) return true; }); UserProvider.getInstance().setUserList(members); @@ -1491,7 +1411,7 @@ module.exports = React.createClass({ // We have no room object for this room, only the ID. // We've got to this room by following a link, possibly a third party invite. - var room_alias = this.props.roomAddress[0] == '#' ? this.props.roomAddress : null; + var room_alias = this.state.room_alias; return (
{ + * this.setState({ cachedPassword: lifecycleStore.getCachedPassword() }) + * }) + * ``` + */ +class LifecycleStore extends Store { + constructor() { + super(dis); + + // Initialise state + this._state = { + deferred_action: null, + }; + } + + _setState(newState) { + this._state = Object.assign(this._state, newState); + this.__emitChange(); + } + + __onDispatch(payload) { + switch (payload.action) { + case 'do_after_sync_prepared': + this._setState({ + deferred_action: payload.deferred_action, + }); + break; + case 'sync_state': + if (payload.state !== 'PREPARED') { + break; + } + console.warn(this._state); + if (!this._state.deferred_action) break; + const deferredAction = Object.assign({}, this._state.deferred_action); + this._setState({ + deferred_action: null, + }); + dis.dispatch(deferredAction); + break; + } + } +} + +let singletonLifecycleStore = null; +if (!singletonLifecycleStore) { + singletonLifecycleStore = new LifecycleStore(); +} +module.exports = singletonLifecycleStore; diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js new file mode 100644 index 0000000000..fe57079859 --- /dev/null +++ b/src/stores/RoomViewStore.js @@ -0,0 +1,145 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +import dis from '../dispatcher'; +import {Store} from 'flux/utils'; +import MatrixClientPeg from '../MatrixClientPeg'; + +const INITIAL_STATE = { + // Whether we're joining the currently viewed room + joining: false, + // Any error occurred during joining + joinError: null, + // The room ID of the room + roomId: null, + // The room alias of the room (or null if not originally specified in view_room) + roomAlias: null, + // Whether the current room is loading + roomLoading: false, + // Any error that has occurred during loading + roomLoadError: null, +}; + +/** + * A class for storing application state for RoomView. This is the RoomView's interface +* with a subset of the js-sdk. + * ``` + */ +class RoomViewStore extends Store { + constructor() { + super(dis); + + // Initialise state + this._state = INITIAL_STATE; + } + + _setState(newState) { + this._state = Object.assign(this._state, newState); + this.__emitChange(); + } + + __onDispatch(payload) { + switch (payload.action) { + // view_room: + // - room_alias: '#somealias:matrix.org' + // - room_id: '!roomid123:matrix.org' + case 'view_room': + this._viewRoom(payload); + break; + + // join_room: + // - opts: options for joinRoom + case 'join_room': + this._joinRoom(payload); + break; + } + } + + _viewRoom(payload) { + const address = payload.room_alias || payload.room_id; + if (address[0] == '#') { + this._setState({ + roomLoading: true, + }); + MatrixClientPeg.get().getRoomIdForAlias(address).then( + (result) => { + this._setState({ + roomId: result.room_id, + roomAlias: address, + roomLoading: false, + roomLoadError: null, + }); + }, (err) => { + console.error(err); + this._setState({ + roomLoading: false, + roomLoadError: err, + }); + }); + } else { + this._setState({ + roomId: address, + }); + } + } + + _joinRoom(payload) { + this._setState({ + joining: true, + }); + MatrixClientPeg.get().joinRoom(this._state.roomId, payload.opts).then( + () => { + this._setState({ + joining: false, + }); + }, (err) => { + this._setState({ + joining: false, + joinError: err, + }); + }); + } + + reset() { + this._state = Object.assign({}, INITIAL_STATE); + } + + getRoomId() { + return this._state.roomId; + } + + getRoomAlias() { + return this._state.roomAlias; + } + + isRoomLoading() { + return this._state.roomLoading; + } + + isJoining() { + return this._state.joining; + } + + getJoinError() { + return this._state.joinError; + } + +} + +let singletonRoomViewStore = null; +if (!singletonRoomViewStore) { + singletonRoomViewStore = new RoomViewStore(); +} +module.exports = singletonRoomViewStore; diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 1570f58688..2fd35ce40a 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -1,3 +1,18 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ import dis from '../dispatcher'; import {Store} from 'flux/utils'; diff --git a/test/components/structures/RoomView-test.js b/test/components/structures/RoomView-test.js deleted file mode 100644 index 8e7c8160b8..0000000000 --- a/test/components/structures/RoomView-test.js +++ /dev/null @@ -1,67 +0,0 @@ -var React = require('react'); -var expect = require('expect'); -var sinon = require('sinon'); -var ReactDOM = require("react-dom"); - -var sdk = require('matrix-react-sdk'); -var RoomView = sdk.getComponent('structures.RoomView'); -var peg = require('../../../src/MatrixClientPeg'); - -var test_utils = require('../../test-utils'); -var q = require('q'); - -var Skinner = require("../../../src/Skinner"); -var stubComponent = require('../../components/stub-component.js'); - -describe('RoomView', function () { - var sandbox; - var parentDiv; - - beforeEach(function() { - test_utils.beforeEach(this); - sandbox = test_utils.stubClient(); - parentDiv = document.createElement('div'); - - this.oldTimelinePanel = Skinner.getComponent('structures.TimelinePanel'); - this.oldRoomHeader = Skinner.getComponent('views.rooms.RoomHeader'); - Skinner.addComponent('structures.TimelinePanel', stubComponent()); - Skinner.addComponent('views.rooms.RoomHeader', stubComponent()); - - peg.get().credentials = { userId: "@test:example.com" }; - }); - - afterEach(function() { - sandbox.restore(); - - ReactDOM.unmountComponentAtNode(parentDiv); - - Skinner.addComponent('structures.TimelinePanel', this.oldTimelinePanel); - Skinner.addComponent('views.rooms.RoomHeader', this.oldRoomHeader); - }); - - it('resolves a room alias to a room id', function (done) { - peg.get().getRoomIdForAlias.returns(q({room_id: "!randomcharacters:aser.ver"})); - - function onRoomIdResolved(room_id) { - expect(room_id).toEqual("!randomcharacters:aser.ver"); - done(); - } - - ReactDOM.render(, parentDiv); - }); - - it('joins by alias if given an alias', function (done) { - peg.get().getRoomIdForAlias.returns(q({room_id: "!randomcharacters:aser.ver"})); - peg.get().getProfileInfo.returns(q({displayname: "foo"})); - var roomView = ReactDOM.render(, parentDiv); - - peg.get().joinRoom = function(x) { - expect(x).toEqual('#alias:ser.ver'); - done(); - }; - - process.nextTick(function() { - roomView.onJoinButtonClicked(); - }); - }); -}); diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js new file mode 100644 index 0000000000..7100dced19 --- /dev/null +++ b/test/stores/RoomViewStore-test.js @@ -0,0 +1,56 @@ +import expect from 'expect'; + +import dis from '../../src/dispatcher'; +import RoomViewStore from '../../src/stores/RoomViewStore'; + + +import peg from '../../src/MatrixClientPeg'; + +import * as testUtils from '../test-utils'; +import q from 'q'; + +const dispatch = testUtils.getDispatchForStore(RoomViewStore); + +describe('RoomViewStore', function() { + let sandbox; + + beforeEach(function() { + testUtils.beforeEach(this); + sandbox = testUtils.stubClient(); + peg.get().credentials = { userId: "@test:example.com" }; + + // Reset the state of the store + RoomViewStore.reset(); + }); + + afterEach(function() { + sandbox.restore(); + }); + + it('can be used to view a room by ID and join', function(done) { + peg.get().joinRoom = (roomId) => { + expect(roomId).toBe("!randomcharacters:aser.ver"); + done(); + }; + + dispatch({ action: 'view_room', room_id: '!randomcharacters:aser.ver' }); + dispatch({ action: 'join_room' }); + expect(RoomViewStore.isJoining()).toBe(true); + }); + + it('can be used to view a room by alias and join', function(done) { + peg.get().getRoomIdForAlias.returns(q({room_id: "!randomcharacters:aser.ver"})); + peg.get().joinRoom = (roomId) => { + expect(roomId).toBe("!randomcharacters:aser.ver"); + done(); + }; + + dispatch({ action: 'view_room', room_alias: '#somealias2:aser.ver' }); + + // Wait for the next event loop to allow for room alias resolution + setTimeout(() => { + dispatch({ action: 'join_room' }); + expect(RoomViewStore.isJoining()).toBe(true); + }, 0); + }); +}); diff --git a/test/test-utils.js b/test/test-utils.js index 2c866d345c..569208b355 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -4,7 +4,8 @@ import sinon from 'sinon'; import q from 'q'; import ReactTestUtils from 'react-addons-test-utils'; -import peg from '../src/MatrixClientPeg.js'; +import peg from '../src/MatrixClientPeg'; +import dis from '../src/dispatcher'; import jssdk from 'matrix-js-sdk'; const MatrixEvent = jssdk.MatrixEvent; @@ -290,3 +291,13 @@ export function mkStubRoom(roomId = null) { }, }; } + +export function getDispatchForStore(store) { + // Mock the dispatcher by gut-wrenching. Stores can only __emitChange whilst a + // dispatcher `_isDispatching` is true. + return (payload) => { + dis._isDispatching = true; + dis._callbacks[store._dispatchToken](payload); + dis._isDispatching = false; + }; +} From 5f36f797da0b1a195c31b0cf2f45f2d4b8dd5ae6 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 24 May 2017 17:55:36 +0100 Subject: [PATCH 038/275] Implement default welcome page and allow custom URL /w config This changes the default behaviour of displaying the room directory to instead displaying the default homepage. If specified, the config "welcomePageUrl" can be used to override the default '/home.html'. --- src/components/structures/LoggedInView.js | 4 ++-- src/components/structures/MatrixChat.js | 12 ++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index e559a21e1a..994e6504cf 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -240,7 +240,8 @@ export default React.createClass({ collapsedRhs={this.props.collapse_rhs} teamServerUrl={this.props.config.teamServerConfig.teamServerURL} teamToken={this.props.teamToken} - /> + homePageUrl={this.props.config.welcomePageUrl} + />; if (!this.props.collapse_rhs) right_panel = break; @@ -276,7 +277,6 @@ export default React.createClass({ selectedRoom={this.props.currentRoomId} collapsed={this.props.collapse_lhs || false} opacity={this.props.sideOpacity} - teamToken={this.props.teamToken} />
{page_element} diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 59ce1b622d..1882831bdc 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -457,10 +457,6 @@ module.exports = React.createClass({ this.notifyNewScreen('directory'); break; case 'view_home_page': - if (!this._teamToken) { - dis.dispatch({action: 'view_room_directory'}); - return; - } this._setPage(PageTypes.HomePage); this.notifyNewScreen('home'); break; @@ -812,7 +808,7 @@ module.exports = React.createClass({ return; } // The user has just logged in after registering - dis.dispatch({action: 'view_room_directory'}); + dis.dispatch({action: 'view_home_page'}); } else { this._showScreenAfterLogin(); } @@ -834,12 +830,8 @@ module.exports = React.createClass({ action: 'view_room', room_id: localStorage.getItem('mx_last_room_id'), }); - } else if (this._teamToken) { - // Team token might be set if we're a guest. - // Guests do not call _onLoggedIn with a teamToken - dis.dispatch({action: 'view_home_page'}); } else { - dis.dispatch({action: 'view_room_directory'}); + dis.dispatch({action: 'view_home_page'}); } }, From dcf2fb68aecd5d1eb64a649eac3bba1912dd96d3 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 24 May 2017 18:02:17 +0100 Subject: [PATCH 039/275] Remove console log --- src/stores/LifecycleStore.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/stores/LifecycleStore.js b/src/stores/LifecycleStore.js index 82a3b1b584..43e2de9d52 100644 --- a/src/stores/LifecycleStore.js +++ b/src/stores/LifecycleStore.js @@ -54,7 +54,6 @@ class LifecycleStore extends Store { if (payload.state !== 'PREPARED') { break; } - console.warn(this._state); if (!this._state.deferred_action) break; const deferredAction = Object.assign({}, this._state.deferred_action); this._setState({ From fffe425730688b1d1adea59c813bdc6b6b695273 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 24 May 2017 18:04:04 +0100 Subject: [PATCH 040/275] Add non-null RoomView key --- src/components/structures/LoggedInView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index df24fbb33b..5022b983f0 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -196,7 +196,7 @@ export default React.createClass({ oobData={this.props.roomOobData} highlightedEventId={this.props.highlightedEventId} eventPixelOffset={this.props.initialEventPixelOffset} - key={this.props.currentRoomId} + key={this.props.currentRoomId || 'roomview'} opacity={this.props.middleOpacity} collapsedRhs={this.props.collapse_rhs} ConferenceHandler={this.props.ConferenceHandler} From 8fc44a9b6661a6a5dab303d6895e903a10d2aed1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 09:30:57 +0100 Subject: [PATCH 041/275] Add comment to explain sync_state dispatch --- src/components/structures/MatrixChat.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b1814bc322..dca73a4601 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -895,6 +895,11 @@ module.exports = React.createClass({ }); cli.on('sync', function(state, prevState) { + // LifecycleStore and others cannot directly subscribe to matrix client for + // events because flux only allows store state changes during flux dispatches. + // So dispatch directly from here. Ideally we'd use a SyncStateStore that + // would do this dispatch and expose the sync state itself (by listening to + // its own dispatch). dis.dispatch({action: 'sync_state', prevState, state}); self.updateStatusIndicator(state, prevState); if (state === "SYNCING" && prevState === "SYNCING") { From c894c83fbe2eaced0c2313e405008c62e9484914 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 11:02:48 +0100 Subject: [PATCH 042/275] Remove GuestWarningBar --- src/components/structures/LoggedInView.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index d2ae57cda4..4687afbee1 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -178,7 +178,6 @@ export default React.createClass({ const RoomDirectory = sdk.getComponent('structures.RoomDirectory'); const HomePage = sdk.getComponent('structures.HomePage'); const MatrixToolbar = sdk.getComponent('globals.MatrixToolbar'); - const GuestWarningBar = sdk.getComponent('globals.GuestWarningBar'); const NewVersionBar = sdk.getComponent('globals.NewVersionBar'); const PasswordNagBar = sdk.getComponent('globals.PasswordNagBar'); @@ -253,8 +252,6 @@ export default React.createClass({ topBar = ; - } else if (this.props.matrixClient.isGuest()) { - topBar = ; } else if (this.state.userHasGeneratedPassword) { topBar = ; } else if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { From 5531f274354df79980152d05521a23114cb5d25b Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 26 Apr 2017 18:59:16 +0100 Subject: [PATCH 043/275] Make the left panel more friendly to new users https://github.com/vector-im/riot-web/issues/3609 Conflicts: src/components/views/rooms/RoomList.js cherry-picking commit f5f35e3. --- src/components/views/rooms/RoomList.js | 163 +++++++++++++++++++------ 1 file changed, 124 insertions(+), 39 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 760b0543c6..9dfa99fb44 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -29,7 +29,14 @@ var Rooms = require('../../../Rooms'); import DMRoomMap from '../../../utils/DMRoomMap'; var Receipt = require('../../../utils/Receipt'); -var HIDE_CONFERENCE_CHANS = true; +const HIDE_CONFERENCE_CHANS = true; + +const VERBS = { + 'm.favourite': 'favourite', + 'im.vector.fake.direct': 'tag direct chat', + 'im.vector.fake.recent': 'restore', + 'm.lowpriority': 'demote', +}; module.exports = React.createClass({ displayName: 'RoomList', @@ -44,6 +51,7 @@ module.exports = React.createClass({ getInitialState: function() { return { isLoadingLeftRooms: false, + totalRoomCount: null, lists: {}, incomingCall: null, }; @@ -63,8 +71,17 @@ module.exports = React.createClass({ cli.on("RoomMember.name", this.onRoomMemberName); cli.on("accountData", this.onAccountData); - var s = this.getRoomLists(); - this.setState(s); + // lookup for which lists a given roomId is currently in. + this.listsForRoomId = {}; + + this.refreshRoomList(); + + // order of the sublists + //this.listOrder = []; + + // loop count to stop a stack overflow if the user keeps waggling the + // mouse for >30s in a row, or if running under mocha + this._delayedRefreshRoomListLoopCount = 0 }, componentDidMount: function() { @@ -202,31 +219,33 @@ module.exports = React.createClass({ }, 500), refreshRoomList: function() { - // console.log("DEBUG: Refresh room list delta=%s ms", - // (!this._lastRefreshRoomListTs ? "-" : (Date.now() - this._lastRefreshRoomListTs)) - // ); - - // TODO: rather than bluntly regenerating and re-sorting everything - // every time we see any kind of room change from the JS SDK - // we could do incremental updates on our copy of the state - // based on the room which has actually changed. This would stop - // us re-rendering all the sublists every time anything changes anywhere - // in the state of the client. - this.setState(this.getRoomLists()); + // TODO: ideally we'd calculate this once at start, and then maintain + // any changes to it incrementally, updating the appropriate sublists + // as needed. + // Alternatively we'd do something magical with Immutable.js or similar. + const lists = this.getRoomLists(); + let totalRooms = 0; + for (const l of Object.values(lists)) { + totalRooms += l.length; + } + this.setState({ + lists: this.getRoomLists(), + totalRoomCount: totalRooms, + }); // this._lastRefreshRoomListTs = Date.now(); }, getRoomLists: function() { var self = this; - var s = { lists: {} }; + const lists = {}; - s.lists["im.vector.fake.invite"] = []; - s.lists["m.favourite"] = []; - s.lists["im.vector.fake.recent"] = []; - s.lists["im.vector.fake.direct"] = []; - s.lists["m.lowpriority"] = []; - s.lists["im.vector.fake.archived"] = []; + lists["im.vector.fake.invite"] = []; + lists["m.favourite"] = []; + lists["im.vector.fake.recent"] = []; + lists["im.vector.fake.direct"] = []; + lists["m.lowpriority"] = []; + lists["im.vector.fake.archived"] = []; const dmRoomMap = new DMRoomMap(MatrixClientPeg.get()); @@ -240,7 +259,8 @@ module.exports = React.createClass({ // ", prevMembership = " + me.events.member.getPrevContent().membership); if (me.membership == "invite") { - s.lists["im.vector.fake.invite"].push(room); + self.listsForRoomId[room.roomId].push("im.vector.fake.invite"); + lists["im.vector.fake.invite"].push(room); } else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) { // skip past this room & don't put it in any lists @@ -254,48 +274,55 @@ module.exports = React.createClass({ if (tagNames.length) { for (var i = 0; i < tagNames.length; i++) { var tagName = tagNames[i]; - s.lists[tagName] = s.lists[tagName] || []; - s.lists[tagNames[i]].push(room); + lists[tagName] = lists[tagName] || []; + lists[tagName].push(room); + self.listsForRoomId[room.roomId].push(tagName); + otherTagNames[tagName] = 1; } } else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { // "Direct Message" rooms (that we're still in and that aren't otherwise tagged) - s.lists["im.vector.fake.direct"].push(room); + self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); + lists["im.vector.fake.direct"].push(room); } else { - s.lists["im.vector.fake.recent"].push(room); + self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); + lists["im.vector.fake.recent"].push(room); } } else if (me.membership === "leave") { - s.lists["im.vector.fake.archived"].push(room); + self.listsForRoomId[room.roomId].push("im.vector.fake.archived"); + lists["im.vector.fake.archived"].push(room); } else { console.error("unrecognised membership: " + me.membership + " - this should never happen"); } }); - if (s.lists["im.vector.fake.direct"].length == 0 && + if (lists["im.vector.fake.direct"].length == 0 && MatrixClientPeg.get().getAccountData('m.direct') === undefined && !MatrixClientPeg.get().isGuest()) { // scan through the 'recents' list for any rooms which look like DM rooms // and make them DM rooms - const oldRecents = s.lists["im.vector.fake.recent"]; - s.lists["im.vector.fake.recent"] = []; + const oldRecents = lists["im.vector.fake.recent"]; + lists["im.vector.fake.recent"] = []; for (const room of oldRecents) { const me = room.getMember(MatrixClientPeg.get().credentials.userId); if (me && Rooms.looksLikeDirectMessageRoom(room, me)) { - s.lists["im.vector.fake.direct"].push(room); + self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); + lists["im.vector.fake.direct"].push(room); } else { - s.lists["im.vector.fake.recent"].push(room); + self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); + lists["im.vector.fake.recent"].push(room); } } // save these new guessed DM rooms into the account data const newMDirectEvent = {}; - for (const room of s.lists["im.vector.fake.direct"]) { + for (const room of lists["im.vector.fake.direct"]) { const me = room.getMember(MatrixClientPeg.get().credentials.userId); const otherPerson = Rooms.getOnlyOtherMember(room, me); if (!otherPerson) continue; @@ -313,7 +340,22 @@ module.exports = React.createClass({ // we actually apply the sorting to this when receiving the prop in RoomSubLists. - return s; + // we'll need this when we get to iterating through lists programatically - e.g. ctrl-shift-up/down +/* + this.listOrder = [ + "im.vector.fake.invite", + "m.favourite", + "im.vector.fake.recent", + "im.vector.fake.direct", + Object.keys(otherTagNames).filter(tagName=>{ + return (!tagName.match(/^m\.(favourite|lowpriority)$/)); + }).sort(), + "m.lowpriority", + "im.vector.fake.archived" + ]; +*/ + + return lists; }, _getScrollNode: function() { @@ -467,6 +509,49 @@ module.exports = React.createClass({ this.refs.gemscroll.forceUpdate(); }, + _getEmptyContent: function(section) { + let greyed = false; + if (this.state.totalRoomCount === 0) { + const TintableSvg = sdk.getComponent('elements.TintableSvg'); + switch (section) { + case 'm.favourite': + case 'm.lowpriority': + greyed = true; + break; + case 'im.vector.fake.direct': + return
+
+ +
+ Use the button below to chat with someone! +
; + case 'im.vector.fake.recent': + return
+
+ +
+ Use the button below to browse the room directory +

+
+ +
+ or this button to start a new one! +
; + } + } + const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); + + const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); + + let label; + if (greyed) { + label = {labelText}; + } else { + label = labelText; + } + return ; + }, + render: function() { var RoomSubList = sdk.getComponent('structures.RoomSubList'); var self = this; @@ -489,7 +574,7 @@ module.exports = React.createClass({ Date: Fri, 28 Apr 2017 11:20:29 +0100 Subject: [PATCH 044/275] Other empty sections no longer need to be greyed --- src/components/views/rooms/RoomList.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 9dfa99fb44..e285c1841e 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -510,14 +510,9 @@ module.exports = React.createClass({ }, _getEmptyContent: function(section) { - let greyed = false; if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); switch (section) { - case 'm.favourite': - case 'm.lowpriority': - greyed = true; - break; case 'im.vector.fake.direct': return
@@ -543,13 +538,7 @@ module.exports = React.createClass({ const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); - let label; - if (greyed) { - label = {labelText}; - } else { - label = labelText; - } - return ; + return ; }, render: function() { From bff0577cb61bfb8095c23254f618d9bb9a42a131 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 13:55:52 +0100 Subject: [PATCH 045/275] Add buttons to room sub list headers Conflicts: src/component-index.js src/components/views/rooms/RoomList.js cherry-picking commit ce119a6. --- src/components/views/elements/RoleButton.js | 75 +++++++++++++++++++++ src/components/views/rooms/RoomList.js | 40 +++++++---- 2 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/components/views/elements/RoleButton.js diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/RoleButton.js new file mode 100644 index 0000000000..06006a5779 --- /dev/null +++ b/src/components/views/elements/RoleButton.js @@ -0,0 +1,75 @@ +/* +Copyright Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +import AccessibleButton from './AccessibleButton'; +import dis from '../../../dispatcher'; +import sdk from '../../../index'; + +export default React.createClass({ + displayName: 'RoleButton', + + propTypes: { + role: PropTypes.string.isRequired, + size: PropTypes.string, + }, + + getDefaultProps: function() { + return { + size: 25, + }; + }, + + _onClick: function(ev) { + ev.stopPropagation(); + + let action; + switch(this.props.role) { + case 'start_chat': + action = 'view_create_chat'; + break; + case 'room_directory': + action = 'view_room_directory'; + break; + case 'create_room': + action = 'view_create_room'; + break; + } + if (action) dis.dispatch({action: action}); + }, + + _getIconPath() { + switch(this.props.role) { + case 'start_chat': + return 'img/icons-people.svg'; + case 'room_directory': + return 'img/icons-directory.svg'; + case 'create_room': + return 'img/icons-create-room.svg'; + } + }, + + render: function() { + const TintableSvg = sdk.getComponent("elements.TintableSvg"); + + return ( + + + + ); + } +}); diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index e285c1841e..9a64c16239 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -510,27 +511,23 @@ module.exports = React.createClass({ }, _getEmptyContent: function(section) { + const RoleButton = sdk.getComponent('elements.RoleButton'); if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); switch (section) { case 'im.vector.fake.direct': return
-
- -
- Use the button below to chat with someone! + Press + + to start a chat with someone
; case 'im.vector.fake.recent': return
-
- -
- Use the button below to browse the room directory -

-
- -
- or this button to start a new one! + You're not in any rooms yet! Press + + to make a room or + + to browse the directory
; } } @@ -541,6 +538,21 @@ module.exports = React.createClass({ return ; }, + _getHeaderItems: function(section) { + const RoleButton = sdk.getComponent('elements.RoleButton'); + switch (section) { + case 'im.vector.fake.direct': + return + + ; + case 'im.vector.fake.recent': + return + + + ; + } + }, + render: function() { var RoomSubList = sdk.getComponent('structures.RoomSubList'); var self = this; @@ -577,6 +589,7 @@ module.exports = React.createClass({ label="People" tagName="im.vector.fake.direct" emptyContent={this._getEmptyContent('im.vector.fake.direct')} + headerItems={this._getHeaderItems('im.vector.fake.direct')} editable={ true } order="recent" selectedRoom={ self.props.selectedRoom } @@ -591,6 +604,7 @@ module.exports = React.createClass({ label="Rooms" editable={ true } emptyContent={this._getEmptyContent('im.vector.fake.recent')} + headerItems={this._getHeaderItems('im.vector.fake.recent')} order="recent" selectedRoom={ self.props.selectedRoom } incomingCall={ self.state.incomingCall } From 54af06e8e12bfe86f11b4a3131ea155b8e161f3c Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 15:02:21 +0100 Subject: [PATCH 046/275] What year is it? Who's the president? --- src/components/views/elements/RoleButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/RoleButton.js index 06006a5779..f20b4c6b88 100644 --- a/src/components/views/elements/RoleButton.js +++ b/src/components/views/elements/RoleButton.js @@ -1,5 +1,5 @@ /* -Copyright Vector Creations Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From a996f52ea34c0d4c7cc072c7cf068baf3b9cde1b Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 15:38:09 +0100 Subject: [PATCH 047/275] Make bottom left menu buttons use RoleButton too --- src/components/views/elements/RoleButton.js | 53 ++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/RoleButton.js index f20b4c6b88..60f227a067 100644 --- a/src/components/views/elements/RoleButton.js +++ b/src/components/views/elements/RoleButton.js @@ -31,6 +31,13 @@ export default React.createClass({ getDefaultProps: function() { return { size: 25, + tooltip: false, + }; + }, + + getInitialState: function() { + return { + showTooltip: false, }; }, @@ -48,10 +55,39 @@ export default React.createClass({ case 'create_room': action = 'view_create_room'; break; + case 'home_page': + action = 'view_home_page'; + break; + case 'settings': + action = 'view_user_settings'; + break; } if (action) dis.dispatch({action: action}); }, + _onMouseEnter: function() { + if (this.props.tooltip) this.setState({showTooltip: true}); + }, + + _onMouseLeave: function() { + this.setState({showTooltip: false}); + }, + + _getLabel() { + switch(this.props.role) { + case 'start_chat': + return 'Start chat'; + case 'room_directory': + return 'Room directory'; + case 'create_room': + return 'Create new room'; + case 'home_page': + return 'Welcome page'; + case 'settings': + return 'Settings'; + } + }, + _getIconPath() { switch(this.props.role) { case 'start_chat': @@ -60,15 +96,30 @@ export default React.createClass({ return 'img/icons-directory.svg'; case 'create_room': return 'img/icons-create-room.svg'; + case 'home_page': + return 'img/icons-home.svg'; + case 'settings': + return 'img/icons-settings.svg'; } }, render: function() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); + let tooltip; + if (this.state.showTooltip) { + const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); + tooltip = ; + } + return ( - + + {tooltip} ); } From 3d3d89202e01100f1162d30542b59c8826c19e29 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 15:46:24 +0100 Subject: [PATCH 048/275] Year --- src/components/views/rooms/RoomList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 9a64c16239..ecb178d145 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -1,6 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd -Copyright Vector Creations Ltd +Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 99efbbee5e23913221d95bc9d8457bed24a4e0ae Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 16:22:06 +0100 Subject: [PATCH 049/275] Depend on prop-types module So we can start writing code compatible with new React --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 059fdd390f..572dcddeb5 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "lodash": "^4.13.1", "matrix-js-sdk": "0.7.8", "optimist": "^0.6.1", + "prop-types": "^15.5.8", "q": "^1.4.1", "react": "^15.4.0", "react-addons-css-transition-group": "15.3.2", From dc2274df54896b48f836854cf46cd10b525d41c8 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 4 May 2017 18:08:04 +0100 Subject: [PATCH 050/275] Hide empty tips if collapsed --- src/components/views/rooms/RoomList.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index ecb178d145..2dce02cc78 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -511,6 +511,12 @@ module.exports = React.createClass({ }, _getEmptyContent: function(section) { + const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); + + if (this.props.collapsed) { + return ; + } + const RoleButton = sdk.getComponent('elements.RoleButton'); if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); @@ -531,7 +537,6 @@ module.exports = React.createClass({
; } } - const RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget'); const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); From 9337158a470e2d23d16cce0054a931e5f97a3b0d Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 5 May 2017 14:25:18 +0100 Subject: [PATCH 051/275] Separate classes for the different buttons Also rename RoleButton to ActionButton because it's not being given a Role any more. Conflicts: src/component-index.js cherry-picking commit 4a5821e. --- .../{RoleButton.js => ActionButton.js} | 60 +++---------------- .../views/elements/CreateRoomButton.js | 37 ++++++++++++ src/components/views/elements/HomeButton.js | 37 ++++++++++++ .../views/elements/RoomDirectoryButton.js | 37 ++++++++++++ .../views/elements/SettingsButton.js | 37 ++++++++++++ .../views/elements/StartChatButton.js | 37 ++++++++++++ src/components/views/rooms/RoomList.js | 20 ++++--- 7 files changed, 204 insertions(+), 61 deletions(-) rename src/components/views/elements/{RoleButton.js => ActionButton.js} (54%) create mode 100644 src/components/views/elements/CreateRoomButton.js create mode 100644 src/components/views/elements/HomeButton.js create mode 100644 src/components/views/elements/RoomDirectoryButton.js create mode 100644 src/components/views/elements/SettingsButton.js create mode 100644 src/components/views/elements/StartChatButton.js diff --git a/src/components/views/elements/RoleButton.js b/src/components/views/elements/ActionButton.js similarity index 54% rename from src/components/views/elements/RoleButton.js rename to src/components/views/elements/ActionButton.js index 60f227a067..6d6289ddab 100644 --- a/src/components/views/elements/RoleButton.js +++ b/src/components/views/elements/ActionButton.js @@ -24,8 +24,11 @@ export default React.createClass({ displayName: 'RoleButton', propTypes: { - role: PropTypes.string.isRequired, size: PropTypes.string, + tooltip: PropTypes.bool, + action: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + iconPath: PropTypes.string.isRequired, }, getDefaultProps: function() { @@ -43,26 +46,7 @@ export default React.createClass({ _onClick: function(ev) { ev.stopPropagation(); - - let action; - switch(this.props.role) { - case 'start_chat': - action = 'view_create_chat'; - break; - case 'room_directory': - action = 'view_room_directory'; - break; - case 'create_room': - action = 'view_create_room'; - break; - case 'home_page': - action = 'view_home_page'; - break; - case 'settings': - action = 'view_user_settings'; - break; - } - if (action) dis.dispatch({action: action}); + dis.dispatch({action: this.props.action}); }, _onMouseEnter: function() { @@ -73,43 +57,13 @@ export default React.createClass({ this.setState({showTooltip: false}); }, - _getLabel() { - switch(this.props.role) { - case 'start_chat': - return 'Start chat'; - case 'room_directory': - return 'Room directory'; - case 'create_room': - return 'Create new room'; - case 'home_page': - return 'Welcome page'; - case 'settings': - return 'Settings'; - } - }, - - _getIconPath() { - switch(this.props.role) { - case 'start_chat': - return 'img/icons-people.svg'; - case 'room_directory': - return 'img/icons-directory.svg'; - case 'create_room': - return 'img/icons-create-room.svg'; - case 'home_page': - return 'img/icons-home.svg'; - case 'settings': - return 'img/icons-settings.svg'; - } - }, - render: function() { const TintableSvg = sdk.getComponent("elements.TintableSvg"); let tooltip; if (this.state.showTooltip) { const RoomTooltip = sdk.getComponent("rooms.RoomTooltip"); - tooltip = ; + tooltip = ; } return ( @@ -118,7 +72,7 @@ export default React.createClass({ onMouseEnter={this._onMouseEnter} onMouseLeave={this._onMouseLeave} > - + {tooltip} ); diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js new file mode 100644 index 0000000000..d6b6526d6c --- /dev/null +++ b/src/components/views/elements/CreateRoomButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const CreateRoomButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +CreateRoomButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default CreateRoomButton; diff --git a/src/components/views/elements/HomeButton.js b/src/components/views/elements/HomeButton.js new file mode 100644 index 0000000000..4c7f295c87 --- /dev/null +++ b/src/components/views/elements/HomeButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const HomeButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +HomeButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default HomeButton; diff --git a/src/components/views/elements/RoomDirectoryButton.js b/src/components/views/elements/RoomDirectoryButton.js new file mode 100644 index 0000000000..651dd8edd0 --- /dev/null +++ b/src/components/views/elements/RoomDirectoryButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const RoomDirectoryButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +RoomDirectoryButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default RoomDirectoryButton; diff --git a/src/components/views/elements/SettingsButton.js b/src/components/views/elements/SettingsButton.js new file mode 100644 index 0000000000..51da6e3fd1 --- /dev/null +++ b/src/components/views/elements/SettingsButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const SettingsButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +SettingsButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default SettingsButton; diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js new file mode 100644 index 0000000000..66cd911754 --- /dev/null +++ b/src/components/views/elements/StartChatButton.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 Vector Creations Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from '../../../index'; +import PropTypes from 'prop-types'; + +const StartChatButton = function(props) { + const ActionButton = sdk.getComponent('elements.ActionButton'); + return ( + + ); +}; + +StartChatButton.propTypes = { + size: PropTypes.string, + tooltip: PropTypes.bool, +}; + +export default StartChatButton; diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 2dce02cc78..8c8fd3ea86 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -517,22 +517,24 @@ module.exports = React.createClass({ return ; } - const RoleButton = sdk.getComponent('elements.RoleButton'); + const StartChatButton = sdk.getComponent('elements.StartChatButton'); + const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); + const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); if (this.state.totalRoomCount === 0) { const TintableSvg = sdk.getComponent('elements.TintableSvg'); switch (section) { case 'im.vector.fake.direct': return
Press - + to start a chat with someone
; case 'im.vector.fake.recent': return
You're not in any rooms yet! Press - + to make a room or - + to browse the directory
; } @@ -544,16 +546,18 @@ module.exports = React.createClass({ }, _getHeaderItems: function(section) { - const RoleButton = sdk.getComponent('elements.RoleButton'); + const StartChatButton = sdk.getComponent('elements.StartChatButton'); + const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); + const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); switch (section) { case 'im.vector.fake.direct': return - + ; case 'im.vector.fake.recent': return - - + + ; } }, From 5e855e6fee3c5cf068263967baa6d0c544c2a32c Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 5 May 2017 14:56:26 +0100 Subject: [PATCH 052/275] Size is a string, import react React gets put in by the JSX transpile --- src/components/views/elements/ActionButton.js | 2 +- src/components/views/elements/CreateRoomButton.js | 1 + src/components/views/elements/HomeButton.js | 1 + src/components/views/elements/RoomDirectoryButton.js | 1 + src/components/views/elements/SettingsButton.js | 1 + src/components/views/elements/StartChatButton.js | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 6d6289ddab..267388daf6 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -33,7 +33,7 @@ export default React.createClass({ getDefaultProps: function() { return { - size: 25, + size: "25", tooltip: false, }; }, diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js index d6b6526d6c..e7e526d36b 100644 --- a/src/components/views/elements/CreateRoomButton.js +++ b/src/components/views/elements/CreateRoomButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/HomeButton.js b/src/components/views/elements/HomeButton.js index 4c7f295c87..5c446f24c9 100644 --- a/src/components/views/elements/HomeButton.js +++ b/src/components/views/elements/HomeButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/RoomDirectoryButton.js b/src/components/views/elements/RoomDirectoryButton.js index 651dd8edd0..5e68776a15 100644 --- a/src/components/views/elements/RoomDirectoryButton.js +++ b/src/components/views/elements/RoomDirectoryButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/SettingsButton.js b/src/components/views/elements/SettingsButton.js index 51da6e3fd1..c6438da277 100644 --- a/src/components/views/elements/SettingsButton.js +++ b/src/components/views/elements/SettingsButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; diff --git a/src/components/views/elements/StartChatButton.js b/src/components/views/elements/StartChatButton.js index 66cd911754..02d5677a7c 100644 --- a/src/components/views/elements/StartChatButton.js +++ b/src/components/views/elements/StartChatButton.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; From 548f319816d94955fc45fc68f51da5f6dcc2787e Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 5 May 2017 17:51:14 +0100 Subject: [PATCH 053/275] Remove redundant role elements --- src/components/views/rooms/RoomList.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 8c8fd3ea86..cde2bec7da 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -552,12 +552,12 @@ module.exports = React.createClass({ switch (section) { case 'im.vector.fake.direct': return - + ; case 'im.vector.fake.recent': return - - + + ; } }, From 3185d3ed41d376d52d65583247a08a74a12f1983 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 13:54:59 +0100 Subject: [PATCH 054/275] Re-add bouncing/callout animation to action buttons --- src/components/views/elements/ActionButton.js | 4 ++++ src/components/views/elements/CreateRoomButton.js | 1 + src/components/views/elements/RoomDirectoryButton.js | 1 + src/components/views/elements/StartChatButton.js | 3 ++- src/components/views/rooms/RoomList.js | 6 +++--- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 267388daf6..08fb6faa1d 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -27,6 +27,7 @@ export default React.createClass({ size: PropTypes.string, tooltip: PropTypes.bool, action: PropTypes.string.isRequired, + mouseOverAction: PropTypes.string, label: PropTypes.string.isRequired, iconPath: PropTypes.string.isRequired, }, @@ -51,6 +52,9 @@ export default React.createClass({ _onMouseEnter: function() { if (this.props.tooltip) this.setState({showTooltip: true}); + if (this.props.mouseOverAction) { + dis.dispatch({action: this.props.mouseOverAction}); + } }, _onMouseLeave: function() { diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js index e7e526d36b..82643559b3 100644 --- a/src/components/views/elements/CreateRoomButton.js +++ b/src/components/views/elements/CreateRoomButton.js @@ -22,6 +22,7 @@ const CreateRoomButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( Press - + to start a chat with someone
; case 'im.vector.fake.recent': return
You're not in any rooms yet! Press - + to make a room or - + to browse the directory
; } From 7900bf1c7de0d170b3ca055332d4bebb3f10f4ef Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 13:55:37 +0100 Subject: [PATCH 055/275] Don't show "Drop to ..." if total rooms = 0 --- src/components/views/rooms/RoomList.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 98a5229d6a..216dd972cf 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -540,6 +540,10 @@ module.exports = React.createClass({ } } + if (this.state.totalRoomCount === 0) { + return null; + } + const labelText = 'Drop here to ' + (VERBS[section] || 'tag ' + section); return ; From 51c8ee6db23f5eacaa348a58324df69704b06a15 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 14:38:12 +0100 Subject: [PATCH 056/275] Allow teamServerConfig to be missing --- src/components/structures/LoggedInView.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 4687afbee1..8cd2bf8a71 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -232,9 +232,15 @@ export default React.createClass({ break; case PageTypes.HomePage: + // If team server config is present, pass the teamServerURL. props.teamToken + // must also be set for the team page to be displayed, otherwise the + // welcomePageUrl is used (which might be undefined). + const teamServerUrl = this.props.config.teamServerConfig ? + this.props.config.teamServerConfig.teamServerURL : null; + page_element = ; From 2265b59287b44c0ad8d473c98e59a84209141df2 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 14:54:28 +0100 Subject: [PATCH 057/275] Remove warm-fuzzy after setting mxid --- src/components/views/dialogs/SetMxIdDialog.js | 39 +------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index c371fdd35a..86b5fccbc2 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -53,9 +53,6 @@ export default React.createClass({ doingUIAuth: false, // Indicate error with auth authError: '', - - // Indicate success of setting mxid - success: false, }; }, @@ -98,10 +95,6 @@ export default React.createClass({ }); }, - onSuccessContinue: function() { - this.props.onFinished(true, this._registeredCreds); - }, - _doUsernameCheck: function() { // Check if username is available return this._matrixClient.isUsernameAvailable(this.state.username).then( @@ -169,7 +162,7 @@ export default React.createClass({ // XXX Implement RTS /register here const teamToken = null; - this._registeredCreds = { + this.props.onFinished(true, { userId: response.user_id, deviceId: response.device_id, homeserverUrl: this._matrixClient.getHomeserverUrl(), @@ -177,11 +170,6 @@ export default React.createClass({ accessToken: response.access_token, password: this._generatedPassword, teamToken: teamToken, - }; - - // Before continuing, show a warm-fuzzy success and only submit onSuccessContinue - this.setState({ - success: true, }); }, @@ -231,31 +219,6 @@ export default React.createClass({ !this.state.usernameError && !this.state.usernameBusy; - if (this.state.success) { - // XXX BaseDialog needs an onFinished - return ( - -
-

- You have successfully - picked { this.state.username } as your - username and you now have access to the full - set of features on Riot. -

-
-
- -
-
- ); - } - return ( Date: Thu, 25 May 2017 15:20:02 +0100 Subject: [PATCH 058/275] Unbreak the roomlist --- src/components/views/rooms/RoomList.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 216dd972cf..efadda08ac 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -72,9 +72,6 @@ module.exports = React.createClass({ cli.on("RoomMember.name", this.onRoomMemberName); cli.on("accountData", this.onAccountData); - // lookup for which lists a given roomId is currently in. - this.listsForRoomId = {}; - this.refreshRoomList(); // order of the sublists @@ -260,7 +257,6 @@ module.exports = React.createClass({ // ", prevMembership = " + me.events.member.getPrevContent().membership); if (me.membership == "invite") { - self.listsForRoomId[room.roomId].push("im.vector.fake.invite"); lists["im.vector.fake.invite"].push(room); } else if (HIDE_CONFERENCE_CHANS && Rooms.isConfCallRoom(room, me, self.props.ConferenceHandler)) { @@ -277,22 +273,18 @@ module.exports = React.createClass({ var tagName = tagNames[i]; lists[tagName] = lists[tagName] || []; lists[tagName].push(room); - self.listsForRoomId[room.roomId].push(tagName); otherTagNames[tagName] = 1; } } else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { // "Direct Message" rooms (that we're still in and that aren't otherwise tagged) - self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); lists["im.vector.fake.direct"].push(room); } else { - self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); lists["im.vector.fake.recent"].push(room); } } else if (me.membership === "leave") { - self.listsForRoomId[room.roomId].push("im.vector.fake.archived"); lists["im.vector.fake.archived"].push(room); } else { @@ -313,10 +305,8 @@ module.exports = React.createClass({ const me = room.getMember(MatrixClientPeg.get().credentials.userId); if (me && Rooms.looksLikeDirectMessageRoom(room, me)) { - self.listsForRoomId[room.roomId].push("im.vector.fake.direct"); lists["im.vector.fake.direct"].push(room); } else { - self.listsForRoomId[room.roomId].push("im.vector.fake.recent"); lists["im.vector.fake.recent"].push(room); } } From 11799b4c71330f8dd0636a386e7e6c2782e20f52 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 15:27:54 +0100 Subject: [PATCH 059/275] Show "Password" instead of "New Password" when the existing password has been cached --- src/components/views/settings/ChangePassword.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index bfc9ac264e..25af0e389f 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -193,12 +193,14 @@ module.exports = React.createClass({ switch (this.state.phase) { case this.Phases.Edit: + const passwordLabel = this.state.cachedPassword ? + 'Password' : 'New Password'; return (
{ currentPassword }
- +
From 91edc064416c202de31bf18ccfcc14b499ce6ee0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 17:04:42 +0100 Subject: [PATCH 060/275] Use RVS to indicate "joining" when setting a mxid This prevents RoomView from doing any peeking whilst the join/registration is in progress, causing weirdness with TimelinePanel getPendingEventList (which throws an error if called when peeking). --- src/components/structures/RoomView.js | 14 ++++++++++---- src/stores/RoomViewStore.js | 11 ++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index e5e38a33d8..6e2a7df5ac 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -671,10 +671,6 @@ module.exports = React.createClass({ // compatability workaround, let's not bother. Rooms.setDMRoom(this.state.room.roomId, me.events.member.getSender()).done(); } - - this.setState({ - joining: false - }); } }, 500), @@ -762,12 +758,22 @@ module.exports = React.createClass({ }, }); + // Don't peek whilst registering otherwise getPendingEventList complains + // Do this by indicating our intention to join + dis.dispatch({ + action: 'will_join', + }); + const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const close = Modal.createDialog(SetMxIdDialog, { homeserverUrl: cli.getHomeserverUrl(), onFinished: (submitted, credentials) => { if (submitted) { this.props.onRegistered(credentials); + } else { + dis.dispatch({ + action: 'cancel_join', + }); } }, onDifferentServerClicked: (ev) => { diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index fe57079859..1ceef551a8 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -58,7 +58,16 @@ class RoomViewStore extends Store { case 'view_room': this._viewRoom(payload); break; - + case 'will_join': + this._setState({ + joining: true, + }); + break; + case 'cancel_join': + this._setState({ + joining: false, + }); + break; // join_room: // - opts: options for joinRoom case 'join_room': From 0849b0e20527ae3c2abf563a0232609ae78550cc Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 17:10:49 +0100 Subject: [PATCH 061/275] Fix view_next_room, view_previous_room and view_indexed_room These must now make a dispatch to RoomViewStore instead of calling `viewRoom` directly on MatrixChat. This will call both `viewRoom` of MatrixChat _and_ the logic in RVS so there is some redundancy here. It'd be best to move as much as possible of viewRoom out to the RVS itself. But for now, this fixes a bug that occures when leaving (the viewed room would not change). --- src/components/structures/MatrixChat.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index a6f2ee820f..2e4a3b90ad 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -553,6 +553,7 @@ module.exports = React.createClass({ this.notifyNewScreen('register'); }, + // TODO: Move to RoomViewStore _viewNextRoom: function(roomIndexDelta) { const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), @@ -566,15 +567,22 @@ module.exports = React.createClass({ } roomIndex = (roomIndex + roomIndexDelta) % allRooms.length; if (roomIndex < 0) roomIndex = allRooms.length - 1; - this._viewRoom({ room_id: allRooms[roomIndex].roomId }); + dis.dispatch({ + action: 'view_room', + room_id: allRooms[roomIndex].roomId, + }); }, + // TODO: Move to RoomViewStore _viewIndexedRoom: function(roomIndex) { const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); if (allRooms[roomIndex]) { - this._viewRoom({ room_id: allRooms[roomIndex].roomId }); + dis.dispatch({ + action: 'view_room', + room_id: allRooms[roomIndex].roomId, + }); } }, From 263a51938d894896306fab155737aecc7c74b04a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 25 May 2017 17:16:16 +0100 Subject: [PATCH 062/275] Reset store state when logging out This prevents leaking of state that we do not want to share with the next user --- src/stores/LifecycleStore.js | 5 +++++ src/stores/RoomViewStore.js | 3 +++ src/stores/SessionStore.js | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/src/stores/LifecycleStore.js b/src/stores/LifecycleStore.js index 43e2de9d52..5dfe82500a 100644 --- a/src/stores/LifecycleStore.js +++ b/src/stores/LifecycleStore.js @@ -61,6 +61,11 @@ class LifecycleStore extends Store { }); dis.dispatch(deferredAction); break; + case 'on_logged_out': + this._state = { + deferred_action: null, + }; + break; } } } diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 1ceef551a8..d893318af7 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -73,6 +73,9 @@ class RoomViewStore extends Store { case 'join_room': this._joinRoom(payload); break; + case 'on_logged_out': + this.reset(); + break; } } diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 2fd35ce40a..5713e4d321 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -66,6 +66,11 @@ class SessionStore extends Store { cachedPassword: null, }); break; + case 'on_logged_out': + this._state = { + cachedPassword: null, + }; + break; } } From b5b157a0fb0bae097fc0cb62af5169b59eae31f4 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 10:34:36 +0100 Subject: [PATCH 063/275] Don't show notif nag bar if guest --- src/components/structures/LoggedInView.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 8cd2bf8a71..e7c1e00008 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -253,6 +253,7 @@ export default React.createClass({ break; } + const isGuest = this.props.matrixClient.isGuest(); var topBar; if (this.props.hasNewVersion) { topBar = ; } else if (this.state.userHasGeneratedPassword) { topBar = ; - } else if (Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { + } else if (!isGuest && Notifier.supportsDesktopNotifications() && !Notifier.isEnabled() && !Notifier.isToolbarHidden()) { topBar = ; } From 2dcc03960a5b9fb362e3fd6a140cc28a61c85344 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 11:46:33 +0100 Subject: [PATCH 064/275] Set the displayname to the mxid once PWLU --- src/components/structures/MatrixChat.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index a6f2ee820f..6d827b3ef0 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -805,6 +805,12 @@ module.exports = React.createClass({ dis.dispatch({action: 'view_home_page'}); } else if (this._is_registered) { this._is_registered = false; + + // Set the display name = entered username + MatrixClientPeg.get().setDisplayName( + MatrixClientPeg.get().getUserIdLocalpart() + ); + if (this.props.config.welcomeUserId) { createRoom({ dmUserId: this.props.config.welcomeUserId, From c0f43a14fd4c5b61bfe05e820a0091d4afa951d8 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 11:47:55 +0100 Subject: [PATCH 065/275] Improve comment --- src/components/structures/MatrixChat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 6d827b3ef0..3c23f649e3 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -806,7 +806,7 @@ module.exports = React.createClass({ } else if (this._is_registered) { this._is_registered = false; - // Set the display name = entered username + // Set the display name = user ID localpart MatrixClientPeg.get().setDisplayName( MatrixClientPeg.get().getUserIdLocalpart() ); From 2400efa92bc2f3622f02a0492102182ff935b613 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 11:48:38 +0100 Subject: [PATCH 066/275] Correct LifecycleStore docs --- src/stores/LifecycleStore.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/stores/LifecycleStore.js b/src/stores/LifecycleStore.js index 43e2de9d52..3ed2e5c045 100644 --- a/src/stores/LifecycleStore.js +++ b/src/stores/LifecycleStore.js @@ -20,13 +20,6 @@ import {Store} from 'flux/utils'; * A class for storing application state to do with login/registration. This is a simple * flux store that listens for actions and updates its state accordingly, informing any * listeners (views) of state changes. - * - * Usage: - * ``` - * lifecycleStore.addListener(() => { - * this.setState({ cachedPassword: lifecycleStore.getCachedPassword() }) - * }) - * ``` */ class LifecycleStore extends Store { constructor() { From ad3373789fe094d5790119aaf5002205f1d92eb1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 11:50:32 +0100 Subject: [PATCH 067/275] Warn about LifecycleStore not explicitly being used --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index a6f2ee820f..ef2882fe13 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -32,6 +32,7 @@ import sdk from '../../index'; import * as Rooms from '../../Rooms'; import linkifyMatrix from "../../linkify-matrix"; import * as Lifecycle from '../../Lifecycle'; +// LifecycleStore is not used but does listen to and dispatch actions import LifecycleStore from '../../stores/LifecycleStore'; import RoomViewStore from '../../stores/RoomViewStore'; import PageTypes from '../../PageTypes'; From 28094a9a6634e5ec827bcf8481448b733bf44430 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 13:13:57 +0100 Subject: [PATCH 068/275] Show "Something went wrong!" when errcode undefined --- src/components/views/dialogs/SetMxIdDialog.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 86b5fccbc2..72599a6b21 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -108,6 +108,7 @@ export default React.createClass({ const newState = { usernameCheckSupport: err.errcode !== "M_UNRECOGNIZED", }; + console.error('Error whilst checking username availability: ', err); switch (err.errcode) { case "M_USER_IN_USE": newState.usernameError = 'Username not available'; @@ -120,8 +121,11 @@ export default React.createClass({ // fine and rely on the error appearing in registration step. newState.usernameError = ''; break; + case undefined: + newState.usernameError = 'Something went wrong!'; + break; default: - newState.usernameError = 'An error occurred' + err.message; + newState.usernameError = 'An error occurred: ' + err.message; break; } this.setState(newState); From 5e136863b0558d1edc83b1413abbef56b4a19742 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 13:18:44 +0100 Subject: [PATCH 069/275] Block user settings with view_set_mxid --- src/components/structures/MatrixChat.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index ef2882fe13..a03273c1c6 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -433,6 +433,10 @@ module.exports = React.createClass({ this._viewIndexedRoom(payload.roomIndex); break; case 'view_user_settings': + if (MatrixClientPeg.get().isGuest()) { + dis.dispatch({action: 'view_set_mxid'}); + break; + } this._setPage(PageTypes.UserSettings); this.notifyNewScreen('settings'); break; @@ -441,7 +445,6 @@ module.exports = React.createClass({ dis.dispatch({action: 'view_set_mxid'}); break; } - Modal.createDialog(TextInputDialog, { title: "Create Room", description: "Room name (optional)", From 9311b9012a4177c501a61c34a5d7d08b48f054f5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 17:23:02 +0100 Subject: [PATCH 070/275] Use the same `.reset` as RoomViewStore --- src/stores/LifecycleStore.js | 16 ++++++++++------ src/stores/SessionStore.js | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/stores/LifecycleStore.js b/src/stores/LifecycleStore.js index 5dfe82500a..f7e3ff9dbb 100644 --- a/src/stores/LifecycleStore.js +++ b/src/stores/LifecycleStore.js @@ -16,6 +16,10 @@ limitations under the License. import dis from '../dispatcher'; import {Store} from 'flux/utils'; +const INITIAL_STATE = { + deferred_action: null, +}; + /** * A class for storing application state to do with login/registration. This is a simple * flux store that listens for actions and updates its state accordingly, informing any @@ -33,9 +37,7 @@ class LifecycleStore extends Store { super(dis); // Initialise state - this._state = { - deferred_action: null, - }; + this._state = INITIAL_STATE; } _setState(newState) { @@ -62,12 +64,14 @@ class LifecycleStore extends Store { dis.dispatch(deferredAction); break; case 'on_logged_out': - this._state = { - deferred_action: null, - }; + this.reset(); break; } } + + reset() { + this._state = Object.assign({}, INITIAL_STATE); + } } let singletonLifecycleStore = null; diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 5713e4d321..a4b49d9cea 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -16,6 +16,10 @@ limitations under the License. import dis from '../dispatcher'; import {Store} from 'flux/utils'; +const INITIAL_STATE = { + cachedPassword: localStorage.getItem('mx_pass'), +}; + /** * A class for storing application state to do with the session. This is a simple flux * store that listens for actions and updates its state accordingly, informing any @@ -33,9 +37,7 @@ class SessionStore extends Store { super(dis); // Initialise state - this._state = { - cachedPassword: localStorage.getItem('mx_pass'), - }; + this._state = INITIAL_STATE; } _update() { @@ -67,11 +69,13 @@ class SessionStore extends Store { }); break; case 'on_logged_out': - this._state = { - cachedPassword: null, - }; + this.reset(); break; } + + reset() { + this._state = Object.assign({}, INITIAL_STATE); + } } getCachedPassword() { From ac44151e2a2d8c9b158d8b8315ddb939430291f6 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 26 May 2017 17:27:31 +0100 Subject: [PATCH 071/275] Put the reset method in the right scope... --- src/stores/SessionStore.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index a4b49d9cea..62868e4fe4 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -72,10 +72,10 @@ class SessionStore extends Store { this.reset(); break; } + } - reset() { - this._state = Object.assign({}, INITIAL_STATE); - } + reset() { + this._state = Object.assign({}, INITIAL_STATE); } getCachedPassword() { From 1efc5c2b2599120849ef7c01ebdef5d8941d4c15 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sun, 28 May 2017 23:28:29 +0100 Subject: [PATCH 072/275] speed up SetMxIdDialog user check to 250ms as it was driving me MAD i18nize new bottomleftmenu buttons --- src/components/views/dialogs/SetMxIdDialog.js | 2 +- src/components/views/elements/CreateRoomButton.js | 3 ++- src/components/views/elements/HomeButton.js | 3 ++- src/components/views/elements/RoomDirectoryButton.js | 3 ++- src/components/views/elements/SettingsButton.js | 3 ++- src/components/views/elements/StartChatButton.js | 3 ++- src/i18n/strings/en_EN.json | 7 ++++++- 7 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 72599a6b21..d0aa067a70 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -23,7 +23,7 @@ import classnames from 'classnames'; // The amount of time to wait for further changes to the input username before // sending a request to the server -const USERNAME_CHECK_DEBOUNCE_MS = 2000; +const USERNAME_CHECK_DEBOUNCE_MS = 250; /** * Prompt the user to set a display name. diff --git a/src/components/views/elements/CreateRoomButton.js b/src/components/views/elements/CreateRoomButton.js index 82643559b3..f98974b489 100644 --- a/src/components/views/elements/CreateRoomButton.js +++ b/src/components/views/elements/CreateRoomButton.js @@ -17,13 +17,14 @@ limitations under the License. import React from 'react'; import sdk from '../../../index'; import PropTypes from 'prop-types'; +import { _t } from '../../../languageHandler'; const CreateRoomButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( Date: Mon, 29 May 2017 01:32:31 +0100 Subject: [PATCH 073/275] add login link to SetMxIdDialog --- src/components/structures/MatrixChat.js | 4 ++++ src/components/structures/RoomView.js | 4 ++++ src/components/views/dialogs/SetMxIdDialog.js | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index c48a3731ae..1adb67887c 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -682,6 +682,10 @@ module.exports = React.createClass({ dis.dispatch({action: 'start_registration'}); close(); }, + onLoginClick: (ev) => { + dis.dispatch({action: 'start_login'}); + close(); + }, }).close; }, diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 7ed5ea6eab..6e853c135a 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -788,6 +788,10 @@ module.exports = React.createClass({ dis.dispatch({action: 'start_registration'}); close(); }, + onLoginClick: (ev) => { + dis.dispatch({action: 'start_login'}); + close(); + }, }).close; return; } diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index d0aa067a70..19924093de 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -36,6 +36,8 @@ export default React.createClass({ onFinished: React.PropTypes.func.isRequired, // Called when the user requests to register with a different homeserver onDifferentServerClicked: React.PropTypes.func.isRequired, + // Called if the user wants to switch to login instead + onLoginClick: React.PropTypes.func.isRequired, }, getInitialState: function() { @@ -245,6 +247,9 @@ export default React.createClass({ different server .

+

+ If you already have a Matrix account you can log in instead. +

{ auth } { authErrorIndicator }
From ad1b14967bfb06614c0b04e7a3dfe1483380225b Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 30 May 2017 03:59:06 +0100 Subject: [PATCH 074/275] hide rightpanel on welcome page --- src/components/structures/LoggedInView.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index f630503500..a297952a2c 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -244,7 +244,6 @@ export default React.createClass({ teamToken={this.props.teamToken} homePageUrl={this.props.config.welcomePageUrl} />; - if (!this.props.collapse_rhs) right_panel = break; case PageTypes.UserView: From 952651c6858b40f425c5efad86fcdb7558ab70d0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 30 May 2017 13:02:35 +0100 Subject: [PATCH 075/275] Allow pressing Enter to submit setMxId --- src/components/views/dialogs/SetMxIdDialog.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 19924093de..61acbf2192 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -91,6 +91,12 @@ export default React.createClass({ }); }, + onKeyUp: function(ev) { + if (ev.keyCode === 13) { + this.onSubmit(); + } + }, + onSubmit: function(ev) { this.setState({ doingUIAuth: true, @@ -233,7 +239,10 @@ export default React.createClass({
{ usernameBusyIndicator } From 47bf5401fa06cc074bb6818b7b5c98c11c8de54a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 30 May 2017 13:14:14 +0100 Subject: [PATCH 076/275] Use KeyCode.ENTER instead of 13 --- src/components/views/dialogs/SetMxIdDialog.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 61acbf2192..efca192ec1 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -20,6 +20,7 @@ import React from 'react'; import sdk from '../../../index'; import MatrixClientPeg from '../../../MatrixClientPeg'; import classnames from 'classnames'; +import KeyCode from '../../../KeyCode'; // The amount of time to wait for further changes to the input username before // sending a request to the server @@ -92,7 +93,7 @@ export default React.createClass({ }, onKeyUp: function(ev) { - if (ev.keyCode === 13) { + if (ev.keyCode === KeyCode.ENTER) { this.onSubmit(); } }, From 2baef643e3ee1a2a9e8a21f1778ab7aa8d237d93 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 30 May 2017 14:27:02 +0100 Subject: [PATCH 077/275] Add /start to show the setMxId above HomePage --- src/components/structures/MatrixChat.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 1adb67887c..e5fab4dde7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -685,7 +685,7 @@ module.exports = React.createClass({ onLoginClick: (ev) => { dis.dispatch({action: 'start_login'}); close(); - }, + }, }).close; }, @@ -991,6 +991,11 @@ module.exports = React.createClass({ dis.dispatch({ action: 'view_home_page', }); + } else if (screen == 'start') { + this.showScreen('home'); + dis.dispatch({ + action: 'view_set_mxid', + }); } else if (screen == 'directory') { dis.dispatch({ action: 'view_room_directory', From 6f8d5b1db3dc088767640e6996fa29aac6cc4864 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 30 May 2017 16:10:19 +0100 Subject: [PATCH 078/275] Remove spurious reference to `otherTagNames` --- src/components/views/rooms/RoomList.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index d62ce4d460..0bca41e9e4 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -274,7 +274,6 @@ module.exports = React.createClass({ var tagName = tagNames[i]; lists[tagName] = lists[tagName] || []; lists[tagName].push(room); - otherTagNames[tagName] = 1; } } else if (dmRoomMap.getUserIdForRoomId(room.roomId)) { From 40154df9304877daccf6da1b46cd2e6db09d1d6a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 30 May 2017 16:14:27 +0100 Subject: [PATCH 079/275] Show People/Rooms emptySubListTip even when total rooms !== 0 --- src/components/views/rooms/RoomList.js | 35 +++++++++++++------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 0bca41e9e4..d672dea504 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -510,24 +510,23 @@ module.exports = React.createClass({ const StartChatButton = sdk.getComponent('elements.StartChatButton'); const RoomDirectoryButton = sdk.getComponent('elements.RoomDirectoryButton'); const CreateRoomButton = sdk.getComponent('elements.CreateRoomButton'); - if (this.state.totalRoomCount === 0) { - const TintableSvg = sdk.getComponent('elements.TintableSvg'); - switch (section) { - case 'im.vector.fake.direct': - return
- Press - - to start a chat with someone -
; - case 'im.vector.fake.recent': - return
- You're not in any rooms yet! Press - - to make a room or - - to browse the directory -
; - } + + const TintableSvg = sdk.getComponent('elements.TintableSvg'); + switch (section) { + case 'im.vector.fake.direct': + return
+ Press + + to start a chat with someone +
; + case 'im.vector.fake.recent': + return
+ You're not in any rooms yet! Press + + to make a room or + + to browse the directory +
; } if (this.state.totalRoomCount === 0) { From c15568e003a9a32c37bf6600b796698cea66cd41 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 30 May 2017 21:05:26 +0100 Subject: [PATCH 080/275] remove spurious string --- src/i18n/strings/en_EN.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 15879f80ee..11727223e3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -583,7 +583,6 @@ "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s", "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", "Set a display name:": "Set a display name:", - "Set a Display Name": "Set a Display Name", "Upload an avatar:": "Upload an avatar:", "This server does not support authentication with a phone number.": "This server does not support authentication with a phone number.", "Missing password.": "Missing password.", From d83f18ab4669ae2d9b80ef06c3b16c698e5df4b0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 31 May 2017 10:03:16 +0100 Subject: [PATCH 081/275] Remove cachedPassword from localStorage on_logged_out Fixes https://github.com/vector-im/riot-web/issues/4101 --- src/stores/SessionStore.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 62868e4fe4..6ec8ae7697 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -69,7 +69,9 @@ class SessionStore extends Store { }); break; case 'on_logged_out': - this.reset(); + this._setState({ + cachedPassword: null, + }); break; } } From d0e270bd1c24244a5dc7cd09801dac60fd792432 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 31 May 2017 15:13:27 +0100 Subject: [PATCH 082/275] Only re-render LoggedInView if MatrixClientPeg.get() is truthy --- src/components/structures/LoggedInView.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index a297952a2c..67e2fe8856 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -24,6 +24,7 @@ import PageTypes from '../../PageTypes'; import sdk from '../../index'; import dis from '../../dispatcher'; import sessionStore from '../../stores/SessionStore'; +import MatrixClientPeg from '../../MatrixClientPeg'; /** * This is what our MatrixChat shows when we are logged in. The precise view is @@ -91,6 +92,16 @@ export default React.createClass({ } }, + // Child components assume that the client peg will not be null, so give them some + // sort of assurance here by only allowing a re-render if the client is truthy. + // + // This is required because `LoggedInView` maintains its own state and if this state + // updates after the client peg has been made null (during logout), then it will + // attempt to re-render and the children will throw errors. + shouldComponentUpdate: function() { + return Boolean(MatrixClientPeg.get()); + }, + getScrollStateForRoom: function(roomId) { return this._scrollStateMap[roomId]; }, From b3a862c2c2f0fe2c0381ea12936775d46c86d894 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 31 May 2017 15:32:55 +0100 Subject: [PATCH 083/275] Remove redundant `reset` --- src/stores/SessionStore.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/stores/SessionStore.js b/src/stores/SessionStore.js index 6ec8ae7697..c4bd39b72c 100644 --- a/src/stores/SessionStore.js +++ b/src/stores/SessionStore.js @@ -76,10 +76,6 @@ class SessionStore extends Store { } } - reset() { - this._state = Object.assign({}, INITIAL_STATE); - } - getCachedPassword() { return this._state.cachedPassword; } From 8192374481935d79a27e61a967a965f2918e4f59 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 31 May 2017 16:02:42 +0100 Subject: [PATCH 084/275] Add missing _t import --- src/components/views/login/LoginFooter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/login/LoginFooter.js b/src/components/views/login/LoginFooter.js index a5183ffff3..8bdec71685 100644 --- a/src/components/views/login/LoginFooter.js +++ b/src/components/views/login/LoginFooter.js @@ -16,6 +16,7 @@ limitations under the License. 'use strict'; +import { _t } from '../../../languageHandler'; import React from 'react'; module.exports = React.createClass({ @@ -27,5 +28,5 @@ module.exports = React.createClass({ {_t("powered by Matrix")}
); - } + }, }); From dd48b3f055c6197efb28d802b9b8eb29944229a5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 1 Jun 2017 10:08:02 +0100 Subject: [PATCH 085/275] Add comment --- src/components/views/rooms/RoomList.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index d672dea504..15f8b34312 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -529,6 +529,7 @@ module.exports = React.createClass({
; } + // We don't want to display drop targets if there are no room tiles to drag'n'drop if (this.state.totalRoomCount === 0) { return null; } From 16c4c14a16acf40650f61f338e241c4e6c67fbdf Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 1 Jun 2017 18:01:30 +0100 Subject: [PATCH 086/275] Fix to show the correct room --- src/components/structures/RoomView.js | 9 +++- src/stores/RoomViewStore.js | 65 ++++++++++++++++++--------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 2189fa3856..9a930d3d06 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -171,7 +171,7 @@ module.exports = React.createClass({ }); // Start listening for RoomViewStore updates - RoomViewStore.addListener(this._onRoomViewStoreUpdate); + this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate); this._onRoomViewStoreUpdate(true); }, @@ -182,6 +182,8 @@ module.exports = React.createClass({ this.setState({ roomId: RoomViewStore.getRoomId(), roomAlias: RoomViewStore.getRoomAlias(), + roomLoading: RoomViewStore.isRoomLoading(), + roomLoadError: RoomViewStore.getRoomLoadError(), joining: RoomViewStore.isJoining(), joinError: RoomViewStore.getJoinError(), }, () => { @@ -343,6 +345,11 @@ module.exports = React.createClass({ document.removeEventListener("keydown", this.onKeyDown); + // Remove RoomStore listener + if (this._roomStoreToken) { + this._roomStoreToken.remove(); + } + // cancel any pending calls to the rate_limited_funcs this._updateRoomMembers.cancelPendingCall(); diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index d893318af7..a74652a39d 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -58,6 +58,9 @@ class RoomViewStore extends Store { case 'view_room': this._viewRoom(payload); break; + case 'view_room_error': + this._viewRoomError(payload); + break; case 'will_join': this._setState({ joining: true, @@ -80,31 +83,45 @@ class RoomViewStore extends Store { } _viewRoom(payload) { - const address = payload.room_alias || payload.room_id; - if (address[0] == '#') { + // Always set the room ID if present + if (payload.room_id) { this._setState({ - roomLoading: true, - }); - MatrixClientPeg.get().getRoomIdForAlias(address).then( - (result) => { - this._setState({ - roomId: result.room_id, - roomAlias: address, - roomLoading: false, - roomLoadError: null, - }); - }, (err) => { - console.error(err); - this._setState({ - roomLoading: false, - roomLoadError: err, - }); - }); - } else { - this._setState({ - roomId: address, + roomId: payload.room_id, }); } + + if (payload.room_alias && !payload.room_id) { + this._setState({ + roomId: null, + roomAlias: payload.room_alias, + roomLoading: true, + roomLoadError: null, + }); + MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias).done( + (result) => { + dis.dispatch({ + action: 'view_room', + room_id: result.room_id, + room_alias: payload.room_alias, + }); + }, (err) => { + dis.dispatch({ + action: 'view_room_error', + room_id: null, + room_alias: payload.room_alias, + err: err, + }); + }); + } + } + + _viewRoomError(payload) { + this._setState({ + roomId: payload.room_id, + roomAlias: payload.room_alias, + roomLoading: false, + roomLoadError: payload.err, + }); } _joinRoom(payload) { @@ -140,6 +157,10 @@ class RoomViewStore extends Store { return this._state.roomLoading; } + getRoomLoadError() { + return this._state.roomLoadError; + } + isJoining() { return this._state.joining; } From 7808994b719ef4cce19c9bcca3aba52315c1fc9a Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 2 Jun 2017 09:22:48 +0100 Subject: [PATCH 087/275] Modify RVS test to wait until room loaded This allows for the alias resolution to occur before a join is attempted. In theory, join_room could in future do an optional view_room-esque thing before attemping a join which would be less fragile than dispatching things in the right order. Also, make sure the store indicates that it is not loading when a room ID has been used - no alias resolution need take place. --- src/stores/RoomViewStore.js | 6 +++--- test/stores/RoomViewStore-test.js | 15 +++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index a74652a39d..b94e772b02 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -87,10 +87,10 @@ class RoomViewStore extends Store { if (payload.room_id) { this._setState({ roomId: payload.room_id, + roomLoading: false, + roomLoadError: null, }); - } - - if (payload.room_alias && !payload.room_id) { + } else if (payload.room_alias) { this._setState({ roomId: null, roomAlias: payload.room_alias, diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js index 7100dced19..2f545ffd74 100644 --- a/test/stores/RoomViewStore-test.js +++ b/test/stores/RoomViewStore-test.js @@ -45,12 +45,15 @@ describe('RoomViewStore', function() { done(); }; - dispatch({ action: 'view_room', room_alias: '#somealias2:aser.ver' }); + RoomViewStore.addListener(() => { + // Wait until the room alias has resolved and the room ID is + if (!RoomViewStore.isRoomLoading()) { + expect(RoomViewStore.getRoomId()).toBe("!randomcharacters:aser.ver"); + dispatch({ action: 'join_room' }); + expect(RoomViewStore.isJoining()).toBe(true); + } + }); - // Wait for the next event loop to allow for room alias resolution - setTimeout(() => { - dispatch({ action: 'join_room' }); - expect(RoomViewStore.isJoining()).toBe(true); - }, 0); + dispatch({ action: 'view_room', room_alias: '#somealias2:aser.ver' }); }); }); From defecb1b147bb2525af9d9fe20325be2311cec02 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 1 Jun 2017 14:16:25 +0100 Subject: [PATCH 088/275] Implement /user/@userid:domain?action=chat This is a URL that can be used to start a chat with a user. - If the user is a guest, setMxId dialog will appear before anything and a defered action will cause `ChatCreateOrReuseDialog` to appear once they've logged in. - If the user is registered, they will not see the setMxId dialog. fixes https://github.com/vector-im/riot-web/issues/4034 --- src/components/structures/MatrixChat.js | 64 +++++++- src/components/views/avatars/BaseAvatar.js | 1 + .../views/dialogs/ChatCreateOrReuseDialog.js | 152 +++++++++++++----- .../views/dialogs/ChatInviteDialog.js | 21 ++- src/createRoom.js | 1 + src/i18n/strings/en_EN.json | 8 +- src/stores/LifecycleStore.js | 2 + 7 files changed, 202 insertions(+), 47 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index ff864379fa..a081ce6fe7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -139,6 +139,10 @@ module.exports = React.createClass({ register_hs_url: null, register_is_url: null, register_id_sid: null, + + // Whether a DM should be created with welcomeUserId (prop) on registration + // see _onLoggedIn + shouldCreateWelcomeDm: true, }; return s; }, @@ -378,6 +382,11 @@ module.exports = React.createClass({ }); this.notifyNewScreen('forgot_password'); break; + case 'start_chat': + createRoom({ + dmUserId: payload.user_id, + }); + break; case 'leave_room': this._leaveRoom(payload.room_id); break; @@ -474,6 +483,9 @@ module.exports = React.createClass({ case 'view_set_mxid': this._setMxId(); break; + case 'view_start_chat_or_reuse': + this._chatCreateOrReuse(payload.user_id); + break; case 'view_create_chat': this._createChat(); break; @@ -707,6 +719,50 @@ module.exports = React.createClass({ }); }, + _chatCreateOrReuse: function(userId) { + const ChatCreateOrReuseDialog = sdk.getComponent( + 'views.dialogs.ChatCreateOrReuseDialog', + ); + if (MatrixClientPeg.get().isGuest()) { + dis.dispatch({ + action: 'do_after_sync_prepared', + deferred_action: { + action: 'view_start_chat_or_reuse', + user_id: userId, + }, + }); + dis.dispatch({ + action: 'view_set_mxid', + }); + return; + } + + const close = Modal.createDialog(ChatCreateOrReuseDialog, { + userId: userId, + onFinished: (success) => { + if (!success) { + // Dialog cancelled, default to home + dis.dispatch({ action: 'view_home_page' }); + } + }, + onNewDMClick: () => { + dis.dispatch({ + action: 'start_chat', + user_id: userId, + }); + // Close the dialog, indicate success (calls onFinished(true)) + close(true); + }, + onExistingRoomSelected: (roomId) => { + dis.dispatch({ + action: 'view_room', + room_id: roomId, + }); + close(true); + }, + }).close; + }, + _invite: function(roomId) { const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog"); Modal.createDialog(ChatInviteDialog, { @@ -838,7 +894,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().getUserIdLocalpart() ); - if (this.props.config.welcomeUserId) { + if (this.props.config.welcomeUserId && this.state.shouldCreateWelcomeDm) { createRoom({ dmUserId: this.props.config.welcomeUserId, andView: false, @@ -1043,6 +1099,12 @@ module.exports = React.createClass({ } } else if (screen.indexOf('user/') == 0) { const userId = screen.substring(5); + + if (params.action === 'chat') { + this._chatCreateOrReuse(userId); + return; + } + this.setState({ viewUserId: userId }); this._setPage(PageTypes.UserView); this.notifyNewScreen('user/' + userId); diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js index 65730be40b..a4443430f4 100644 --- a/src/components/views/avatars/BaseAvatar.js +++ b/src/components/views/avatars/BaseAvatar.js @@ -32,6 +32,7 @@ module.exports = React.createClass({ urls: React.PropTypes.array, // [highest_priority, ... , lowest_priority] width: React.PropTypes.number, height: React.PropTypes.number, + // XXX resizeMethod not actually used. resizeMethod: React.PropTypes.string, defaultToInitialLetter: React.PropTypes.bool // true to add default url }, diff --git a/src/components/views/dialogs/ChatCreateOrReuseDialog.js b/src/components/views/dialogs/ChatCreateOrReuseDialog.js index f563af6691..93ebf8cc2f 100644 --- a/src/components/views/dialogs/ChatCreateOrReuseDialog.js +++ b/src/components/views/dialogs/ChatCreateOrReuseDialog.js @@ -18,34 +18,30 @@ import React from 'react'; import sdk from '../../../index'; import dis from '../../../dispatcher'; import MatrixClientPeg from '../../../MatrixClientPeg'; +import { _t } from '../../../languageHandler'; import DMRoomMap from '../../../utils/DMRoomMap'; import AccessibleButton from '../elements/AccessibleButton'; import Unread from '../../../Unread'; import classNames from 'classnames'; import createRoom from '../../../createRoom'; +import { RoomMember } from "matrix-js-sdk"; export default class ChatCreateOrReuseDialog extends React.Component { constructor(props) { super(props); - this.onNewDMClick = this.onNewDMClick.bind(this); this.onRoomTileClick = this.onRoomTileClick.bind(this); + + this.state = { + tiles: [], + profile: { + displayName: null, + avatarUrl: null, + }, + }; } - onNewDMClick() { - createRoom({dmUserId: this.props.userId}); - this.props.onFinished(true); - } - - onRoomTileClick(roomId) { - dis.dispatch({ - action: 'view_room', - room_id: roomId, - }); - this.props.onFinished(true); - } - - render() { + componentWillMount() { const client = MatrixClientPeg.get(); const dmRoomMap = new DMRoomMap(client); @@ -70,40 +66,115 @@ export default class ChatCreateOrReuseDialog extends React.Component { highlight={highlight} isInvite={me.membership == "invite"} onClick={this.onRoomTileClick} - /> + />, ); } } - const labelClasses = classNames({ - mx_MemberInfo_createRoom_label: true, - mx_RoomTile_name: true, + this.setState({ + tiles: tiles, }); - const startNewChat = -
- -
-
{_("Start new chat")}
-
; + + if (tiles.length === 0) { + this.setState({ + busyProfile: true, + }); + MatrixClientPeg.get().getProfileInfo(this.props.userId).then((resp) => { + const profile = { + displayName: resp.displayname, + avatarUrl: null, + }; + if (resp.avatar_url) { + profile.avatarUrl = MatrixClientPeg.get().mxcUrlToHttp( + resp.avatar_url, 48, 48, "crop", + ); + } + this.setState({ + profile: profile, + }); + }, (err) => { + console.error('Unable to get profile for user', this.props.userId, err); + }).finally(() => { + this.setState({ + busyProfile: false, + }); + }); + } + } + + onRoomTileClick(roomId) { + this.props.onExistingRoomSelected(roomId); + } + + render() { + let title = ''; + let content = null; + if (this.state.tiles.length > 0) { + // Show the existing rooms with a "+" to add a new dm + title = _t('Create a new chat or reuse an existing one'); + const labelClasses = classNames({ + mx_MemberInfo_createRoom_label: true, + mx_RoomTile_name: true, + }); + const startNewChat = +
+ +
+
{ _t("Start new chat") }
+
; + content =
+ { _t('You already have existing direct chats with this user:') } +
+ { this.state.tiles } + { startNewChat } +
+
; + } else { + // Show the avatar, name and a button to confirm that a new chat is requested + const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); + const Spinner = sdk.getComponent('elements.Spinner'); + title = _t('Start chatting'); + + let profile = null; + if (this.state.busyProfile) { + profile = ; + } else { + profile =
+ +
+ {this.state.profile.displayName || this.props.userId} +
+
; + } + content =
+
+

+ { _t('Click on the button below to start chatting!') } +

+ { profile } +
+
+ +
+
; + } const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); return ( { - this.props.onFinished(false) - }} - title='Create a new chat or reuse an existing one' + onFinished={ this.props.onFinished.bind(false) } + title={title} > -
- You already have existing direct chats with this user: -
- {tiles} - {startNewChat} -
-
+ { content }
); } @@ -111,5 +182,8 @@ export default class ChatCreateOrReuseDialog extends React.Component { ChatCreateOrReuseDialog.propTyps = { userId: React.PropTypes.string.isRequired, + // Called when clicking outside of the dialog onFinished: React.PropTypes.func.isRequired, + onNewDMClick: React.PropTypes.func.isRequired, + onExistingRoomSelected: React.PropTypes.func.isRequired, }; diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index b50a782073..f475635212 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -95,16 +95,25 @@ module.exports = React.createClass({ // A Direct Message room already exists for this user, so select a // room from a list that is similar to the one in MemberInfo panel const ChatCreateOrReuseDialog = sdk.getComponent( - "views.dialogs.ChatCreateOrReuseDialog" + "views.dialogs.ChatCreateOrReuseDialog", ); Modal.createDialog(ChatCreateOrReuseDialog, { userId: userId, onFinished: (success) => { - if (success) { - this.props.onFinished(true, inviteList[0]); - } - // else show this ChatInviteDialog again - } + this.props.onFinished(success); + }, + onNewDMClick: () => { + dis.dispatch({ + action: 'start_chat', + user_id: userId, + }); + }, + onExistingRoomSelected: (roomId) => { + dis.dispatch({ + action: 'view_room', + user_id: roomId, + }); + }, }); } else { this._startChat(inviteList); diff --git a/src/createRoom.js b/src/createRoom.js index f476a86dcc..1522dbc9a8 100644 --- a/src/createRoom.js +++ b/src/createRoom.js @@ -97,6 +97,7 @@ function createRoom(opts) { // the room exists, causing things like // https://github.com/vector-im/vector-web/issues/1813 if (opts.andView) { + console.info('And viewing'); dis.dispatch({ action: 'view_room', room_id: roomId, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 11727223e3..c8d9614961 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -771,5 +771,11 @@ "Idle": "Idle", "Offline": "Offline", "disabled": "disabled", - "enabled": "enabled" + "enabled": "enabled", + "Start chatting": "Start chatting", + "Start Chatting": "Start Chatting", + "Click on the button below to start chatting!": "Click on the button below to start chatting!", + "Create a new chat or reuse an existing one": "Create a new chat or reuse an existing one", + "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", + "Start new chat": "Start new chat" } diff --git a/src/stores/LifecycleStore.js b/src/stores/LifecycleStore.js index d38138b3ef..b06c03b778 100644 --- a/src/stores/LifecycleStore.js +++ b/src/stores/LifecycleStore.js @@ -41,6 +41,7 @@ class LifecycleStore extends Store { __onDispatch(payload) { switch (payload.action) { case 'do_after_sync_prepared': + console.info('Will do after sync', payload.deferred_action); this._setState({ deferred_action: payload.deferred_action, }); @@ -49,6 +50,7 @@ class LifecycleStore extends Store { if (payload.state !== 'PREPARED') { break; } + console.info('Doing', payload.deferred_action); if (!this._state.deferred_action) break; const deferredAction = Object.assign({}, this._state.deferred_action); this._setState({ From 6a9781f0231c532fde87f99e78ce84a5b3cfbdc2 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 2 Jun 2017 11:41:09 +0100 Subject: [PATCH 089/275] Remove redundant state --- src/components/structures/MatrixChat.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index a081ce6fe7..7b51fdb524 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -139,10 +139,6 @@ module.exports = React.createClass({ register_hs_url: null, register_is_url: null, register_id_sid: null, - - // Whether a DM should be created with welcomeUserId (prop) on registration - // see _onLoggedIn - shouldCreateWelcomeDm: true, }; return s; }, @@ -894,7 +890,7 @@ module.exports = React.createClass({ MatrixClientPeg.get().getUserIdLocalpart() ); - if (this.props.config.welcomeUserId && this.state.shouldCreateWelcomeDm) { + if (this.props.config.welcomeUserId) { createRoom({ dmUserId: this.props.config.welcomeUserId, andView: false, From e88b52fa8fd49cfca3517338c2a1da4558875fff Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 2 Jun 2017 11:42:47 +0100 Subject: [PATCH 090/275] Add comment --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 7b51fdb524..5791ffe49a 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -719,6 +719,7 @@ module.exports = React.createClass({ const ChatCreateOrReuseDialog = sdk.getComponent( 'views.dialogs.ChatCreateOrReuseDialog', ); + // Use a deferred action to reshow the dialog once the user has registered if (MatrixClientPeg.get().isGuest()) { dis.dispatch({ action: 'do_after_sync_prepared', From 6e84b6e996db49511a9ec5315ce210ef07275cbc Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 2 Jun 2017 11:50:58 +0100 Subject: [PATCH 091/275] Display profile errors better --- .../views/dialogs/ChatCreateOrReuseDialog.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/views/dialogs/ChatCreateOrReuseDialog.js b/src/components/views/dialogs/ChatCreateOrReuseDialog.js index 93ebf8cc2f..fdb4e994ae 100644 --- a/src/components/views/dialogs/ChatCreateOrReuseDialog.js +++ b/src/components/views/dialogs/ChatCreateOrReuseDialog.js @@ -38,6 +38,7 @@ export default class ChatCreateOrReuseDialog extends React.Component { displayName: null, avatarUrl: null, }, + profileError: null, }; } @@ -79,7 +80,7 @@ export default class ChatCreateOrReuseDialog extends React.Component { this.setState({ busyProfile: true, }); - MatrixClientPeg.get().getProfileInfo(this.props.userId).then((resp) => { + MatrixClientPeg.get().getProfileInfo(this.props.userId).done((resp) => { const profile = { displayName: resp.displayname, avatarUrl: null, @@ -90,13 +91,17 @@ export default class ChatCreateOrReuseDialog extends React.Component { ); } this.setState({ + busyProfile: false, profile: profile, }); }, (err) => { - console.error('Unable to get profile for user', this.props.userId, err); - }).finally(() => { + console.error( + 'Unable to get profile for user ' + this.props.userId + ':', + err, + ); this.setState({ busyProfile: false, + profileError: err, }); }); } @@ -141,6 +146,10 @@ export default class ChatCreateOrReuseDialog extends React.Component { let profile = null; if (this.state.busyProfile) { profile = ; + } else if (this.state.profileError) { + profile =
+ Unable to load profile information for { this.props.userId } +
; } else { profile =
Date: Fri, 2 Jun 2017 11:53:10 +0100 Subject: [PATCH 092/275] Propagate room join errors to the UI Dispatch so we can set the state in RoomViewStore. Show the error when the room join fails (unsure if it's better to do this from the component or the store). Remove unused joinError from roomview. --- src/components/structures/RoomView.js | 1 - src/stores/RoomViewStore.js | 47 +++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 9a930d3d06..3151fd28f9 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -185,7 +185,6 @@ module.exports = React.createClass({ roomLoading: RoomViewStore.isRoomLoading(), roomLoadError: RoomViewStore.getRoomLoadError(), joining: RoomViewStore.isJoining(), - joinError: RoomViewStore.getJoinError(), }, () => { this._onHaveRoom(); this.onRoom(MatrixClientPeg.get().getRoom(this.state.roomId)); diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index b94e772b02..b0957ec3df 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -16,6 +16,9 @@ limitations under the License. import dis from '../dispatcher'; import {Store} from 'flux/utils'; import MatrixClientPeg from '../MatrixClientPeg'; +import sdk from '../index'; +import Modal from '../Modal'; +import { _t } from '../languageHandler'; const INITIAL_STATE = { // Whether we're joining the currently viewed room @@ -76,6 +79,12 @@ class RoomViewStore extends Store { case 'join_room': this._joinRoom(payload); break; + case 'joined_room': + this._joinedRoom(payload); + break; + case 'join_room_error': + this._joinRoomError(payload); + break; case 'on_logged_out': this.reset(); break; @@ -128,19 +137,43 @@ class RoomViewStore extends Store { this._setState({ joining: true, }); - MatrixClientPeg.get().joinRoom(this._state.roomId, payload.opts).then( - () => { - this._setState({ - joining: false, + MatrixClientPeg.get().joinRoom(this._state.roomId, payload.opts).done(() => { + dis.dispatch({ + action: 'joined_room', + room_id: this._state.roomId, }); }, (err) => { - this._setState({ - joining: false, - joinError: err, + dis.dispatch({ + action: 'join_room_error', + room_id: this._state.roomId, + err: err, + }); + const msg = err.message ? err.message : JSON.stringify(err); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createDialog(ErrorDialog, { + title: _t("Failed to join room"), + description: msg, }); }); } + _joinedRoom(payload) { + if (payload.room_id === this._state.roomId) { + this._setState({ + joining: false, + }); + } + } + + _joinRoomError(payload) { + if (payload.room_id === this._state.roomId) { + this._setState({ + joining: false, + joinError: payload.err, + }); + } + } + reset() { this._state = Object.assign({}, INITIAL_STATE); } From 95e38eb9c458fb0cc8e5a56a8277e0510c966957 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 2 Jun 2017 12:02:37 +0100 Subject: [PATCH 093/275] Remove cryptic log --- src/createRoom.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/createRoom.js b/src/createRoom.js index 1522dbc9a8..f476a86dcc 100644 --- a/src/createRoom.js +++ b/src/createRoom.js @@ -97,7 +97,6 @@ function createRoom(opts) { // the room exists, causing things like // https://github.com/vector-im/vector-web/issues/1813 if (opts.andView) { - console.info('And viewing'); dis.dispatch({ action: 'view_room', room_id: roomId, From f52035f3cd7aa63db1a3c56ef23af16092dce868 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 2 Jun 2017 13:41:41 +0100 Subject: [PATCH 094/275] Set state from dispatch payload unconditionally As apparently doing it confitionally is bad --- src/stores/RoomViewStore.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index b0957ec3df..6ba0e45f68 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -158,20 +158,16 @@ class RoomViewStore extends Store { } _joinedRoom(payload) { - if (payload.room_id === this._state.roomId) { - this._setState({ - joining: false, - }); - } + this._setState({ + joining: false, + }); } _joinRoomError(payload) { - if (payload.room_id === this._state.roomId) { - this._setState({ - joining: false, - joinError: payload.err, - }); - } + this._setState({ + joining: false, + joinError: payload.err, + }); } reset() { From ac0f2f79d18d6b9e2ec2a98b85f4d9150acc24d6 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 2 Jun 2017 16:02:20 +0100 Subject: [PATCH 095/275] Remove redundant room_id --- src/stores/RoomViewStore.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 6ba0e45f68..cc8959af7a 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -140,12 +140,10 @@ class RoomViewStore extends Store { MatrixClientPeg.get().joinRoom(this._state.roomId, payload.opts).done(() => { dis.dispatch({ action: 'joined_room', - room_id: this._state.roomId, }); }, (err) => { dis.dispatch({ action: 'join_room_error', - room_id: this._state.roomId, err: err, }); const msg = err.message ? err.message : JSON.stringify(err); From 2cc9f9c4030fb81f844ee4c3aeaee020e5b790ee Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 2 Jun 2017 16:25:14 +0100 Subject: [PATCH 096/275] Fix accepting a 3pid invite Fixes https://github.com/vector-im/riot-web/issues/4123 --- src/components/structures/RoomView.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 3151fd28f9..3be7073a4f 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -764,11 +764,13 @@ module.exports = React.createClass({ // If the user is a ROU, allow them to transition to a PWLU if (cli && cli.isGuest()) { // Join this room once the user has registered and logged in + const signUrl = this.props.thirdPartyInvite ? + this.props.thirdPartyInvite.inviteSignUrl : undefined; dis.dispatch({ action: 'do_after_sync_prepared', deferred_action: { action: 'join_room', - room_id: this.state.roomId, + opts: { inviteSignUrl: signUrl }, }, }); From ae91f0ca62478e9722ac9828ac7fba54d6a3f547 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 21:34:18 +0100 Subject: [PATCH 097/275] catch ev arg so the disable stuff works Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/login/RegistrationForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/login/RegistrationForm.js b/src/components/views/login/RegistrationForm.js index daabb7cb61..75feab0f12 100644 --- a/src/components/views/login/RegistrationForm.js +++ b/src/components/views/login/RegistrationForm.js @@ -121,7 +121,7 @@ module.exports = React.createClass({ } }, - _doSubmit: function() { + _doSubmit: function(ev) { let email = this.refs.email.value.trim(); var promise = this.props.onRegisterClick({ username: this.refs.username.value.trim() || this.props.guestUsername, From 464863acd6200a42fba52e107e7e31e4c5c20819 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 21:35:55 +0100 Subject: [PATCH 098/275] remove unused imports Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/CallMediaHandler.js | 1 - src/MatrixClientPeg.js | 1 - src/Rooms.js | 1 - src/autocomplete/Components.js | 1 - src/autocomplete/UserProvider.js | 1 - src/components/structures/CreateRoom.js | 1 - src/components/structures/InteractiveAuth.js | 2 -- src/components/structures/RoomStatusBar.js | 1 - src/components/structures/login/Login.js | 1 - src/components/structures/login/Registration.js | 2 -- src/components/views/dialogs/ChatInviteDialog.js | 3 --- src/components/views/dialogs/InteractiveAuthDialog.js | 2 -- src/components/views/dialogs/UnknownDeviceDialog.js | 1 - src/components/views/elements/AddressTile.js | 2 -- src/components/views/elements/LanguageDropdown.js | 1 - src/components/views/login/PasswordLogin.js | 1 - src/components/views/messages/MAudioBody.js | 1 - src/components/views/messages/MFileBody.js | 1 - src/components/views/messages/MVideoBody.js | 2 -- src/components/views/rooms/Autocomplete.js | 2 +- src/components/views/rooms/MessageComposerInput.js | 1 - src/components/views/rooms/PresenceLabel.js | 2 -- src/index.js | 2 -- src/languageHandler.js | 1 - 24 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/CallMediaHandler.js b/src/CallMediaHandler.js index 45ca5dc30d..839b496845 100644 --- a/src/CallMediaHandler.js +++ b/src/CallMediaHandler.js @@ -16,7 +16,6 @@ import UserSettingsStore from './UserSettingsStore'; import * as Matrix from 'matrix-js-sdk'; -import q from 'q'; export default { getDevices: function() { diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index 452b67c4ee..94e55a8d8a 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -16,7 +16,6 @@ limitations under the License. 'use strict'; -import q from "q"; import Matrix from 'matrix-js-sdk'; import utils from 'matrix-js-sdk/lib/utils'; import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline'; diff --git a/src/Rooms.js b/src/Rooms.js index 08fa7f797f..16b5ab9ee2 100644 --- a/src/Rooms.js +++ b/src/Rooms.js @@ -15,7 +15,6 @@ limitations under the License. */ import MatrixClientPeg from './MatrixClientPeg'; -import DMRoomMap from './utils/DMRoomMap'; import q from 'q'; /** diff --git a/src/autocomplete/Components.js b/src/autocomplete/Components.js index b26a217ec6..0f0399cf7d 100644 --- a/src/autocomplete/Components.js +++ b/src/autocomplete/Components.js @@ -15,7 +15,6 @@ limitations under the License. */ import React from 'react'; -import ReactDOM from 'react-dom'; import classNames from 'classnames'; /* These were earlier stateless functional components but had to be converted diff --git a/src/autocomplete/UserProvider.js b/src/autocomplete/UserProvider.js index fedebb3618..809fec94be 100644 --- a/src/autocomplete/UserProvider.js +++ b/src/autocomplete/UserProvider.js @@ -18,7 +18,6 @@ limitations under the License. import React from 'react'; import { _t } from '../languageHandler'; import AutocompleteProvider from './AutocompleteProvider'; -import Q from 'q'; import Fuse from 'fuse.js'; import {PillCompletion} from './Components'; import sdk from '../index'; diff --git a/src/components/structures/CreateRoom.js b/src/components/structures/CreateRoom.js index 8b3d035dc1..0a4a30d24a 100644 --- a/src/components/structures/CreateRoom.js +++ b/src/components/structures/CreateRoom.js @@ -17,7 +17,6 @@ limitations under the License. 'use strict'; import React from 'react'; -import q from 'q'; import { _t } from '../../languageHandler'; import sdk from '../../index'; import MatrixClientPeg from '../../MatrixClientPeg'; diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js index 7c8a5b8065..dee8400a08 100644 --- a/src/components/structures/InteractiveAuth.js +++ b/src/components/structures/InteractiveAuth.js @@ -19,8 +19,6 @@ const InteractiveAuth = Matrix.InteractiveAuth; import React from 'react'; -import sdk from '../../index'; - import {getEntryComponentForLoginType} from '../views/login/InteractiveAuthEntryComponents'; export default React.createClass({ diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 5a9592243a..f8a3d340b7 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -17,7 +17,6 @@ limitations under the License. import React from 'react'; import { _t } from '../../languageHandler'; import sdk from '../../index'; -import dis from '../../dispatcher'; import WhoIsTyping from '../../WhoIsTyping'; import MatrixClientPeg from '../../MatrixClientPeg'; import MemberAvatar from '../views/avatars/MemberAvatar'; diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index 8848a33deb..a15068e058 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -19,7 +19,6 @@ limitations under the License. import React from 'react'; import { _t, _tJsx } from '../../../languageHandler'; -import ReactDOM from 'react-dom'; import sdk from '../../../index'; import Login from '../../../Login'; diff --git a/src/components/structures/login/Registration.js b/src/components/structures/login/Registration.js index d9b7c46b6b..85fb18f13b 100644 --- a/src/components/structures/login/Registration.js +++ b/src/components/structures/login/Registration.js @@ -21,11 +21,9 @@ import q from 'q'; import React from 'react'; import sdk from '../../../index'; -import dis from '../../../dispatcher'; import ServerConfig from '../../views/login/ServerConfig'; import MatrixClientPeg from '../../../MatrixClientPeg'; import RegistrationForm from '../../views/login/RegistrationForm'; -import CaptchaForm from '../../views/login/CaptchaForm'; import RtsClient from '../../../RtsClient'; import { _t } from '../../../languageHandler'; diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index 7dd5b05041..cd294a123d 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -15,15 +15,12 @@ limitations under the License. */ import React from 'react'; -import classNames from 'classnames'; import { _t } from '../../../languageHandler'; import sdk from '../../../index'; import { getAddressType, inviteMultipleToRoom } from '../../../Invite'; import createRoom from '../../../createRoom'; import MatrixClientPeg from '../../../MatrixClientPeg'; import DMRoomMap from '../../../utils/DMRoomMap'; -import rate_limited_func from '../../../ratelimitedfunc'; -import dis from '../../../dispatcher'; import Modal from '../../../Modal'; import AccessibleButton from '../elements/AccessibleButton'; import q from 'q'; diff --git a/src/components/views/dialogs/InteractiveAuthDialog.js b/src/components/views/dialogs/InteractiveAuthDialog.js index 51561270c4..945e0a9d69 100644 --- a/src/components/views/dialogs/InteractiveAuthDialog.js +++ b/src/components/views/dialogs/InteractiveAuthDialog.js @@ -15,8 +15,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import Matrix from 'matrix-js-sdk'; - import React from 'react'; import sdk from '../../../index'; diff --git a/src/components/views/dialogs/UnknownDeviceDialog.js b/src/components/views/dialogs/UnknownDeviceDialog.js index 9ffad5d32a..8f91b84519 100644 --- a/src/components/views/dialogs/UnknownDeviceDialog.js +++ b/src/components/views/dialogs/UnknownDeviceDialog.js @@ -16,7 +16,6 @@ limitations under the License. import React from 'react'; import sdk from '../../../index'; -import dis from '../../../dispatcher'; import MatrixClientPeg from '../../../MatrixClientPeg'; import GeminiScrollbar from 'react-gemini-scrollbar'; import Resend from '../../../Resend'; diff --git a/src/components/views/elements/AddressTile.js b/src/components/views/elements/AddressTile.js index 33cc7f9923..78fd942a46 100644 --- a/src/components/views/elements/AddressTile.js +++ b/src/components/views/elements/AddressTile.js @@ -19,9 +19,7 @@ limitations under the License. import React from 'react'; import classNames from 'classnames'; import sdk from "../../../index"; -import Invite from "../../../Invite"; import MatrixClientPeg from "../../../MatrixClientPeg"; -import Avatar from '../../../Avatar'; import { _t } from '../../../languageHandler'; // React PropType definition for an object describing diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index 49f89aa469..c5ed1f8942 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -19,7 +19,6 @@ import React from 'react'; import sdk from '../../../index'; import UserSettingsStore from '../../../UserSettingsStore'; -import { _t } from '../../../languageHandler'; import * as languageHandler from '../../../languageHandler'; function languageMatchesSearchQuery(query, language) { diff --git a/src/components/views/login/PasswordLogin.js b/src/components/views/login/PasswordLogin.js index 972516b553..46a48d14a0 100644 --- a/src/components/views/login/PasswordLogin.js +++ b/src/components/views/login/PasswordLogin.js @@ -16,7 +16,6 @@ limitations under the License. */ import React from 'react'; -import ReactDOM from 'react-dom'; import classNames from 'classnames'; import sdk from '../../../index'; import { _t } from '../../../languageHandler'; diff --git a/src/components/views/messages/MAudioBody.js b/src/components/views/messages/MAudioBody.js index 0b6214b9bf..52c1341e60 100644 --- a/src/components/views/messages/MAudioBody.js +++ b/src/components/views/messages/MAudioBody.js @@ -20,7 +20,6 @@ import React from 'react'; import MFileBody from './MFileBody'; import MatrixClientPeg from '../../../MatrixClientPeg'; -import sdk from '../../../index'; import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile'; import { _t } from '../../../languageHandler'; diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js index 1bb9464999..bccae923eb 100644 --- a/src/components/views/messages/MFileBody.js +++ b/src/components/views/messages/MFileBody.js @@ -24,7 +24,6 @@ import { _t } from '../../../languageHandler'; import {decryptFile} from '../../../utils/DecryptFile'; import Tinter from '../../../Tinter'; import request from 'browser-request'; -import q from 'q'; import Modal from '../../../Modal'; diff --git a/src/components/views/messages/MVideoBody.js b/src/components/views/messages/MVideoBody.js index 8caf9d8f96..46d8366592 100644 --- a/src/components/views/messages/MVideoBody.js +++ b/src/components/views/messages/MVideoBody.js @@ -19,8 +19,6 @@ limitations under the License. import React from 'react'; import MFileBody from './MFileBody'; import MatrixClientPeg from '../../../MatrixClientPeg'; -import Model from '../../../Modal'; -import sdk from '../../../index'; import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile'; import q from 'q'; import UserSettingsStore from '../../../UserSettingsStore'; diff --git a/src/components/views/rooms/Autocomplete.js b/src/components/views/rooms/Autocomplete.js index 9be91e068a..5f6bac0007 100644 --- a/src/components/views/rooms/Autocomplete.js +++ b/src/components/views/rooms/Autocomplete.js @@ -4,7 +4,7 @@ import classNames from 'classnames'; import flatMap from 'lodash/flatMap'; import isEqual from 'lodash/isEqual'; import sdk from '../../../index'; -import type {Completion, SelectionRange} from '../../../autocomplete/Autocompleter'; +import type {Completion} from '../../../autocomplete/Autocompleter'; import Q from 'q'; import {getCompletions} from '../../../autocomplete/Autocompleter'; diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 65148f91ef..d3010044e5 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -33,7 +33,6 @@ import sdk from '../../../index'; import { _t } from '../../../languageHandler'; import dis from '../../../dispatcher'; -import KeyCode from '../../../KeyCode'; import UserSettingsStore from '../../../UserSettingsStore'; import * as RichText from '../../../RichText'; diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.js index b79de2b21c..47a723f5cd 100644 --- a/src/components/views/rooms/PresenceLabel.js +++ b/src/components/views/rooms/PresenceLabel.js @@ -18,8 +18,6 @@ limitations under the License. import React from 'react'; -import MatrixClientPeg from '../../../MatrixClientPeg'; -import sdk from '../../../index'; import { _t } from '../../../languageHandler'; diff --git a/src/index.js b/src/index.js index 03b854a112..7d0547d9c9 100644 --- a/src/index.js +++ b/src/index.js @@ -15,8 +15,6 @@ limitations under the License. */ import Skinner from './Skinner'; -import request from 'browser-request'; -import UserSettingsStore from './UserSettingsStore'; module.exports.loadSkin = function(skinObject) { Skinner.load(skinObject); diff --git a/src/languageHandler.js b/src/languageHandler.js index 798798b6e5..0e8b08018f 100644 --- a/src/languageHandler.js +++ b/src/languageHandler.js @@ -18,7 +18,6 @@ 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'; From 4032a820f0961dea44cd5bb2a2fdeacef69701c4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jun 2017 21:46:08 +0100 Subject: [PATCH 099/275] move KEY_M to KeyCode Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/KeyCode.js | 1 + src/components/views/rooms/MessageComposerInput.js | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/KeyCode.js b/src/KeyCode.js index c9cac01239..28aafc00cb 100644 --- a/src/KeyCode.js +++ b/src/KeyCode.js @@ -32,4 +32,5 @@ module.exports = { DELETE: 46, KEY_D: 68, KEY_E: 69, + KEY_M: 77, }; diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index d3010044e5..1c92a9339e 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -28,6 +28,7 @@ import Q from 'q'; import MatrixClientPeg from '../../../MatrixClientPeg'; import type {MatrixClient} from 'matrix-js-sdk/lib/matrix'; import SlashCommands from '../../../SlashCommands'; +import KeyCode from '../../../KeyCode'; import Modal from '../../../Modal'; import sdk from '../../../index'; import { _t } from '../../../languageHandler'; @@ -44,8 +45,6 @@ import {onSendMessageFailed} from './MessageComposerInputOld'; const TYPING_USER_TIMEOUT = 10000, TYPING_SERVER_TIMEOUT = 30000; -const KEY_M = 77; - const ZWS_CODE = 8203; const ZWS = String.fromCharCode(ZWS_CODE); // zero width space function stateToMarkdown(state) { @@ -61,7 +60,7 @@ function stateToMarkdown(state) { export default class MessageComposerInput extends React.Component { static getKeyBinding(e: SyntheticKeyboardEvent): string { // C-m => Toggles between rich text and markdown modes - if (e.keyCode === KEY_M && KeyBindingUtil.isCtrlKeyCommand(e)) { + if (e.keyCode === KeyCode.KEY_M && KeyBindingUtil.isCtrlKeyCommand(e)) { return 'toggle-mode'; } From fc97518ce9a903e69618777fcd14eb3459fcbcad Mon Sep 17 00:00:00 2001 From: zzottel Date: Fri, 2 Jun 2017 19:55:06 +0000 Subject: [PATCH 100/275] Translated using Weblate (German) Currently translated at 100.0% (827 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 4209792d51..68125f1961 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1,5 +1,5 @@ { - "Filter room members": "Raum Benutzer filtern", + "Filter room members": "Raum-Benutzer filtern", "You have no visible notifications": "Du hast keine sichtbaren Benachrichtigungen", "Invites": "Einladungen", "Favourites": "Favoriten", From 9db280544319b30d2ae4ce777f75e25533cb27ab Mon Sep 17 00:00:00 2001 From: jx tsai Date: Fri, 2 Jun 2017 16:14:30 +0000 Subject: [PATCH 101/275] Translated using Weblate (Chinese (Traditional)) Currently translated at 42.8% (354 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 2966aaa558..d99387c16e 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -326,5 +326,31 @@ "Friday": "星期五", "Saturday": "星期六", "OK": "OK", - "Please Register": "請註冊" + "Please Register": "請註冊", + "Add a topic": "新增標題", + "VoIP": "VoIP", + "Default Device": "默認裝置", + "Microphone": "麥克風", + "Camera": "攝影機", + "Anyone": "任何人", + "Bulk Options": "批次選項", + "Command error": "指令出錯", + "Commands": "指令", + "Device ID:": "裝置 ID:", + "device id: ": "裝置 id:", + "Reason": "原因", + "Register": "注冊", + "Registration required": "要求註冊", + "rejected": "拒絕", + "Default server": "默認的伺服器", + "Custom server": "自定的伺服器", + "Home server URL": "自家伺服器網址", + "Identity server URL": "識別伺服器網址", + "What does this mean?": "它代表什麼意思?", + "Error decrypting audio": "解密音檔出錯", + "Error decrypting image": "解密圖片出錯", + "Image '%(Body)s' cannot be displayed.": "圖片 '%(Body)s' 無法顯示", + "This image cannot be displayed.": "這張圖片無法顯示", + "Error decrypting video": "解密影片出錯", + "Add an Integration": "新增整合器" } From 1e679d3db21f1ca2bf8f201c099ee961fa0d81c7 Mon Sep 17 00:00:00 2001 From: Rob van den Berg Date: Fri, 2 Jun 2017 20:13:48 +0000 Subject: [PATCH 102/275] Translated using Weblate (Dutch) Currently translated at 24.1% (200 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/nl/ --- src/i18n/strings/nl.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index b89c360792..226706c884 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -198,5 +198,6 @@ "Confirm password": "Bevestigen wachtwoord", "Confirm your new password": "Bevestig je nieuwe wachtwoord", "Continue": "Doorgaan", - "Could not connect to the integration server": "Mislukt om te verbinden met de integratie server" + "Could not connect to the integration server": "Mislukt om te verbinden met de integratie server", + "Cancel": "Annuleer" } From 357dd7ca1923a9b0040dab9f2fbc85823092da68 Mon Sep 17 00:00:00 2001 From: Vladi Date: Fri, 2 Jun 2017 21:03:53 +0000 Subject: [PATCH 103/275] Translated using Weblate (Russian) Currently translated at 75.9% (628 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 743aade542..992426fd9c 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -237,7 +237,7 @@ "Conference calls are not supported in encrypted rooms": "Конференц-вызовы не поддерживаются в зашифрованных комнатах", "Conference calls are not supported in this client": "Конференц-вызовы не поддерживаются в этом клиенте", "/ddg is not a command": "/ddg не команда", - "Drop here %(toAction)s": "Вставить здесь %(toAction)s", + "Drop here %(toAction)s": "Вставить сюда для %(toAction)s", "Drop here to tag %(section)s": "Вставить здесь для тега %(section)s", "%(senderName)s ended the call.": "%(senderName)s прекратил звонок.", "Existing Call": "Существующий вызов", @@ -258,7 +258,7 @@ "Missing room_id in request": "Отсутствует room_id в запросе", "Missing user_id in request": "Отсутствует user_id в запросе", "Must be viewing a room": "Комната должна быть посищена", - "New Composer & Autocomplete": "Новые Компонист & Автозаполнение", + "New Composer & Autocomplete": "Новый едитор & Автозаполнение", "(not supported by this browser)": "(не поддерживаемый этим браузером)", "af": "Африкаанс", "ar-ae": "Арабский (О.А.Е)", @@ -397,7 +397,7 @@ "Unable to enable Notifications": "Невозможно включить уведомления", "Upload Failed": "Неудавшаяся загрузка", "Usage": "Использование", - "Use with caution": "Используйте с осторожностью", + "Use with caution": "Использовать осторожно", "VoIP is unsupported": "VoIP не поддерживается", "es-pr": "Испанский (Пуэрто-Рико)", "es-py": "Испанский язык (Парагвай)", @@ -426,7 +426,7 @@ "sk": "Словацкий", "sl": "Словенский", "sq": "Албанский", - "sr": "Сербский (Латиница)", + "sr": "Сербский", "sv-fi": "Шведский (Финляндия)", "sz": "Саами (лопарский)", "tn": "Тсвана", @@ -443,7 +443,7 @@ "fr-lu": "Французский (Люксембург)", "gd": "Гэльский (Шотландия)", "it-ch": "Итальянский (Швейцария)", - "ko": "Корейский (Johab)", + "ko": "Корейский", "mk": "Македонский (FYROM)", "ro-mo": "Румынский (Республика Молдова)", "sx": "Суту", @@ -522,7 +522,7 @@ "No devices with registered encryption keys": "Нет устройств с записанными ключами шифрования", "No more results": "Нет больше результатов", "No results": "Нет результатов", - "OK": "Да", + "OK": "ОК", "Only people who have been invited": "Только приглашённые люди", "Passwords can't be empty": "Пароли не могут быть пустыми", "%(senderName)s placed a %(callType)s call.": "%(senderName)s выполнил %(callType)s вызов.", @@ -584,7 +584,7 @@ "This room has no local addresses": "Эта комната не имеет местного адреса", "This room is not recognised.": "Эта комната не опознана.", "This room is private or inaccessible to guests. You may be able to join if you register": "Эта комната личная или недоступна для гостей. Мы может быть войдёте, если зарегистрируйтесь", - "These are experimental features that may break in unexpected ways": "Это экспериментальные возможности, которые могут сломаться неожиданным образом", + "These are experimental features that may break in unexpected ways": "Это экспериментальные функции, которые могут неожиданным образом вызывать ошибки", "This doesn't appear to be a valid email address": "Не похоже, что это правильный адрес электронной почты", "This is a preview of this room. Room interactions have been disabled": "Это просмотр данной комнаты. Взаимодействия с ней были отключены.", "This phone number is already in use": "Этот телефонный номер уже используется", @@ -624,7 +624,7 @@ "%(severalUsers)sjoined and left": "%(severalUsers)sвошли и ушли", "%(oneUser)sjoined and left": "%(oneUser)sвошёл и ушёл", "%(severalUsers)sleft and rejoined %(repeats)s times": "%(severalUsers)sушли и перезашли %(repeats)s раз", - "%(oneUser)sleft and rejoined %(repeats)s times": "%(oneUser)sушёл и перезашёл %(repeats)s раз", + "%(oneUser)sleft and rejoined %(repeats)s times": "%(oneUser)s ушёл и перезашёл %(repeats)s раз", "%(severalUsers)sleft and rejoined": "%(severalUsers)sушли и перезашли", "%(oneUser)sleft and rejoined": "%(oneUser)sушёл и перезашёл", "%(severalUsers)srejected their invitations %(repeats)s times": "%(severalUsers)sотклонили приглашения %(repeats)s раз", @@ -651,5 +651,19 @@ "%(oneUser)schanged their avatar %(repeats)s times": "%(oneUser)sизменил своё изображение %(repeats)s раз", "%(severalUsers)schanged their avatar": "%(severalUsers)sизменили своё изображение", "%(oneUser)schanged their avatar": "%(oneUser)sизменил своё изображение", - "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Не возможно подключиться к серверу через HTTP, когда в строке браузера HTTPS. Используйте HTTPS или включив небезопасные скрипты." + "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Не возможно подключиться к серверу через HTTP, когда в строке браузера HTTPS. Используйте HTTPS или включив небезопасные скрипты.", + "Dismiss": "Отказ", + "Custom Server Options": "Расширенные настройки сервера", + "Mute": "Беззвучный", + "Operation failed": "Действие не удалось", + "powered by Matrix": "управляемый с Matrix", + "Add a topic": "Добавить тему", + "Show timestamps in 12 hour format (e.g. 2:30pm)": "Времея отображать в 12 часовом формате (напр. 2:30pm)", + "Use compact timeline layout": "Используйте компактным указанием времени", + "Hide removed messages": "Скрыть удаленное сообщение", + "No Microphones detected": "Микрофоны не обнаружены", + "Unknown devices": "Незнакомое устройство", + "Camera": "Камера", + "Microphone": "Микрофон", + "Desktop specific": "Специфический десктоп" } From dd78ae63b22489830346d2fc36273eaaaddbedb3 Mon Sep 17 00:00:00 2001 From: Max Sandholm Date: Fri, 2 Jun 2017 13:46:19 +0000 Subject: [PATCH 104/275] Translated using Weblate (Swedish) Currently translated at 21.5% (178 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/sv/ --- src/i18n/strings/sv.json | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index cb57beac14..5b376a22d6 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -159,8 +159,22 @@ "An email has been sent to": "Ett epostmeddelande har sänts till", "A new password must be entered.": "Ett nytt lösenord måste anges.", "%(senderName)s answered the call.": "%(senderName)s svarade på samtalet.", - "Anyone who knows the room's link, including guests": "Vem som hel", + "Anyone who knows the room's link, including guests": "Alla som har rummets adress, inklusive gäster", "anyone": "vem som helst", "Anyone": "Vem som helst", - "Anyone who knows the room's link, apart from guests": "Alla som har rummets address, förutom gäster" + "Anyone who knows the room's link, apart from guests": "Alla som har rummets adress, förutom gäster", + "An error has occurred.": "Ett fel har inträffat.", + "Are you sure?": "Är du säker?", + "Are you sure you want to leave the room '%(roomName)s'?": "Vill du lämna rummet '%(roomName)s'?", + "Are you sure you want to upload the following files?": "Vill du ladda upp följande filer?", + "Autoplay GIFs and videos": "Spela automatiskt upp GIFar och videor", + "Are you sure you want to reject the invitation?": "Vill du avvisa inbjudan?", + "Bulk Options": "Volymhandlingar", + "Bug Report": "Buggrapport", + "Blacklisted": "Svartlistad", + "%(senderName)s banned %(targetName)s.": "%(senderName)s bannade %(targetName)s.", + "Banned users": "Bannade användare", + "Bans user with given id": "Bannar användaren med givet ID", + "Ban": "Banna", + "Attachment": "Bilaga" } From b934127508b0c2c6ecfbaf189727be37b56ac162 Mon Sep 17 00:00:00 2001 From: mujx Date: Fri, 2 Jun 2017 21:58:11 +0000 Subject: [PATCH 105/275] Added translation using Weblate (Greek) --- src/i18n/strings/el.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/i18n/strings/el.json diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/src/i18n/strings/el.json @@ -0,0 +1 @@ +{} \ No newline at end of file From 2f5d4e79d757c59f2aa02dbbc70040249cb9c7d0 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Fri, 2 Jun 2017 21:41:09 +0000 Subject: [PATCH 106/275] Translated using Weblate (German) Currently translated at 99.8% (826 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 43da1f958f..e231d2bdaf 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -292,7 +292,7 @@ "Riot does not have permission to send you notifications - please check your browser settings": "Riot hat keine Berechtigung Benachrichtigungen zu senden - bitte prüfe deine Browser-Einstellungen", "Riot was not given permission to send notifications - please try again": "Riot hat das Recht nicht bekommen Benachrichtigungen zu senden. Bitte erneut probieren", "This email address is already in use": "Diese E-Mail-Adresse wird bereits verwendet", - "This email address was not found": "Diese E-Mail-Adresse wurde nicht gefunden", + "This email address was not found": "Diese E-Mail-Adresse konnte nicht gefunden werden", "The file '%(fileName)s' exceeds this home server's size limit for uploads": "Die Datei '%(fileName)s' überschreitet das Größen-Limit für Uploads auf diesem Homeserver", "The file '%(fileName)s' failed to upload": "Das Hochladen der Datei '%(fileName)s' schlug fehl", "The remote side failed to pick up": "Die Gegenstelle konnte nicht abheben", @@ -349,7 +349,7 @@ "%(targetName)s accepted an invitation.": "%(targetName)s hat eine Einladung angenommen.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s akzeptierte die Einladung für %(displayName)s.", "%(names)s and one other are typing": "%(names)s und eine weitere Person tippen", - "%(names)s and %(count)s others are typing": "%(names)s und %(count)s weitere Personen tippen", + "%(names)s and %(count)s others are typing": "%(names)s und %(count)s weitere Personen schreiben", "%(senderName)s answered the call.": "%(senderName)s beantwortete den Anruf.", "%(senderName)s banned %(targetName)s.": "%(senderName)s hat %(targetName)s aus dem Raum verbannt.", "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s hat den Anzeigenamen von %(oldDisplayName)s auf %(displayName)s geändert.", @@ -576,7 +576,7 @@ "Failed to delete device": "Löschen des Geräts fehlgeschlagen", "Failed to join room": "Betreten des Raumes ist fehlgeschlagen", "Failed to kick": "Kicken fehlgeschlagen", - "Failed to mute user": "Nutzer lautlos zu stellen fehlgeschlagen", + "Failed to mute user": "Stummschalten des Nutzers fehlgeschlagen", "Failed to reject invite": "Ablehnen der Einladung ist fehlgeschlagen", "Failed to save settings": "Einstellungen konnten nicht gespeichert werden", "Failed to set display name": "Anzeigename konnte nicht gesetzt werden", @@ -687,10 +687,10 @@ "were unbanned": "wurden entbannt", "were kicked %(repeats)s times": "wurden %(repeats)s mal gekickt", "was kicked %(repeats)s times": "wurde %(repeats)s mal gekickt", - "were kicked": "wurden gekickt", + "were kicked": "wurden aus dem Raum entfernt", "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)sänderten %(repeats)s mal ihre Namen", "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)sänderte %(repeats)s mal seinen/ihren Namen", - "%(severalUsers)schanged their name": "%(severalUsers)sänderten ihre Namen", + "%(severalUsers)schanged their name": "%(severalUsers)shaben ihre Namen geändert", "%(oneUser)schanged their name": "%(oneUser)sänderte seinen/ihren Namen", "%(severalUsers)schanged their avatar %(repeats)s times": "%(severalUsers)shaben %(repeats)s mal ihren Avatar geändert", "%(oneUser)schanged their avatar %(repeats)s times": "%(oneUser)sänderte %(repeats)s mal seinen/ihren Avatar", @@ -738,7 +738,7 @@ "You must join the room to see its files": "Du musst dem Raum beitreten, um die Raum-Dateien sehen zu können", "Server may be unavailable, overloaded, or you hit a bug.": "Server ist nicht verfügbar, überlastet oder du bist auf einen Fehler gestoßen.", "Reject all %(invitedRooms)s invites": "Alle %(invitedRooms)s Einladungen ablehnen", - "Start new chat": "Starte neuen Chat", + "Start new Chat": "Starte neuen Chat", "Guest users can't invite users. Please register.": "Gäste können keine Nutzer einladen. Bitte registrieren.", "Failed to invite": "Einladen fehlgeschlagen", "Failed to invite user": "Einladen des Nutzers fehlgeschlagen", @@ -884,7 +884,7 @@ "You cannot place VoIP calls in this browser.": "Du kannst keine VoIP-Gespräche in diesem Browser starten.", "You have disabled URL previews by default.": "Du hast die URL-Vorschau standardmäßig deaktiviert.", "You have enabled URL previews by default.": "Du hast die URL-Vorschau standardmäßig aktiviert.", - "You have entered an invalid contact. Try using their Matrix ID or email address.": "Du hast einen invaliden Kontakt eingegeben. Versuche es mit der Matrix-ID oder E-Mail-Adresse.", + "You have entered an invalid contact. Try using their Matrix ID or email address.": "Du hast einen ungültigen Kontakt eingegeben. Versuche es mit der Matrix-ID oder der E-Mail-Adresse.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Heimserver verbunden zu sein.", "$senderDisplayName changed the room avatar to ": "$senderDisplayName änderte das Raum-Bild zu ", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s änderte das Bild für %(roomName)s", From 1ff8a9ac7604c74bf8e837ee433d6d19fdaa3642 Mon Sep 17 00:00:00 2001 From: Vladi Date: Fri, 2 Jun 2017 21:20:30 +0000 Subject: [PATCH 107/275] Translated using Weblate (Russian) Currently translated at 76.5% (633 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 992426fd9c..37b36de963 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -94,7 +94,7 @@ "Hangup": "Отключение", "Historical": "Исторический", "Homeserver is": "Домашний сервер является", - "Identity Server is": "Регистрационный Сервер является", + "Identity Server is": "Регистрационный сервер", "I have verified my email address": "Я проверил мой адрес электронной почты", "Import E2E room keys": "Импортировать E2E ключ комнаты", "Invalid Email Address": "Недействительный адрес электронной почты", @@ -665,5 +665,10 @@ "Unknown devices": "Незнакомое устройство", "Camera": "Камера", "Microphone": "Микрофон", - "Desktop specific": "Специфический десктоп" + "Desktop specific": "Специфический десктоп", + "Start automatically after system login": "Автостарт после входа в систему", + "Analytics": "Аналитика", + "Riot collects anonymous analytics to allow us to improve the application.": "Riot собирет анонимные данные, чтобы улутшыть эту програму.", + "Opt out of analytics": "Подтвердить отказ передачи аналитических данных", + "Logged in as:": "Зарегестрирован как:" } From 9fdb3df9d845523297beace75013977c20284072 Mon Sep 17 00:00:00 2001 From: RiotTranslate Date: Sat, 3 Jun 2017 13:43:43 +0200 Subject: [PATCH 108/275] Update from Weblate. (#1017) * Translated using Weblate (Chinese (Traditional)) Currently translated at 43.8% (363 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/zh_Hant/ * Translated using Weblate (Greek) Currently translated at 23.2% (192 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/el/ * Translated using Weblate (Russian) Currently translated at 76.5% (633 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (Portuguese) Currently translated at 99.8% (826 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/pt/ * Translated using Weblate (Greek) Currently translated at 24.3% (201 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/el/ * Translated using Weblate (Greek) Currently translated at 24.5% (203 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/el/ * Translated using Weblate (Greek) Currently translated at 31.8% (263 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/el/ --- src/i18n/strings/el.json | 266 +++++++++++++++++++++++++++++++++- src/i18n/strings/pt.json | 22 +-- src/i18n/strings/ru.json | 4 +- src/i18n/strings/zh_Hant.json | 11 +- 4 files changed, 288 insertions(+), 15 deletions(-) diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 9e26dfeeb6..20ec222c6f 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -1 +1,265 @@ -{} \ No newline at end of file +{ + "af": "Αφρικάνικα", + "Error": "Σφάλμα", + "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου", + "Failed to join the room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο", + "Mute": "Σίγαση", + "Notifications": "Ειδοποιήσεις", + "Operation failed": "Η λειτουργία απέτυχε", + "Please Register": "Παρακαλώ εγγραφείτε", + "Remove": "Αφαίρεσε", + "Search": "Αναζήτηση", + "Settings": "Ρυθμίσεις", + "unknown error code": "άγνωστος κωδικός σφάλματος", + "Sunday": "Κυριακή", + "ar-ae": "Αραβικά (Η.Α.Ε)", + "ar-bh": "Αραβικά (Μπαχρέιν)", + "ar-dz": "Αραβικά (Αλγερία)", + "ar-eg": "Αραβικά (Αίγυπτος)", + "ar-iq": "Αραβικά (Ιράκ)", + "ar-jo": "Αραβικά (Ιορδανία)", + "ar-kw": "Αραβικά (Κουβέιτ)", + "ar-lb": "Αραβικά (Λίβανος)", + "ar-ly": "Αραβικά (Λιβύη)", + "ar-ma": "Αραβικά (Μαρόκο)", + "ar-om": "Αραβικά (Ομάν)", + "ar-qa": "Αραβικά (Κατάρ)", + "ar-sa": "Αραβικά (Σαουδική Αραβία)", + "ar-sy": "Αραβικά (Συρία)", + "ar-tn": "Αραβικά (Τυνισία)", + "ar-ye": "Αραβικά (Υεμένη)", + "accept": "αποδοχή", + "%(targetName)s accepted an invitation.": "%(targetName)s δέχτηκε την πρόσκληση.", + "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s δέχτηκες την πρόσκληση για %(displayName)s.", + "Account": "Λογαριασμός", + "Add a topic": "Πρόσθεσε μια περιγραφή", + "Add email address": "Πρόσθεσε ένα email", + "Add phone number": "Πρόσθεσε έναν αριθμό τηλεφώνου", + "Admin": "Διαχειριστής", + "VoIP": "VoIP", + "No Microphones detected": "Δεν εντοπίστηκε μικρόφωνο", + "No Webcams detected": "Δεν εντοπίστηκε κάμερα", + "Default Device": "Προεπιλεγμένη Συσκευή", + "Microphone": "Μικρόφωνο", + "Camera": "Κάμερα", + "Advanced": "Προχωρημένα", + "Algorithm": "Αλγόριθμος", + "Hide removed messages": "Κρύψε διαγραμμένα μηνύματα", + "Authentication": "Πιστοποίηση", + "and": "και", + "An email has been sent to": "Ένα email στάλθηκε σε", + "A new password must be entered.": "Ο νέος κωδικός πρέπει να εισαχθεί", + "%(senderName)s answered the call.": "Ο χρήστης %(senderName)s απάντησε.", + "An error has occurred.": "Ένα σφάλμα προέκυψε", + "Anyone": "Oποιοσδήποτε", + "Are you sure?": "Είσαι σίγουρος;", + "Are you sure you want to leave the room '%(roomName)s'?": "Είσαι σίγουρος οτι θές να φύγεις από το δωμάτιο '%(roomName)s';", + "Are you sure you want to reject the invitation?": "Είσαι σίγουρος οτι θες να απορρίψεις την πρόσκληση;", + "Are you sure you want to upload the following files?": "Είσαι σίγουρος οτι θές να ανεβάσεις τα ακόλουθα αρχεία;", + "Attachment": "Επισύναψη", + "%(senderName)s banned %(targetName)s.": "Ο χρήστης %(senderName)s έδιωξε τον χρήστη %(targetName)s.", + "Autoplay GIFs and videos": "Αυτόματη αναπαραγωγή GIFs και βίντεο", + "Bug Report": "Αναφορά Σφάλματος", + "anyone": "οποιοσδήποτε", + "Anyone who knows the room's link, apart from guests": "Oποιοσδήποτε", + "all room members, from the point they joined": "όλα τα μέλη του δωματίου, από τη στιγμή που συνδέθηκαν", + "%(items)s and %(lastItem)s": "%(items)s %(lastItem)s", + "be": "Λευκορώσικα", + "bg": "Βουλγάρικα", + "ca": "Καταλανικά", + "cs": "Τσέχικα", + "da": "Δανέζικα", + "de-at": "Γερμανικά (Αυστρία)", + "de-ch": "Γερμανικά (Ελβετία)", + "de": "Γερμανικά", + "de-li": "Γερμανικά (Λιχτενστάιν)", + "de-lu": "Γερμανικά (Λουξεμβούργο)", + "el": "Ελληνικά", + "en-au": "Αγγλικά (Αυστραλία)", + "en-bz": "Αγγλικά (Μπελίζε)", + "en-ca": "Αγγλικά (Καναδάς)", + "en": "Αγγλικά", + "en-gb": "Αγγλικά (Ηνωμένο Βασίλειο)", + "en-ie": "Αγγλικά (Ιρλανδία)", + "en-jm": "Αγγλικά (Τζαμάικα)", + "en-nz": "Αγγλικά (Νέα Ζηλανδία)", + "en-tt": "Αγγλικά (Τρινιντάντ)", + "en-us": "Αγγλικά (Ηνωμένες Πολιτείες)", + "en-za": "Αγγλικά (Νότια Αφρική)", + "es-ar": "Ισπανικά (Αργεντινή)", + "es-bo": "Ισπανικά (Βολιβία)", + "es-cl": "Ισπανικά (Χιλή)", + "es-co": "Ισπανικά (Κολομβία)", + "es-cr": "Ισπανικά (Κόστα Ρίκα)", + "es-do": "Ισπανικά (Δομινικανή Δημοκρατία)", + "es-ec": "Ισπανικά (Ισημερινός)", + "es-gt": "Ισπανικά (Γουατεμάλα)", + "es-hn": "Ισπανικά (Ονδούρα)", + "es-mx": "Ισπανικά (Μεξικό)", + "es-ni": "Ισπανικά (Νικαράγουα)", + "es-pa": "Ισπανικά (Παναμάς)", + "es-pe": "Ισπανικά (Περού)", + "es-pr": "Ισπανικά (Πουέρτο Ρίκο)", + "es-py": "Ισπανικά (Παραγουάη)", + "es": "Ισπανικά (Ισπανία)", + "es-sv": "Ισπανικά (Ελ Σαλβαδόρ)", + "es-uy": "Ισπανικά (Ουρουγουάη)", + "es-ve": "Ισπανικά (Βενεζουέλα)", + "et": "Εσθονικά", + "eu": "Βασκική (βασκική)", + "fa": "Φάρσι", + "fi": "Φινλανδικά", + "fo": "Φαρόε", + "fr-be": "Γαλλικά (Βέλγιο)", + "fr-ca": "Γαλλικά (Καναδάς)", + "fr-ch": "Γαλλικά (Ελβετία)", + "fr": "Γαλλικά", + "fr-lu": "Γαλλικά (Λουξεμβούργο)", + "ga": "Ιρλανδικά", + "gd": "Γαελική (Σκωτία)", + "he": "Εβραϊκά", + "hi": "Χίντι", + "hr": "Κροατικά", + "hu": "Ουγγρικά", + "is": "Ισλανδικά", + "it-ch": "Ιταλικά (Ελβετία)", + "it": "Ιταλικά", + "ja": "Ιαπωνικά", + "ji": "Γίντις", + "ko": "Κορεάτικα", + "lt": "Λιθουανικά", + "mk": "Μακεδονική (ΠΓΔΜ)", + "ms": "Μαλαισίας", + "mt": "Μαλτέζικα", + "nl-be": "Ολλανδικά (Βέλγιο)", + "nl": "Ολλανδικά", + "no": "Νορβηγικά", + "pl": "Πολωνέζικα", + "pt-br": "Πορτογαλικά Βραζιλίας", + "pt": "Πορτογαλικά", + "rm": "Ραιτορωμαϊκά", + "ro-mo": "Ρουμάνικα (Δημοκρατία της Μολδαβίας)", + "ro": "Ρουμάνικα", + "ru-mo": "Ρώσικα (Δημοκρατία της Μολδαβίας)", + "ru": "Ρώσικα", + "sb": "Σορβικά", + "sk": "Σλοβάκικα", + "sl": "Σλοβενικά", + "sq": "Αλβανικά", + "sr": "Σερβικά", + "sv-fi": "Σουηδικά (Φινλανδία)", + "sv": "Σουηδικά", + "sx": "Σούτου", + "sz": "Σάμη (Λαπωνικά)", + "th": "Ταϊλανδέζικα", + "tn": "Τσουάνα", + "tr": "Τουρκικά", + "ts": "Τσονγκά", + "uk": "Ουκρανικά", + "ur": "Ουρντού", + "ve": "Venda", + "vi": "Βιετναμέζικα", + "xh": "Xhosa", + "zh-cn": "Κινέζικα (ΛΔΚ)", + "zh-hk": "Κινέζικα (ΕΔΠ Χονγκ Κονγκ)", + "zh-sg": "Κινέζικα (Σιγκαπούρη)", + "zh-tw": "Κινέζικα (Ταϊβάν)", + "zu": "Ζουλού", + "id": "Ινδονησιακά", + "lv": "Λετονικά", + "A registered account is required for this action": "Ένας εγγεγραμμένος λογαριασμός απαιτείται για αυτή την ενέργεια", + "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Ένα μήνυμα στάλθηκε στο +%(msisdn)s. Παρακαλώ γράψε τον κωδικό επαλήθευσης που περιέχει", + "Access Token:": "Κωδικός Πρόσβασης:", + "Always show message timestamps": "Δείχνε πάντα ένδειξη ώρας στα μηνύματα", + "all room members": "όλα τα μέλη του δωματίου", + "all room members, from the point they are invited": "όλα τα μέλη του δωματίου, από τη στιγμή που προσκλήθηκαν", + "an address": "μία διεύθηνση", + "%(items)s and %(remaining)s others": "%(items)s και %(remaining)s ακόμα", + "%(items)s and one other": "%(items)s και ένας ακόμα", + "and %(overflowCount)s others...": "και %(overflowCount)s άλλοι...", + "and one other...": "και ένας ακόμα...", + "%(names)s and %(lastPerson)s are typing": "%(names)s και %(lastPerson)s γράφουν", + "%(names)s and one other are typing": "%(names)s και ένας ακόμα γράφουν", + "%(names)s and %(count)s others are typing": "%(names)s και %(count)s άλλοι γράφουν", + "Anyone who knows the room's link, including guests": "Οποιοσδήποτε γνωρίζει τον σύνδεδμο του δωματίου, συμπεριλαμβάνωντας τους επισκέπτες", + "Blacklisted": "Στη μαύρη λίστα", + "Can't load user settings": "Δεν είναι δυνατή η φόρτωση των ρυθμίσεων χρήστη", + "Change Password": "Αλλαγή Κωδικού", + "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "ο χρήστης %(senderName)s άλλαξε το όνομά του από %(oldDisplayName)s σε %(displayName)s.", + "%(senderName)s changed their profile picture.": "ο χρήστης %(senderName)s άλλαξε τη φωτογραφία του προφίλ του.", + "%(senderDisplayName)s changed the room name to %(roomName)s.": "Ο χρήστης %(senderDisplayName)s άλλαξε το όνομα του δωματίου σε %(roomName)s.", + "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "Ο χρήστης %(senderDisplayName)s άλλαξε το θέμα σε \"%(topic)s\".", + "Clear Cache and Reload": "Καθάρισε την μνήμη και Ανανέωσε", + "Clear Cache": "Καθάρισε την μνήμη", + "Bans user with given id": "Διώχνει τον χρήστη με το συγκεκριμένο id", + "%(senderDisplayName)s removed the room name.": "Ο χρήστης %(senderDisplayName)s διέγραψε το όνομα του δωματίου.", + "Changes your display nickname": "Αλλάζει το όνομα χρήστη", + "Click here": "Κάνε κλικ εδώ", + "Drop here %(toAction)s": "Άφησε εδώ %(toAction)s", + "Conference call failed.": "Η κλήση συνδιάσκεψης απέτυχε.", + "powered by Matrix": "βασισμένο στο πρωτόκολλο Matrix", + "Confirm password": "Επιβεβαίωση κωδικού", + "Confirm your new password": "Επιβεβαίωση του νέου κωδικού", + "Continue": "Συνέχεια", + "Create an account": "Δημιουργία λογαριασμού", + "Create Room": "Δημιουργία Δωματίου", + "Cryptography": "Κρυπτογραφία", + "Current password": "Τωρινός κωδικός", + "Curve25519 identity key": "Κλειδί ταυτότητας Curve25519", + "Custom level": "Προσαρμοσμένο επίπεδο", + "/ddg is not a command": "/ddg δεν αναγνωρίζεται ως εντολή", + "Deactivate Account": "Απενεργοποίηση Λογαριασμού", + "Deactivate my account": "Απενεργοποίηση του λογαριασμού μου", + "decline": "απόρριψη", + "Decrypt %(text)s": "Αποκρυπτογράφησε %(text)s", + "Decryption error": "Σφάλμα αποκρυπτογράφησης", + "(default: %(userName)s)": "(προεπιλογή: %(userName)s)", + "Delete": "Διαγραφή", + "Default": "Προεπιλογή", + "Device already verified!": "Η συσκευή έχει ήδη επαληθευτεί!", + "Device ID": "ID Συσκευής", + "Device ID:": "ID Συσκευής:", + "device id: ": "id συσκευής: ", + "Device key:": "Κλειδί Συσκευής:", + "Devices": "Συσκευές", + "Direct Chat": "Απευθείας Συνομιλία", + "Direct chats": "Απευθείας συνομιλίες", + "disabled": "ανενεργό", + "Disinvite": "Ανακάλεσε πρόσκληση", + "Display name": "Όνομα χρήστη", + "Download %(text)s": "Κατέβασε %(text)s", + "Ed25519 fingerprint": "Αποτύπωμα Ed25519", + "Email": "Ηλ. Αλληλογραφία", + "Email address": "Διεύθυνση email", + "Email address (optional)": "Διεύθυνση email (προαιρετικό)", + "Email, name or matrix ID": "Email, όνομα ή matrix ID", + "Emoji": "Εικονίδια", + "enabled": "ενεργό", + "Encrypted messages will not be visible on clients that do not yet implement encryption": "Τα κρυπτογραφημένα μηνύματα δεν θα είναι ορατά σε εφαρμογές που δεν παρέχουν τη δυνατότητα κρυπτογράφησης", + "Encrypted room": "Κρυπτογραφημένο δωμάτιο", + "%(senderName)s ended the call.": "%(senderName)s τερμάτισε την κλήση.", + "End-to-end encryption information": "Πληροφορίες σχετικά με τη κρυπτογράφηση από άκρο σε άκρο (End-to-end encryption)", + "Error decrypting attachment": "Σφάλμα κατά την αποκρυπτογράφηση της επισύναψης", + "Event information": "Πληροφορίες μηνύματος", + "Existing Call": "Υπάρχουσα Κλήση", + "Export": "Εξαγωγή", + "Export E2E room keys": "Εξαγωγή κλειδιών κρυπτογραφίας για το δωμάτιο", + "Failed to change password. Is your password correct?": "Δεν ήταν δυνατή η αλλαγή του κωδικού. Είναι ο κωδικός σωστός;", + "Failed to delete device": "Δεν ήταν δυνατή η διαγραφή της συσκευής", + "Failed to join room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο", + "Failed to leave room": "Δεν ήταν δυνατή η αποχώρηση από το δωμάτιο", + "Failed to mute user": "Δεν ήταν δυνατή η σίγαση του χρήστη", + "Failed to register as guest:": "Δεν ήταν δυνατή η εγγραφή ως επισκέπτης:", + "Failed to reject invite": "Δεν ήταν δυνατή η απόρριψη της πρόσκλησης", + "Failed to reject invitation": "Δεν ήταν δυνατή η απόρριψη της πρόσκλησης", + "Failed to save settings": "Δεν ήταν δυνατή η αποθήκευση των ρυθμίσεων", + "Failed to send email": "Δεν ήταν δυνατή η απστολή email", + "Failed to verify email address: make sure you clicked the link in the email": "Δεν ήταν δυνατή η επαλήθευση του email: βεβαιωθείτε οτι κάνατε κλικ στον σύνδεσμο που σας στάλθηκε", + "Favourite": "Αγαπημένο", + "favourite": "αγαπημένο", + "Favourites": "Αγαπημένα", + "Fill screen": "Γέμισε την οθόνη", + "Filter room members": "Φίλτραρε τα μέλη", + "Forget room": "Διέγραψε το δωμάτιο", + "Forgot your password?": "Ξέχασες τον κωδικό σου;" +} diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 52f2b152cf..6329bf9829 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -161,7 +161,7 @@ "Phone": "Telefone", "placed a": "iniciou uma", "Please check your email and click on the link it contains. Once this is done, click continue.": "Por favor verifique seu email e clique no link enviado. Quando finalizar este processo, clique para continuar.", - "Please Register": "Por favor, cadastre-se", + "Please Register": "Por favor registe-se", "Privacy warning": "Alerta sobre privacidade", "Privileged Users": "Usuárias/os privilegiadas/os", "Profile": "Perfil", @@ -329,7 +329,7 @@ "Conference calls are not supported in encrypted rooms": "Chamadas de conferência não são possíveis em salas criptografadas", "Conference calls are not supported in this client": "Chamadas de conferência não são possíveis neste navegador", "/ddg is not a command": "/ddg não é um comando", - "Drop here %(toAction)s": "Arraste aqui %(toAction)s", + "Drop here %(toAction)s": "Arraste aqui para %(toAction)s", "Drop here to tag %(section)s": "Arraste aqui para marcar como %(section)s", "%(senderName)s ended the call.": "%(senderName)s finalizou a chamada.", "Existing Call": "Chamada em andamento", @@ -437,7 +437,7 @@ "ar-bh": "Árabe (Bahrain)", "ar-dz": "Árabe (Algéria)", "Sunday": "Domingo", - "Monday": "Segunda", + "Monday": "Segunda-feira", "ar-eg": "Árabe (Egito)", "ar-tn": "Árabe (Tunisia)", "be": "Bielorusso", @@ -496,12 +496,12 @@ "vi": "Vietnamita", "xh": "Xhosa", "zu": "Zulu", - "Failed to forget room %(errCode)s": "Falhou ao esquecer a sala %(errCode)s", - "Failed to join the room": "Falhou ao entrar na sala", - "Tuesday": "Terça", - "Wednesday": "Quarta", - "Thursday": "Quinta", - "Friday": "Sexta", + "Failed to forget room %(errCode)s": "Falha ao esquecer a sala %(errCode)s", + "Failed to join the room": "Falha ao entrar na sala", + "Tuesday": "Terça-feira", + "Wednesday": "Quarta-feira", + "Thursday": "Quinta-feira", + "Friday": "Sexta-feira", "Saturday": "Sábado", "ar-iq": "Árabe (Iraque)", "ar-jo": "Árabe (Jordânia)", @@ -621,7 +621,7 @@ "No results": "Sem resultados", "OK": "Ok", "Revoke Moderator": "Retirar status de moderador", - "Search": "Buscar", + "Search": "Pesquisar", "Search failed": "Busca falhou", "Server error": "Erro no servidor", "Server may be unavailable, overloaded, or search timed out :(": "O servidor pode estar indisponível, sobrecarregado, ou a busca ultrapassou o tempo limite :(", @@ -714,7 +714,7 @@ "Invalid file%(extra)s": "Arquivo inválido %(extra)s", "Logged in as:": "Logado como:", "matrix-react-sdk version:": "versão do matrix-react-sdk:", - "Mute": "Mudo", + "Mute": "Silenciar", "olm version:": "versão do olm:", "Operation failed": "A operação falhou", "Registration required": "Registro obrigatório", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 37b36de963..4d83321009 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -237,7 +237,7 @@ "Conference calls are not supported in encrypted rooms": "Конференц-вызовы не поддерживаются в зашифрованных комнатах", "Conference calls are not supported in this client": "Конференц-вызовы не поддерживаются в этом клиенте", "/ddg is not a command": "/ddg не команда", - "Drop here %(toAction)s": "Вставить сюда для %(toAction)s", + "Drop here %(toAction)s": "Вставить сюда: %(toAction)s", "Drop here to tag %(section)s": "Вставить здесь для тега %(section)s", "%(senderName)s ended the call.": "%(senderName)s прекратил звонок.", "Existing Call": "Существующий вызов", @@ -388,7 +388,7 @@ "You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver. This is a once off; sorry for the inconvenience.": "Вам необходимо снова войти в генерировать сквозное шифрование (е2е) ключей для этого устройства и предоставить публичный ключ Вашему домашнему серверу. Это после выключения; приносим извинения за причиненные неудобства.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Ваш адрес электронной почты, кажется, не связан с Matrix ID на этом Homeserver.", "to start a chat with someone": "Начать чат с кем-то", - "to tag direct chat": "Пометить прямой чат", + "to tag direct chat": "отометить прямой чат", "To use it, just wait for autocomplete results to load and tab through them.": "Для его использования, просто подождите результатов автозаполнения для загрузки на вкладке и через них.", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s включил сквозное шифрование (algorithm %(algorithm)s).", "Unable to restore previous session": "Невозможно востановить предыдущий сеанс", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index d99387c16e..250dc23ef3 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -352,5 +352,14 @@ "Image '%(Body)s' cannot be displayed.": "圖片 '%(Body)s' 無法顯示", "This image cannot be displayed.": "這張圖片無法顯示", "Error decrypting video": "解密影片出錯", - "Add an Integration": "新增整合器" + "Add an Integration": "新增整合器", + "Ongoing conference call%(supportedText)s. %(joinText)s": "%(supportedText)s. %(joinText)s 正在進行電話會議", + " (unsupported)": " (不支持)", + "URL Previews": "網址預覽", + "Enable URL previews for this room (affects only you)": "啟用此房間的網址預覽(僅影響您)", + "Drop file here to upload": "把文件放在這裡上傳", + "Disable URL previews by default for participants in this room": "默認情況下,此房間的參與者禁用網址預覽", + "URL previews are %(globalDisableUrlPreview)s by default for participants in this room.": "默認情況下,這個房間的參與者的網址預覽是%(globalDisableUrlPreview)。", + "Removed or unknown message type": "已刪除或未知的信息類型", + "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "您即將被帶到第三方網站,以便您可以驗證您的帳戶以使用%(integrationsUrl)。你想繼續嗎?" } From a9d516e8ea6e70e28275f86dfa0b36ae76e40fcc Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Sat, 3 Jun 2017 12:48:41 +0100 Subject: [PATCH 109/275] fix toAction i18n thinkos --- src/i18n/strings/es.json | 2 +- src/i18n/strings/pt.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index df6f0dd011..9a07710570 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -225,7 +225,7 @@ "Displays action": "Mostrar acción", "Don't send typing notifications": "No enviar notificaciones cuando se escribe", "Download %(text)s": "Descargar %(text)s", - "Drop here %(toAction)s": "Suelta aquí para %(toAction)s", + "Drop here %(toAction)s": "Suelta aquí %(toAction)s", "Drop here to tag %(section)s": "Suelta aquí para etiquetar %(section)s", "Ed25519 fingerprint": "Clave de cifrado Ed25519", "Email": "Correo electrónico", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 6329bf9829..587043f544 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -329,7 +329,7 @@ "Conference calls are not supported in encrypted rooms": "Chamadas de conferência não são possíveis em salas criptografadas", "Conference calls are not supported in this client": "Chamadas de conferência não são possíveis neste navegador", "/ddg is not a command": "/ddg não é um comando", - "Drop here %(toAction)s": "Arraste aqui para %(toAction)s", + "Drop here %(toAction)s": "Arraste aqui %(toAction)s", "Drop here to tag %(section)s": "Arraste aqui para marcar como %(section)s", "%(senderName)s ended the call.": "%(senderName)s finalizou a chamada.", "Existing Call": "Chamada em andamento", From 1bbdb6c9850f0305d640ae6aaf8f22a05ae50f38 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 3 Jun 2017 15:51:20 +0100 Subject: [PATCH 110/275] actually pass ev through Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/views/login/RegistrationForm.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/views/login/RegistrationForm.js b/src/components/views/login/RegistrationForm.js index 75feab0f12..9066e31b47 100644 --- a/src/components/views/login/RegistrationForm.js +++ b/src/components/views/login/RegistrationForm.js @@ -110,13 +110,12 @@ module.exports = React.createClass({ button: _t("Continue"), onFinished: function(confirmed) { if (confirmed) { - self._doSubmit(); + self._doSubmit(ev); } }, }); - } - else { - self._doSubmit(); + } else { + self._doSubmit(ev); } } }, From 159a920dc8896a01bf6059c67a890d4155c70708 Mon Sep 17 00:00:00 2001 From: "saul.kredi@krutt.org" Date: Sat, 3 Jun 2017 18:52:45 +0300 Subject: [PATCH 111/275] Better RTL support --- src/components/views/messages/SenderProfile.js | 2 +- src/components/views/rooms/EntityTile.js | 4 ++-- src/components/views/rooms/MessageComposerInput.js | 1 + src/components/views/rooms/MessageComposerInputOld.js | 2 +- src/components/views/rooms/RoomHeader.js | 4 ++-- src/components/views/rooms/RoomNameEditor.js | 4 ++-- src/components/views/rooms/RoomTile.js | 6 +++--- src/components/views/rooms/RoomTopicEditor.js | 3 ++- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index 9e6fba2127..e224714a27 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -30,7 +30,7 @@ export default function SenderProfile(props) { } return ( - {`${name || ''} ${props.aux || ''}`} ); } diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index 71e8fb0be7..67b3f54ba9 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -115,7 +115,7 @@ module.exports = React.createClass({ nameEl = (
- {name} + {name} @@ -124,7 +124,7 @@ module.exports = React.createClass({ } else { nameEl = ( - {name} + {name} ); } diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js index 65148f91ef..5416ee5d27 100644 --- a/src/components/views/rooms/MessageComposerInput.js +++ b/src/components/views/rooms/MessageComposerInput.js @@ -723,6 +723,7 @@ export default class MessageComposerInput extends React.Component { title={ this.state.isRichtextEnabled ? _t("Markdown is disabled") : _t("Markdown is enabled")} src={`img/button-md-${!this.state.isRichtextEnabled}.png`} /> - + , ); - var error; - var addressSelector; + let error; + let addressSelector; if (this.state.error) { error =
{_t("You have entered an invalid contact. Try using their Matrix ID or email address.")}
; + } else if ( + this.state.query.length > 0 && + this.state.queryList.length === 0 && + !this.state.busy + ) { + error =
{_t("No results")}
; } else { const addressSelectorHeader =
- Searching known users + { _t("Searching known users") }
; addressSelector = ( {this.addressSelector = ref;}} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c87ffb8cdf..eb331c24a9 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -599,6 +599,7 @@ "Who can read history?": "Who can read history?", "Who would you like to add to this room?": "Who would you like to add to this room?", "Who would you like to communicate with?": "Who would you like to communicate with?", + "Searching known users": "Searching known users", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.", "Would you like to": "Would you like to", "You are already in a call.": "You are already in a call.", From 49b22fb6c6f42fd9366cb19c261b1b03359a6aed Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 7 Jun 2017 16:13:40 +0100 Subject: [PATCH 168/275] Use an arrow function to allow `this` This was causing `TypeError: Cannot read property '_getEmptyContent' of undefined` for those with custom tags. --- src/components/views/rooms/RoomList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index bf270b1148..f90d89c8c1 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -578,7 +578,7 @@ module.exports = React.createClass({ onHeaderClick={ self.onSubListHeaderClick } onShowMoreRooms={ self.onShowMoreRooms } /> - { Object.keys(self.state.lists).map(function(tagName) { + { Object.keys(self.state.lists).map((tagName) => { if (!tagName.match(/^(m\.(favourite|lowpriority)|im\.vector\.fake\.(invite|recent|direct|archived))$/)) { return Date: Wed, 7 Jun 2017 17:33:15 +0100 Subject: [PATCH 169/275] Use then, catch, done and display any errors that occur during search --- .../views/dialogs/ChatInviteDialog.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index 867a3b423c..0c65f02525 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -61,6 +61,8 @@ module.exports = React.createClass({ // Whether a search is ongoing busy: false, + // An error message generated during the user directory search + searchError: null, // The query being searched for query: "", // List of AddressTile.InviteAddressType objects representing @@ -181,6 +183,7 @@ module.exports = React.createClass({ this.setState({ busy: true, query, + searchError: null, }); MatrixClientPeg.get().searchUserDirectory({ term: query, @@ -222,7 +225,12 @@ module.exports = React.createClass({ }, () => { this.addressSelector.moveSelectionTop(); }); - }).finally(() => { + }).catch((err) => { + console.error('Error whilst searching user directory: ', err); + this.setState({ + searchError: err.errcode ? err.message : _t('Something went wrong!'), + }); + }).done(() => { this.setState({ busy: false, }); @@ -232,6 +240,7 @@ module.exports = React.createClass({ this.setState({ queryList: [], query: "", + searchError: null, }); } }, @@ -494,6 +503,8 @@ module.exports = React.createClass({ let addressSelector; if (this.state.error) { error =
{_t("You have entered an invalid contact. Try using their Matrix ID or email address.")}
; + } else if (this.state.searchError) { + error =
{this.state.searchError}
; } else if ( this.state.query.length > 0 && this.state.queryList.length === 0 && @@ -501,15 +512,11 @@ module.exports = React.createClass({ ) { error =
{_t("No results")}
; } else { - const addressSelectorHeader =
- { _t("Searching known users") } -
; addressSelector = ( {this.addressSelector = ref;}} addressList={ this.state.queryList } onSelected={ this.onSelected } truncateAt={ TRUNCATE_QUERY_LIST } - header={ addressSelectorHeader } /> ); } From 3db286f8f007f10ad99a81cf2924ca4179b9123b Mon Sep 17 00:00:00 2001 From: Krombel Date: Wed, 7 Jun 2017 16:45:34 +0000 Subject: [PATCH 170/275] Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index b6011ccf2d..79603ad361 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -111,7 +111,7 @@ "Default": "Standard", "demote": "Berechtigungslevel herabstufen", "Export E2E room keys": "E2E-Raum-Schlüssel exportieren", - "Failed to change password. Is your password correct?": "Passwort-Änderung schlug fehl. Ist dein Passwort korrekt?", + "Failed to change password. Is your password correct?": "Passwortänderung fehlgeschlagen. Ist dein Passwort richtig?", "Failed to forget room": "Vergessen des Raums schlug fehl", "Failed to leave room": "Verlassen des Raums fehlgeschlagen", "Failed to reject invitation": "Fehler beim Abweisen der Einladung", @@ -890,5 +890,35 @@ "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s hat das Raum-Bild für %(roomName)s geändert", "Hide removed messages": "Gelöschte Nachrichten verbergen", "Start new chat": "Neuen Chat starten", - "Disable markdown formatting": "Deaktiviere Markdown-Formatierung" + "Disable markdown formatting": "Deaktiviere Markdown-Formatierung", + "Add": "Hinzufügen", + "%(count)s new messages.one": "%(count)s neue Nachricht", + "%(count)s new messages.other": "%(count)s neue Nachrichten", + "Error: Problem communicating with the given homeserver.": "Fehler: Problem beim kommunizieren mit dem angegebenen Heimserver.", + "Failed to fetch avatar URL": "Fehler beim holen der Avatar-URL", + "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", + "The phone number entered looks invalid": "Die Telefonnummer, die eingegeben wurde, sieht ungültig aus", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht betretbar. Du kannst evtl. beitreten wenn du dich registrierst.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber du hast keine Berechtigung diese Nachricht zu sehen.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber er konnte nicht gefunden werden.", + "Uploading %(filename)s and %(count)s others.zero": "%(filename)s wird hochgeladen", + "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere werden hochgeladen", + "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere werden hochgeladen", + "You must register to use this functionality": "Du musst dich registrieren um diese Funktionalität zu nutzen", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Sende erneut oder breche alles ab. Du kannst auch auch individuelle Nachrichten erneut senden or abbrechen.", + "Create new room": "Erstelle neuen Raum", + "Welcome page": "Willkommensseite", + "Room directory": "Raum-Verzeichnis", + "Start chat": "Starte Chat", + "New Password": "Neues Passwort", + "Start chatting": "Starte plaudern", + "Start Chatting": "Starte Gespräche", + "Click on the button below to start chatting!": "Klicke den Button unten um das Plaudern zu beginnen!", + "Create a new chat or reuse an existing one": "Erstelle einen neuen Chat oder nutze einen existierenden", + "You already have existing direct chats with this user:": "Du hast bereits direkte Chats mit diesem Nutzer:", + "Username available": "Nutzername verfügbar", + "Username not available": "Nutzername nicht verfügbar", + "Something went wrong!": "Etwas ging schief!", + "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", + "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Konto hast, kannst du ansonsten auch anmelden." } From b2a17fea08acba34ee3de3b444b2d8e9de6ca98d Mon Sep 17 00:00:00 2001 From: Amandine Date: Wed, 7 Jun 2017 16:28:38 +0000 Subject: [PATCH 171/275] Translated using Weblate (French) Currently translated at 96.5% (821 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 0ae02be82f..c4a606b9bc 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -827,5 +827,8 @@ "You have disabled URL previews by default.": "Vous avez désactivé les aperçus d’URL par défaut.", "You have enabled URL previews by default.": "Vous avez activé les aperçus d’URL par défaut.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Vous avez entré un contact invalide. Essayez d’utiliser leur identifiant Matrix ou leur adresse email.", - "Hide removed messages": "Cacher les messages supprimés" + "Hide removed messages": "Cacher les messages supprimés", + "Add": "Ajouter", + "%(count)s new messages.one": "%(count)s nouveau message", + "%(count)s new messages.other": "%(count)s nouveaux messages" } From c11fd8c3b18f7d6b7ea01af9ea09047d03df3720 Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Wed, 7 Jun 2017 16:45:41 +0000 Subject: [PATCH 172/275] Translated using Weblate (Thai) Currently translated at 39.0% (332 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 2fa93e02fc..a05f5c8f68 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -327,5 +327,9 @@ "%(oneUser)schanged their name": "%(oneUser)sเปลี่ยนชื่อของเขาแล้ว", "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)sเปลี่ยนชื่อของพวกเขา %(repeats)s ครั้ง", "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)sเปลี่ยนชื่อของเขา %(repeats)s ครั้ง", - "%(severalUsers)schanged their name": "%(severalUsers)sเปลี่ยนชื่อของพวกเขาแล้ว" + "%(severalUsers)schanged their name": "%(severalUsers)sเปลี่ยนชื่อของพวกเขาแล้ว", + "Create new room": "สร้างห้องใหม่", + "Room directory": "ไดเรกทอรีห้อง", + "Start chat": "เริ่มแชท", + "Welcome page": "หน้าต้อนรับ" } From 29da25529c903a5d621032271cf17979c36a27cc Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 7 Jun 2017 17:40:09 +0100 Subject: [PATCH 173/275] Make it backwards compatible Hit the user_directory API and if M_UNRECOGNIZED, do a local search and continue to search locally therein. --- .../views/dialogs/ChatInviteDialog.js | 154 +++++++++++------- 1 file changed, 99 insertions(+), 55 deletions(-) diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index 0c65f02525..2f635fd670 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -63,6 +63,8 @@ module.exports = React.createClass({ busy: false, // An error message generated during the user directory search searchError: null, + // Whether the server supports the user_directory API + serverSupportsUserDirectory: true, // The query being searched for query: "", // List of AddressTile.InviteAddressType objects representing @@ -180,61 +182,11 @@ module.exports = React.createClass({ // Only do search if there is something to search if (query.length > 0 && query != '@' && query.length >= 2) { this.queryChangedDebouncer = setTimeout(() => { - this.setState({ - busy: true, - query, - searchError: null, - }); - MatrixClientPeg.get().searchUserDirectory({ - term: query, - }).then((resp) => { - const queryList = []; - resp.results.forEach((user) => { - if (user.user_id === MatrixClientPeg.get().credentials.userId) { - return; - } - // Return objects, structure of which is defined - // by InviteAddressType - queryList.push({ - addressType: 'mx', - address: user.user_id, - displayName: user.display_name, - avatarMxc: user.avatar_url, - isKnown: true, - }); - }); - - // If the query is a valid address, add an entry for that - // This is important, otherwise there's no way to invite - // a perfectly valid address if there are close matches. - const addrType = getAddressType(query); - if (addrType !== null) { - queryList.unshift({ - addressType: addrType, - address: query, - isKnown: false, - }); - if (this._cancelThreepidLookup) this._cancelThreepidLookup(); - if (addrType == 'email') { - this._lookupThreepid(addrType, query).done(); - } - } - this.setState({ - queryList, - error: false, - }, () => { - this.addressSelector.moveSelectionTop(); - }); - }).catch((err) => { - console.error('Error whilst searching user directory: ', err); - this.setState({ - searchError: err.errcode ? err.message : _t('Something went wrong!'), - }); - }).done(() => { - this.setState({ - busy: false, - }); - }); + if (this.state.serverSupportsUserDirectory) { + this._doUserDirectorySearch(query); + } else { + this._doLocalSearch(query); + } }, QUERY_USER_DIRECTORY_DEBOUNCE_MS); } else { this.setState({ @@ -277,6 +229,98 @@ module.exports = React.createClass({ if (this._cancelThreepidLookup) this._cancelThreepidLookup(); }, + _doUserDirectorySearch: function(query) { + this.setState({ + busy: true, + query, + searchError: null, + }); + MatrixClientPeg.get().searchUserDirectory({ + term: query, + }).then((resp) => { + this._processResults(resp.results, query); + }).catch((err) => { + console.error('Error whilst searching user directory: ', err); + this.setState({ + searchError: err.errcode ? err.message : _t('Something went wrong!'), + }); + if (err.errcode === 'M_UNRECOGNIZED') { + this.setState({ + serverSupportsUserDirectory: false, + }); + // Do a local search immediately + this._doLocalSearch(query); + } + }).done(() => { + this.setState({ + busy: false, + }); + }); + }, + + _doLocalSearch: function(query) { + this.setState({ + query, + searchError: null, + }); + const results = []; + MatrixClientPeg.get().getUsers().forEach((user) => { + if (user.userId.toLowerCase().indexOf(query) === -1 && + user.displayName.toLowerCase().indexOf(query) === -1 + ) { + return; + } + + // Put results in the format of the new API + results.push({ + user_id: user.userId, + display_name: user.displayName, + avatar_url: user.avatarUrl, + }); + }); + this._processResults(results, query); + }, + + _processResults: function(results, query) { + const queryList = []; + results.forEach((user) => { + if (user.user_id === MatrixClientPeg.get().credentials.userId) { + return; + } + // Return objects, structure of which is defined + // by InviteAddressType + queryList.push({ + addressType: 'mx', + address: user.user_id, + displayName: user.display_name, + avatarMxc: user.avatar_url, + isKnown: true, + }); + }); + + // If the query is a valid address, add an entry for that + // This is important, otherwise there's no way to invite + // a perfectly valid address if there are close matches. + const addrType = getAddressType(query); + if (addrType !== null) { + queryList.unshift({ + addressType: addrType, + address: query, + isKnown: false, + }); + if (this._cancelThreepidLookup) this._cancelThreepidLookup(); + if (addrType == 'email') { + this._lookupThreepid(addrType, query).done(); + } + } + this.setState({ + queryList, + error: false, + }, () => { + if (this.addressSelector) this.addressSelector.moveSelectionTop(); + }); + }, + _getDirectMessageRooms: function(addr) { const dmRoomMap = new DMRoomMap(MatrixClientPeg.get()); const dmRooms = dmRoomMap.getDMRoomsForUserId(addr); From 74d680a9524aa1eb73d0b4f276c78ce80b5985f9 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 7 Jun 2017 18:15:13 +0100 Subject: [PATCH 174/275] sync fullstops everywhere --- src/i18n/strings/de_DE.json | 28 ++++++++++++++-------------- src/i18n/strings/el.json | 4 ++-- src/i18n/strings/en_US.json | 10 +++++----- src/i18n/strings/es.json | 2 +- src/i18n/strings/fr.json | 10 +++++----- src/i18n/strings/pt.json | 10 +++++----- src/i18n/strings/pt_BR.json | 10 +++++----- src/i18n/strings/ru.json | 6 +++--- 8 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 15375b8f90..513faea017 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -227,7 +227,7 @@ "to join the discussion": "um an der Diskussion teilzunehmen", "To kick users": "Um Nutzer zu entfernen", "Admin": "Administrator", - "Server may be unavailable, overloaded, or you hit a bug": "Server könnte nicht verfügbar oder überlastet sein oder du bist auf einen Fehler gestoßen", + "Server may be unavailable, overloaded, or you hit a bug.": "Server könnte nicht verfügbar oder überlastet sein oder du bist auf einen Fehler gestoßen.", "Could not connect to the integration server": "Konnte keine Verbindung zum Integrations-Server herstellen", "Disable inline URL previews by default": "URL-Vorschau im Chat standardmäßig deaktivieren", "Guests can't use labs features. Please register.": "Gäste können keine Labor-Funktionen nutzen. Bitte registrieren.", @@ -280,15 +280,15 @@ "times": "mal", "Bulk Options": "Bulk-Optionen", "Call Timeout": "Anruf-Timeout", - "Conference call failed": "Konferenzgespräch fehlgeschlagen", - "Conference calling is in development and may not be reliable": "Konferenzgespräche sind in Entwicklung und evtl. nicht zuverlässig", + "Conference call failed.": "Konferenzgespräch fehlgeschlagen.", + "Conference calling is in development and may not be reliable.": "Konferenzgespräche sind in Entwicklung und evtl. nicht zuverlässig.", "Conference calls are not supported in encrypted rooms": "Konferenzgespräche werden in verschlüsselten Räumen nicht unterstützt", "Conference calls are not supported in this client": "Konferenzgespräche werden von diesem Client nicht unterstützt", "Existing Call": "Bereits bestehender Anruf", "Failed to set up conference call": "Konferenzgespräch konnte nicht gestartet werden", "Failed to verify email address: make sure you clicked the link in the email": "Verifizierung der E-Mail-Adresse fehlgeschlagen: Bitte stelle sicher, dass du den Link in der E-Mail angeklickt hast", "Failure to create room": "Raumerstellung fehlgeschlagen", - "Guest users can't create new rooms. Please register to create room and start a chat": "Gäste können keine neuen Räume erstellen. Bitte registrieren um einen Raum zu erstellen und einen Chat zu starten", + "Guest users can't create new rooms. Please register to create room and start a chat.": "Gäste können keine neuen Räume erstellen. Bitte registrieren um einen Raum zu erstellen und einen Chat zu starten.", "Riot does not have permission to send you notifications - please check your browser settings": "Riot hat keine Berechtigung Benachrichtigungen zu senden - bitte prüfe deine Browser-Einstellungen", "Riot was not given permission to send notifications - please try again": "Riot hat das Recht nicht bekommen Benachrichtigungen zu senden. Bitte erneut probieren", "This email address is already in use": "Diese E-Mail-Adresse wird bereits verwendet", @@ -302,11 +302,11 @@ "Unable to enable Notifications": "Benachrichtigungen konnten nicht aktiviert werden", "Upload Failed": "Upload fehlgeschlagen", "VoIP is unsupported": "VoIP wird nicht unterstützt", - "You are already in a call": "Du bist bereits bei einem Anruf", - "You cannot place a call with yourself": "Du kannst keinen Anruf mit dir selbst starten", - "You cannot place VoIP calls in this browser": "Du kannst kein VoIP-Gespräch in diesem Browser starten", + "You are already in a call.": "Du bist bereits bei einem Anruf.", + "You cannot place a call with yourself.": "Du kannst keinen Anruf mit dir selbst starten.", + "You cannot place VoIP calls in this browser.": "Du kannst kein VoIP-Gespräch in diesem Browser starten.", "You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver. This is a once off; sorry for the inconvenience.": "Du musst dich erneut anmelden, um Ende-zu-Ende-Verschlüsselungs-Schlüssel für dieses Gerät zu generieren und um den öffentlichen Schlüssel auf deinem Homeserver zu hinterlegen. Dies muss nur einmal durchgeführt werden, bitte entschuldige die Unannehmlichkeiten.", - "Your email address does not appear to be associated with a Matrix ID on this Homeserver": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Homeserver verknüpft zu sein", + "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Homeserver verknüpft zu sein.", "Sun": "So", "Mon": "Mo", "Tue": "Di", @@ -581,7 +581,7 @@ "Failed to save settings": "Einstellungen konnten nicht gespeichert werden", "Failed to set display name": "Anzeigename konnte nicht gesetzt werden", "Fill screen": "Fülle Bildschirm", - "Guest users can't upload files. Please register to upload": "Gäste können keine Dateien hochladen. Bitte zunächst registrieren", + "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte zunächst registrieren.", "Hide Text Formatting Toolbar": "Verberge Text-Formatierungs-Toolbar", "Incorrect verification code": "Falscher Verifizierungscode", "Invalid alias format": "Ungültiges Alias-Format", @@ -608,16 +608,16 @@ "Server error": "Server-Fehler", "Server may be unavailable, overloaded, or search timed out :(": "Der Server ist entweder nicht verfügbar, überlastet oder die Suche wurde wegen Zeitüberschreitung abgebrochen :(", "Server may be unavailable, overloaded, or the file too big": "Server ist entweder nicht verfügbar, überlastet oder die Datei ist zu groß", - "Server unavailable, overloaded, or something else went wrong": "Der Server ist entweder nicht verfügbar, überlastet oder es liegt ein anderweitiger Fehler vor", - "Some of your messages have not been sent": "Einige deiner Nachrichten wurden noch nicht gesendet", + "Server unavailable, overloaded, or something else went wrong.": "Der Server ist entweder nicht verfügbar, überlastet oder es liegt ein anderweitiger Fehler vor.", + "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden noch nicht gesendet.", "Submit": "Absenden", "The main address for this room is: %(canonical_alias_section)s": "Die Hauptadresse für diesen Raum ist: %(canonical_alias_section)s", "This action cannot be performed by a guest user. Please register to be able to do this": "Diese Aktion kann nicht von einem Gast ausgeführt werden. Bitte registriere dich um dies zu tun", "%(actionVerb)s this person?": "Diese Person %(actionVerb)s?", "This room has no local addresses": "Dieser Raum hat keine lokale Adresse", - "This room is private or inaccessible to guests. You may be able to join if you register": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden.", "Turn Markdown off": "Markdown abschalten", "Turn Markdown on": "Markdown einschalten", "Unable to load device list": "Geräteliste konnte nicht geladen werden", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index ab2129dc81..d8729202d5 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -48,7 +48,7 @@ "Authentication": "Πιστοποίηση", "and": "και", "An email has been sent to": "Ένα email στάλθηκε σε", - "A new password must be entered.": "Ο νέος κωδικός πρέπει να εισαχθεί", + "A new password must be entered.": "Ο νέος κωδικός πρέπει να εισαχθεί.", "%(senderName)s answered the call.": "Ο χρήστης %(senderName)s απάντησε.", "An error has occurred.": "Ένα σφάλμα προέκυψε", "Anyone": "Oποιοσδήποτε", @@ -265,7 +265,7 @@ "For security, this session has been signed out. Please sign in again.": "Για λόγους ασφαλείας, αυτή η συνεδρία έχει τερματιστεί. Παρακαλώ συνδεθείτε ξανά.", "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Για λόγους ασφαλείας, τα κλειδιά κρυπτογράφησης θα διαγράφονται από τον φυλλομετρητή κατά την αποσύνδεση σας. Εάν επιθυμείτε να αποκρυπτογραφήσετε τις συνομιλίες σας στο μέλλον, εξάγετε τα κλειδιά σας και κρατήστε τα ασφαλή.", "Found a bug?": "Βρήκατε κάποιο πρόβλημα;", - "Guest users can't upload files. Please register to upload": "Οι επισκέπτες δεν μπορούν να ανεβάσουν αρχεία. Παρακαλώ εγγραφείτε πρώτα", + "Guest users can't upload files. Please register to upload.": "Οι επισκέπτες δεν μπορούν να ανεβάσουν αρχεία. Παρακαλώ εγγραφείτε πρώτα.", "had": "είχε", "Hangup": "Κλείσε", "Historical": "Ιστορικό", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index 2ad228254b..19b854e936 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -308,7 +308,7 @@ "Guest access is disabled on this Home Server.": "Guest access is disabled on this Home Server.", "Guests can't set avatars. Please register.": "Guests can't set avatars. Please register.", "Guest users can't create new rooms. Please register to create room and start a chat.": "Guest users can't create new rooms. Please register to create room and start a chat.", - "Guest users can't upload files. Please register to upload": "Guest users can't upload files. Please register to upload", + "Guest users can't upload files. Please register to upload.": "Guest users can't upload files. Please register to upload.", "Guests can't use labs features. Please register.": "Guests can't use labs features. Please register.", "Guests cannot join this room even if explicitly invited.": "Guests cannot join this room even if explicitly invited.", "had": "had", @@ -476,7 +476,7 @@ "since the point in time of selecting this option": "since the point in time of selecting this option", "since they joined": "since they joined", "since they were invited": "since they were invited", - "Some of your messages have not been sent": "Some of your messages have not been sent", + "Some of your messages have not been sent.": "Some of your messages have not been sent.", "Someone": "Someone", "Sorry, this homeserver is using a login which is not recognised ": "Sorry, this homeserver is using a login which is not recognized ", "Start a chat": "Start a chat", @@ -501,7 +501,7 @@ "There was a problem logging in.": "There was a problem logging in.", "This room has no local addresses": "This room has no local addresses", "This room is not recognised.": "This room is not recognized.", - "This room is private or inaccessible to guests. You may be able to join if you register": "This room is private or inaccessible to guests. You may be able to join if you register", + "This room is private or inaccessible to guests. You may be able to join if you register.": "This room is private or inaccessible to guests. You may be able to join if you register.", "These are experimental features that may break in unexpected ways": "These are experimental features that may break in unexpected ways", "The visibility of existing history will be unchanged": "The visibility of existing history will be unchanged", "This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address", @@ -530,8 +530,8 @@ "to tag as %(tagName)s": "to tag as %(tagName)s", "to tag direct chat": "to tag direct chat", "To use it, just wait for autocomplete results to load and tab through them.": "To use it, just wait for autocomplete results to load and tab through them.", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Tried to load a specific point in this room's timeline, but was unable to find it", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Tried to load a specific point in this room's timeline, but was unable to find it.", "Turn Markdown off": "Turn Markdown off", "Turn Markdown on": "Turn Markdown on", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 9a07710570..125a929b9f 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -282,7 +282,7 @@ "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s de %(fromPowerLevel)s a %(toPowerLevel)s", "Guests can't set avatars. Please register.": "Invitados no puedes establecer avatares. Por favor regístrate.", "Guest users can't create new rooms. Please register to create room and start a chat.": "Usuarios invitados no pueden crear nuevas salas. Por favor regístrate para crear la sala y iniciar la conversación.", - "Guest users can't upload files. Please register to upload": "Usuarios invitados no puedes subir archivos. Por favor regístrate para subir tus archivos", + "Guest users can't upload files. Please register to upload.": "Usuarios invitados no puedes subir archivos. Por favor regístrate para subir tus archivos.", "Guests can't use labs features. Please register.": "Invitados no puedes usar las características en desarrollo. Por favor regístrate.", "Guests cannot join this room even if explicitly invited.": "Invitados no pueden unirse a esta sala aun cuando han sido invitados explícitamente.", "had": "tuvo", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 0ae02be82f..80d2479c48 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -294,7 +294,7 @@ "Found a bug?": "Trouvé un problème ?", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s de %(fromPowerLevel)s à %(toPowerLevel)s", "Guest users can't create new rooms. Please register to create room and start a chat.": "Les visiteurs ne peuvent créer de nouveaux salons. Merci de vous enregistrer pour commencer une discussion.", - "Guest users can't upload files. Please register to upload": "Les visiteurs ne peuvent telécharger de fichiers. Merci de vous enregistrer pour télécharger", + "Guest users can't upload files. Please register to upload.": "Les visiteurs ne peuvent telécharger de fichiers. Merci de vous enregistrer pour télécharger.", "had": "avait", "Hangup": "Raccrocher", "Hide read receipts": "Cacher les accusés de réception", @@ -457,7 +457,7 @@ "since the point in time of selecting this option": "depuis le moment où cette option a été sélectionnée", "since they joined": "depuis qu’ils ont rejoint le salon", "since they were invited": "depuis qu’ils ont été invités", - "Some of your messages have not been sent": "Certains de vos messages n’ont pas été envoyés", + "Some of your messages have not been sent.": "Certains de vos messages n’ont pas été envoyés.", "Someone": "Quelqu'un", "Sorry, this homeserver is using a login which is not recognised ": "Désolé, ce homeserver utilise un identifiant qui n’est pas reconnu ", "Start a chat": "Démarrer une conversation", @@ -478,7 +478,7 @@ "The remote side failed to pick up": "Le correspondant n’a pas décroché", "This room has no local addresses": "Ce salon n'a pas d'adresse locale", "This room is not recognised.": "Ce salon n'a pas été reconnu.", - "This room is private or inaccessible to guests. You may be able to join if you register": "Ce salon est privé ou non autorisé aux visiteurs. Vous devriez pouvoir le rejoindre si vous vous enregistrez", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Ce salon est privé ou non autorisé aux visiteurs. Vous devriez pouvoir le rejoindre si vous vous enregistrez.", "These are experimental features that may break in unexpected ways": "Ces fonctionnalités sont expérimentales et risquent de mal fonctionner", "The visibility of existing history will be unchanged": "La visibilité de l’historique existant sera inchangée", "This doesn't appear to be a valid email address": "Cette adresse n’a pas l’air d’être valide", @@ -507,8 +507,8 @@ "to tag as %(tagName)s": "pour marquer comme %(tagName)s", "to tag direct chat": "pour marquer comme conversation directe", "To use it, just wait for autocomplete results to load and tab through them.": "Pour l’utiliser, attendez simplement que les résultats de l’auto-complétion s’affichent et défilez avec la touche Tab.", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Une tentative de chargement d’un point donné dans la chronologie de ce salon a été effectuée, mais vous n’avez pas la permission de voir le message en question", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Une tentative de chargement d’un point donné dans la chronologie de ce salon a été effectuée, mais il n’a pas été trouvé", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Une tentative de chargement d’un point donné dans la chronologie de ce salon a été effectuée, mais vous n’avez pas la permission de voir le message en question.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Une tentative de chargement d’un point donné dans la chronologie de ce salon a été effectuée, mais il n’a pas été trouvé.", "Turn Markdown off": "Désactiver le formatage ’Markdown’", "Turn Markdown on": "Activer le formatage ’Markdown’", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s a activé l’encryption bout-en-bout (algorithme %(algorithm)s).", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index fb90423c3a..47260b4909 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -101,7 +101,7 @@ "Guests cannot join this room even if explicitly invited.": "Visitantes não podem entrar nesta sala, mesmo se forem explicitamente convidadas/os.", "Guests can't set avatars. Please register.": "Convidados não podem definir uma foto do perfil. Por favor, registre-se.", "Guests can't use labs features. Please register.": "Convidados não podem usar as funcionalidades de laboratório (lab), por gentileza se registre.", - "Guest users can't upload files. Please register to upload": "Usuários não podem fazer envio de arquivos. Por favor se cadastre para enviar arquivos", + "Guest users can't upload files. Please register to upload.": "Usuários não podem fazer envio de arquivos. Por favor se cadastre para enviar arquivos.", "had": "teve", "Hangup": "Desligar", "Historical": "Histórico", @@ -627,15 +627,15 @@ "Server may be unavailable, overloaded, or search timed out :(": "O servidor pode estar indisponível, sobrecarregado, ou a busca ultrapassou o tempo limite :(", "Server may be unavailable, overloaded, or the file too big": "O servidor pode estar indisponível, sobrecarregado, ou o arquivo é muito grande", "Server unavailable, overloaded, or something else went wrong.": "O servidor pode estar indisponível, sobrecarregado, ou alguma outra coisa não funcionou.", - "Some of your messages have not been sent": "Algumas das suas mensagens não foram enviadas", + "Some of your messages have not been sent.": "Algumas das suas mensagens não foram enviadas.", "Submit": "Enviar", "The main address for this room is": "O endereço principal desta sala é", "This action cannot be performed by a guest user. Please register to be able to do this": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso", "%(actionVerb)s this person?": "%(actionVerb)s esta pessoa?", "This room has no local addresses": "Esta sala não tem endereços locais", - "This room is private or inaccessible to guests. You may be able to join if you register": "Esta sala é privada ou inacessível para visitantes. Você poderá ingressar nela se registrar-se", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Tentei carregar um ponto específico na linha do tempo desta sala, mas não o encontrei", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Esta sala é privada ou inacessível para visitantes. Você poderá ingressar nela se registrar-se.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas não o encontrei.", "Turn Markdown off": "Desabilitar a formatação 'Markdown'", "Turn Markdown on": "Habilitar a marcação 'Markdown'", "Unable to load device list": "Não foi possível carregar a lista de dispositivos", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index fc942c2ed8..13c9ec0737 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -101,7 +101,7 @@ "Guests cannot join this room even if explicitly invited.": "Visitantes não podem entrar nesta sala, mesmo se forem explicitamente convidadas/os.", "Guests can't set avatars. Please register.": "Convidados não podem definir uma foto do perfil. Por favor, registre-se.", "Guests can't use labs features. Please register.": "Convidados não podem usar as funcionalidades de laboratório (lab), por gentileza se registre.", - "Guest users can't upload files. Please register to upload": "Usuários não podem fazer envio de arquivos. Por favor se cadastre para enviar arquivos", + "Guest users can't upload files. Please register to upload.": "Usuários não podem fazer envio de arquivos. Por favor se cadastre para enviar arquivos.", "had": "teve", "Hangup": "Desligar", "Historical": "Histórico", @@ -627,15 +627,15 @@ "Server may be unavailable, overloaded, or search timed out :(": "O servidor pode estar indisponível, sobrecarregado, ou a busca ultrapassou o tempo limite :(", "Server may be unavailable, overloaded, or the file too big": "O servidor pode estar indisponível, sobrecarregado, ou o arquivo é muito grande", "Server unavailable, overloaded, or something else went wrong.": "O servidor pode estar indisponível, sobrecarregado, ou alguma outra coisa não funcionou.", - "Some of your messages have not been sent": "Algumas das suas mensagens não foram enviadas", + "Some of your messages have not been sent.": "Algumas das suas mensagens não foram enviadas.", "Submit": "Enviar", "The main address for this room is": "O endereço principal desta sala é", "This action cannot be performed by a guest user. Please register to be able to do this": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso", "%(actionVerb)s this person?": "%(actionVerb)s esta pessoa?", "This room has no local addresses": "Esta sala não tem endereços locais", - "This room is private or inaccessible to guests. You may be able to join if you register": "Esta sala é privada ou inacessível para visitantes. Você poderá ingressar nela se registrar-se", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Tentei carregar um ponto específico na linha do tempo desta sala, mas não o encontrei", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Esta sala é privada ou inacessível para visitantes. Você poderá ingressar nela se registrar-se.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas não o encontrei.", "Turn Markdown off": "Desabilitar a formatação 'Markdown'", "Turn Markdown on": "Habilitar a marcação 'Markdown'", "Unable to load device list": "Não foi possível carregar a lista de dispositivos", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index a0788a15dc..cf9bd78ffd 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -498,7 +498,7 @@ "Failed to set display name": "Не удалось установить отображаемое имя", "Failed to toggle moderator status": "Не удалось изменить статус модератора", "Fill screen": "Заполнить экран", - "Guest users can't upload files. Please register to upload": "Гости не могут посылать файлы. Пожалуйста, зарегистрируйтесь для отправки", + "Guest users can't upload files. Please register to upload.": "Гости не могут посылать файлы. Пожалуйста, зарегистрируйтесь для отправки.", "Hide read receipts": "Скрыть отметки о прочтении", "Hide Text Formatting Toolbar": "Скрыть панель форматирования текста", "Incorrect verification code": "Неверный код подтверждения", @@ -567,7 +567,7 @@ "since the point in time of selecting this option": "с момента выбора этой настройки", "since they joined": "с момента входа", "since they were invited": "с момента приглашения", - "Some of your messages have not been sent": "Некоторые из ваших сообщений не были отправлены", + "Some of your messages have not been sent.": "Некоторые из ваших сообщений не были отправлены.", "Someone": "Кто-то", "Submit": "Отправить", "Success": "Успех", @@ -583,7 +583,7 @@ "The remote side failed to pick up": "Удалённая сторона не смогла ответить", "This room has no local addresses": "Эта комната не имеет местного адреса", "This room is not recognised.": "Эта комната не опознана.", - "This room is private or inaccessible to guests. You may be able to join if you register": "Эта комната личная или недоступна для гостей. Мы может быть войдёте, если зарегистрируйтесь", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Эта комната личная или недоступна для гостей. Мы может быть войдёте, если зарегистрируйтесь.", "These are experimental features that may break in unexpected ways": "Это экспериментальные функции, которые могут неожиданным образом вызывать ошибки", "This doesn't appear to be a valid email address": "Не похоже, что это правильный адрес электронной почты", "This is a preview of this room. Room interactions have been disabled": "Это просмотр данной комнаты. Взаимодействия с ней были отключены.", From fe487232ade5ebe30e3e1b7b60b08574d7729f0e Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 7 Jun 2017 18:15:48 +0100 Subject: [PATCH 175/275] sync fullstops everywhere --- scripts/fix-i18n.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/fix-i18n.pl b/scripts/fix-i18n.pl index 247b2b663f..ea19d710df 100755 --- a/scripts/fix-i18n.pl +++ b/scripts/fix-i18n.pl @@ -61,6 +61,11 @@ You are already in a call. You cannot place VoIP calls in this browser. You cannot place a call with yourself. Your email address does not appear to be associated with a Matrix ID on this Homeserver. +Guest users can't upload files. Please register to upload. +Some of your messages have not been sent. +This room is private or inaccessible to guests. You may be able to join if you register. +Tried to load a specific point in this room's timeline, but was unable to find it. +Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question. EOT )]; } From ef2fedc3a9ead6c38888276ad93aed361ef6d6eb Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 7 Jun 2017 18:24:35 +0100 Subject: [PATCH 176/275] fix missing translations and typos in i18n --- src/components/structures/CreateRoom.js | 2 +- src/components/views/dialogs/SetMxIdDialog.js | 6 +++--- src/i18n/strings/de_DE.json | 2 +- src/i18n/strings/en_EN.json | 4 +++- src/i18n/strings/en_US.json | 2 +- src/i18n/strings/fr.json | 2 +- src/i18n/strings/pt.json | 2 +- src/i18n/strings/pt_BR.json | 2 +- src/i18n/strings/ru.json | 2 +- 9 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/structures/CreateRoom.js b/src/components/structures/CreateRoom.js index 3e291dfd94..7ecc315ba7 100644 --- a/src/components/structures/CreateRoom.js +++ b/src/components/structures/CreateRoom.js @@ -231,7 +231,7 @@ module.exports = React.createClass({ if (curr_phase == this.phases.ERROR) { error_box = (
- {_t('An error occured: %(error_string)s', {error_string: this.state.error_string})} + {_t('An error occurred: %(error_string)s', {error_string: this.state.error_string})}
); } diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 78576eb1e4..2081701c6b 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -125,8 +125,8 @@ export default React.createClass({ break; case "M_INVALID_USERNAME": newState.usernameError = _t( - 'Username invalid: %(errMessage)', - { errMessage: err.message}, + 'Username invalid: %(error_message)s', + { error_message: err.message}, ); break; case "M_UNRECOGNIZED": @@ -139,7 +139,7 @@ export default React.createClass({ break; default: newState.usernameError = _t( - 'An error occurred: %(errMessage)', + 'An error occurred: %(errMessage)s', { errMessage: err.message }, ); break; diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 513faea017..798540900c 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -339,7 +339,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "Benutzernamen sollen nur Buchstaben, Nummern, Binde- und Unterstriche enthalten.", "An unknown error occurred.": "Ein unbekannter Fehler trat auf.", "I already have an account": "Ich habe bereits einen Account", - "An error occured: %(error_string)s": "Ein Fehler trat auf: %(error_string)s", + "An error occurred: %(error_string)s": "Ein Fehler trat auf: %(error_string)s", "Topic": "Thema", "Make this room private": "Mache diesen Raum privat", "Share message history with new users": "Bisherigen Chatverlauf mit neuen Nutzern teilen", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index eb331c24a9..11af1c03df 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -268,6 +268,7 @@ "End-to-end encryption information": "End-to-end encryption information", "End-to-end encryption is in beta and may not be reliable": "End-to-end encryption is in beta and may not be reliable", "Enter Code": "Enter Code", + "Enter passphrase": "Enter passphrase", "Error": "Error", "Error decrypting attachment": "Error decrypting attachment", "Error: Problem communicating with the given homeserver.": "Error: Problem communicating with the given homeserver.", @@ -580,6 +581,7 @@ "User ID": "User ID", "User Interface": "User Interface", "User name": "User name", + "Username invalid: %(errMessage)s": "Username invalid: %(errMessage)s", "Users": "Users", "User": "User", "Verification Pending": "Verification Pending", @@ -661,7 +663,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "User names may only contain letters, numbers, dots, hyphens and underscores.", "An unknown error occurred.": "An unknown error occurred.", "I already have an account": "I already have an account", - "An error occured: %(error_string)s": "An error occured: %(error_string)s", + "An error occurred: %(error_string)s": "An error occurred: %(error_string)s", "Topic": "Topic", "Make Moderator": "Make Moderator", "Make this room private": "Make this room private", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index 19b854e936..96f2243f63 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -645,7 +645,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "User names may only contain letters, numbers, dots, hyphens and underscores.", "An unknown error occurred.": "An unknown error occurred.", "I already have an account": "I already have an account", - "An error occured: %(error_string)s": "An error occured: %(error_string)s", + "An error occurred: %(error_string)s": "An error occurred: %(error_string)s", "Topic": "Topic", "Make Moderator": "Make Moderator", "Make this room private": "Make this room private", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 80d2479c48..ff6cb57ab5 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -611,7 +611,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "Les noms d’utilisateurs ne peuvent contenir que des lettres, chiffres, points et tirets hauts ou bas.", "An unknown error occurred.": "Une erreur inconnue est survenue.", "I already have an account": "J’ai déjà un compte", - "An error occured: %(error_string)s": "Une erreur est survenue : %(error_string)s", + "An error occurred: %(error_string)s": "Une erreur est survenue : %(error_string)s", "Topic": "Sujet", "Make Moderator": "Nommer modérateur", "Make this room private": "Rendre ce salon privé", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 47260b4909..b76cf6a274 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -417,7 +417,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "Nomes de usuária/o podem conter apenas letras, números, pontos, hífens e linha inferior (_).", "An unknown error occurred.": "Um erro desconhecido ocorreu.", "I already have an account": "Eu já tenho uma conta", - "An error occured: %(error_string)s": "Um erro ocorreu: %(error_string)s", + "An error occurred: %(error_string)s": "Um erro ocorreu: %(error_string)s", "Topic": "Tópico", "Make this room private": "Tornar esta sala privada", "Share message history with new users": "Compartilhar histórico de mensagens com novas/os usuárias/os", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 13c9ec0737..f77ef74799 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -417,7 +417,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "Nomes de usuária/o podem conter apenas letras, números, pontos, hífens e linha inferior (_).", "An unknown error occurred.": "Um erro desconhecido ocorreu.", "I already have an account": "Eu já tenho uma conta", - "An error occured: %(error_string)s": "Um erro ocorreu: %(error_string)s", + "An error occurred: %(error_string)s": "Um erro ocorreu: %(error_string)s", "Topic": "Tópico", "Make this room private": "Tornar esta sala privada", "Share message history with new users": "Compartilhar histórico de mensagens com novas/os usuárias/os", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index cf9bd78ffd..61c82e6448 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -336,7 +336,7 @@ "User names may only contain letters, numbers, dots, hyphens and underscores.": "Имена пользователей могут только содержать буквы, числа, точки, дефисы и подчеркивания.", "An unknown error occurred.": "Произошла неизвестная ошибка.", "I already have an account": "У меня уже есть учетная запись", - "An error occured: %(error_string)s": "Произошла ошибка: %(error_string)s", + "An error occurred: %(error_string)s": "Произошла ошибка: %(error_string)s", "Topic": "Тема", "Make this room private": "Сделать эту комнату частной", "Share message history with new users": "Поделись историей сообщений с новыми учасниками", From 8228db88d2f8ea3f2acca0709dd431976c59192c Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 7 Jun 2017 18:28:49 +0100 Subject: [PATCH 177/275] oops, fix more i18n var name typos --- src/components/views/dialogs/SetMxIdDialog.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js index 2081701c6b..d428223ad6 100644 --- a/src/components/views/dialogs/SetMxIdDialog.js +++ b/src/components/views/dialogs/SetMxIdDialog.js @@ -125,8 +125,8 @@ export default React.createClass({ break; case "M_INVALID_USERNAME": newState.usernameError = _t( - 'Username invalid: %(error_message)s', - { error_message: err.message}, + 'Username invalid: %(errMessage)s', + { errMessage: err.message}, ); break; case "M_UNRECOGNIZED": @@ -139,8 +139,8 @@ export default React.createClass({ break; default: newState.usernameError = _t( - 'An error occurred: %(errMessage)s', - { errMessage: err.message }, + 'An error occurred: %(error_string)s', + { error_string: err.message }, ); break; } From f7ab6a574ccda7e6469ae1ec962a6aa0520c9991 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 7 Jun 2017 18:32:32 +0100 Subject: [PATCH 178/275] Remove unused string --- src/i18n/strings/de_DE.json | 1 - src/i18n/strings/en_EN.json | 1 - src/i18n/strings/en_US.json | 1 - src/i18n/strings/fr.json | 1 - src/i18n/strings/pt.json | 1 - src/i18n/strings/pt_BR.json | 1 - src/i18n/strings/ru.json | 1 - src/i18n/strings/th.json | 1 - 8 files changed, 8 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 798540900c..6d3abef3e4 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -615,7 +615,6 @@ "This action cannot be performed by a guest user. Please register to be able to do this": "Diese Aktion kann nicht von einem Gast ausgeführt werden. Bitte registriere dich um dies zu tun", "%(actionVerb)s this person?": "Diese Person %(actionVerb)s?", "This room has no local addresses": "Dieser Raum hat keine lokale Adresse", - "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst.", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden.", "Turn Markdown off": "Markdown abschalten", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 11af1c03df..6a7f01e9df 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -511,7 +511,6 @@ "There was a problem logging in.": "There was a problem logging in.", "This room has no local addresses": "This room has no local addresses", "This room is not recognised.": "This room is not recognised.", - "This room is private or inaccessible to guests. You may be able to join if you register.": "This room is private or inaccessible to guests. You may be able to join if you register.", "These are experimental features that may break in unexpected ways": "These are experimental features that may break in unexpected ways", "The visibility of existing history will be unchanged": "The visibility of existing history will be unchanged", "This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index 96f2243f63..6736e39276 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -501,7 +501,6 @@ "There was a problem logging in.": "There was a problem logging in.", "This room has no local addresses": "This room has no local addresses", "This room is not recognised.": "This room is not recognized.", - "This room is private or inaccessible to guests. You may be able to join if you register.": "This room is private or inaccessible to guests. You may be able to join if you register.", "These are experimental features that may break in unexpected ways": "These are experimental features that may break in unexpected ways", "The visibility of existing history will be unchanged": "The visibility of existing history will be unchanged", "This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ff6cb57ab5..bf05173356 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -478,7 +478,6 @@ "The remote side failed to pick up": "Le correspondant n’a pas décroché", "This room has no local addresses": "Ce salon n'a pas d'adresse locale", "This room is not recognised.": "Ce salon n'a pas été reconnu.", - "This room is private or inaccessible to guests. You may be able to join if you register.": "Ce salon est privé ou non autorisé aux visiteurs. Vous devriez pouvoir le rejoindre si vous vous enregistrez.", "These are experimental features that may break in unexpected ways": "Ces fonctionnalités sont expérimentales et risquent de mal fonctionner", "The visibility of existing history will be unchanged": "La visibilité de l’historique existant sera inchangée", "This doesn't appear to be a valid email address": "Cette adresse n’a pas l’air d’être valide", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index b76cf6a274..27d257de9e 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -633,7 +633,6 @@ "This action cannot be performed by a guest user. Please register to be able to do this": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso", "%(actionVerb)s this person?": "%(actionVerb)s esta pessoa?", "This room has no local addresses": "Esta sala não tem endereços locais", - "This room is private or inaccessible to guests. You may be able to join if you register.": "Esta sala é privada ou inacessível para visitantes. Você poderá ingressar nela se registrar-se.", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas não o encontrei.", "Turn Markdown off": "Desabilitar a formatação 'Markdown'", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index f77ef74799..99175c874e 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -633,7 +633,6 @@ "This action cannot be performed by a guest user. Please register to be able to do this": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso", "%(actionVerb)s this person?": "%(actionVerb)s esta pessoa?", "This room has no local addresses": "Esta sala não tem endereços locais", - "This room is private or inaccessible to guests. You may be able to join if you register.": "Esta sala é privada ou inacessível para visitantes. Você poderá ingressar nela se registrar-se.", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas não o encontrei.", "Turn Markdown off": "Desabilitar a formatação 'Markdown'", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 61c82e6448..58f8e0291c 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -583,7 +583,6 @@ "The remote side failed to pick up": "Удалённая сторона не смогла ответить", "This room has no local addresses": "Эта комната не имеет местного адреса", "This room is not recognised.": "Эта комната не опознана.", - "This room is private or inaccessible to guests. You may be able to join if you register.": "Эта комната личная или недоступна для гостей. Мы может быть войдёте, если зарегистрируйтесь.", "These are experimental features that may break in unexpected ways": "Это экспериментальные функции, которые могут неожиданным образом вызывать ошибки", "This doesn't appear to be a valid email address": "Не похоже, что это правильный адрес электронной почты", "This is a preview of this room. Room interactions have been disabled": "Это просмотр данной комнаты. Взаимодействия с ней были отключены.", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index db67539b38..5bafdc97cd 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -318,7 +318,6 @@ "The file '%(fileName)s' failed to upload": "การอัปโหลดไฟล์ '%(fileName)s' ล้มเหลว", "This Home Server does not support login using email address.": "เซิร์ฟเวอร์บ้านนี้ไม่รองรับการลงชื่อเข้าใช้ด้วยที่อยู่อีเมล", "There was a problem logging in.": "มีปัญหาในการลงชื่อเข้าใช้", - "This room is private or inaccessible to guests. You may be able to join if you register": "ห้องนี้เป็นส่วนตัวหรือไม่อนุญาตให้แขกเข้าถึง คุณอาจเข้าร่วมได้หากคุณลงทะเบียน", "this invitation?": "คำเชิญนี้?", "This is a preview of this room. Room interactions have been disabled": "นี่คือตัวอย่างของห้อง การตอบสนองภายในห้องถูกปิดใช้งาน", "This phone number is already in use": "หมายเลขโทรศัพท์นี้ถูกใช้งานแล้ว", From 0170a12ad6d558ab03b9c4a2b4e53c6f65317839 Mon Sep 17 00:00:00 2001 From: Amandine Date: Wed, 7 Jun 2017 17:08:15 +0000 Subject: [PATCH 179/275] Translated using Weblate (French) Currently translated at 97.0% (825 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index c4a606b9bc..c7bff8977b 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -830,5 +830,9 @@ "Hide removed messages": "Cacher les messages supprimés", "Add": "Ajouter", "%(count)s new messages.one": "%(count)s nouveau message", - "%(count)s new messages.other": "%(count)s nouveaux messages" + "%(count)s new messages.other": "%(count)s nouveaux messages", + "Disable markdown formatting": "Désactiver le formattage markdown", + "Error: Problem communicating with the given homeserver.": "Erreur: Problème de communication avec le homeserveur.", + "Failed to fetch avatar URL": "Échec lors de la récupération de l’URL de l’avatar", + "The phone number entered looks invalid": "Le numéro de téléphone entré semble être invalide" } From ca5215a28841a7123ade7ddc0e8015f2310248e1 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Wed, 7 Jun 2017 17:34:00 +0000 Subject: [PATCH 180/275] Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 79603ad361..0d952ffcd9 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -114,7 +114,7 @@ "Failed to change password. Is your password correct?": "Passwortänderung fehlgeschlagen. Ist dein Passwort richtig?", "Failed to forget room": "Vergessen des Raums schlug fehl", "Failed to leave room": "Verlassen des Raums fehlgeschlagen", - "Failed to reject invitation": "Fehler beim Abweisen der Einladung", + "Failed to reject invitation": "Einladung konnte nicht abgelehnt werden", "Failed to set avatar.": "Fehler beim Setzen des Profilbilds.", "Failed to unban": "Entbannen fehlgeschlagen", "Failed to upload file": "Datei-Upload fehlgeschlagen", @@ -418,7 +418,7 @@ "Press": "Drücke", "tag as %(tagName)s": "als %(tagName)s taggen", "to browse the directory": "um das Raum-Verzeichnis zu durchsuchen", - "to demote": "um die Priorität herabzusetzen", + "to demote": "um das Berechtigungslevel herabzusetzen", "to favourite": "zum Favorisieren", "to make a room or": "um einen Raum zu erstellen, oder", "to restore": "zum wiederherstellen", @@ -618,7 +618,7 @@ "This room is private or inaccessible to guests. You may be able to join if you register": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen", "Tried to load a specific point in this room's timeline, but was unable to find it": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden", - "Turn Markdown off": "Markdown abschalten", + "Turn Markdown off": "Markdown deaktiveren", "Turn Markdown on": "Markdown einschalten", "Unable to load device list": "Geräteliste konnte nicht geladen werden", "Unknown command": "Unbekannter Befehl", @@ -786,7 +786,7 @@ "This image cannot be displayed.": "Dieses Bild kann nicht angezeigt werden.", "Error decrypting video": "Video-Entschlüsselung fehlgeschlagen", "Import room keys": "Importiere Raum-Schlüssel", - "File to import": "Datei zum Importieren", + "File to import": "Zu importierende Datei", "Failed to invite the following users to the %(roomName)s room:": "Das Einladen der folgenden Nutzer in den Raum \"%(roomName)s\" ist fehlgeschlagen:", "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Bist du sicher, dass du dieses Ereignis entfernen (löschen) möchtest? Wenn du die Änderung eines Raum-Namens oder eines Raum-Themas löscht, kann dies dazu führen, dass die ursprüngliche Änderung rückgängig gemacht wird.", "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Dieser Prozess erlaubt es dir, die Schlüssel für in verschlüsselten Räumen empfangene Nachrichten in eine lokale Datei zu exportieren. In Zukunft wird es möglich sein, diese Datei in einen anderen Matrix-Client zu importieren, sodass dieser Client ebenfalls diese Nachrichten entschlüsseln kann.", @@ -828,7 +828,7 @@ "Invited": "Eingeladen", "Set a Display Name": "Setze einen Anzeigenamen", "for %(amount)ss": "für %(amount)ss", - "for %(amount)sm": "für %(amount)sm", + "for %(amount)sm": "seit %(amount)smin", "for %(amount)sh": "für %(amount)sh", "for %(amount)sd": "für %(amount)sd", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s hat das Raum-Bild entfernt.", @@ -906,7 +906,7 @@ "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere werden hochgeladen", "You must register to use this functionality": "Du musst dich registrieren um diese Funktionalität zu nutzen", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Sende erneut oder breche alles ab. Du kannst auch auch individuelle Nachrichten erneut senden or abbrechen.", - "Create new room": "Erstelle neuen Raum", + "Create new room": "Neuen Raum erstellen", "Welcome page": "Willkommensseite", "Room directory": "Raum-Verzeichnis", "Start chat": "Starte Chat", From 8d7f40ed075a550ce289f4fadc333fe1a2c589bf Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Wed, 7 Jun 2017 17:33:48 +0000 Subject: [PATCH 181/275] Translated using Weblate (Thai) Currently translated at 40.8% (347 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index a05f5c8f68..2f64cdaf71 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -323,7 +323,7 @@ "This is a preview of this room. Room interactions have been disabled": "นี่คือตัวอย่างของห้อง การตอบสนองภายในห้องถูกปิดใช้งาน", "This phone number is already in use": "หมายเลขโทรศัพท์นี้ถูกใช้งานแล้ว", "This room's internal ID is": "ID ภายในของห้องนี้คือ", - "times": "เวลา", + "times": "ครั้ง", "%(oneUser)schanged their name": "%(oneUser)sเปลี่ยนชื่อของเขาแล้ว", "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)sเปลี่ยนชื่อของพวกเขา %(repeats)s ครั้ง", "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)sเปลี่ยนชื่อของเขา %(repeats)s ครั้ง", @@ -331,5 +331,20 @@ "Create new room": "สร้างห้องใหม่", "Room directory": "ไดเรกทอรีห้อง", "Start chat": "เริ่มแชท", - "Welcome page": "หน้าต้อนรับ" + "Welcome page": "หน้าต้อนรับ", + "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "ไม่สามารถเชื่อมต่อไปยังเซิร์ฟเวอร์บ้านผ่านทาง HTTP ได้เนื่องจาก URL ที่อยู่บนเบราว์เซอร์เป็น HTTPS กรุณาใช้ HTTPS หรือเปิดใช้งานสคริปต์ที่ไม่ปลอดภัย.", + "%(count)s new messages.one": "มี %(count)s ข้อความใหม่", + "%(count)s new messages.other": "มี %(count)s ข้อความใหม่", + "Disable inline URL previews by default": "ตั้งค่าเริ่มต้นให้ไม่แสดงตัวอย่าง URL ในแชท", + "Disable markdown formatting": "ปิดใช้งานการจัดรูปแบบ markdown", + "End-to-end encryption information": "ข้อมูลการเข้ารหัสจากปลายทางถึงปลายทาง", + "End-to-end encryption is in beta and may not be reliable": "การเข้ารหัสจากปลายทางถึงปลายทางยังอยู่ในเบต้า และอาจพึ่งพาไม่ได้", + "Error: Problem communicating with the given homeserver.": "ข้อผิดพลาด: มีปัญหาในการติดต่อกับเซิร์ฟเวอร์บ้านที่กำหนด", + "Export E2E room keys": "ส่งออกกุญแจถอดรหัส E2E", + "Failed to change power level": "การเปลี่ยนระดับอำนาจล้มเหลว", + "Import E2E room keys": "นำเข้ากุญแจถอดรหัส E2E", + "to favourite": "ไปยังรายการโปรด", + "to demote": "เพื่อลดขั้น", + "The default role for new room members is": "บทบาทเริ่มต้นของสมาชิกใหม่คือ", + "The phone number entered looks invalid": "ดูเหมือนว่าหมายเลขโทรศัพท์ที่กรอกรมาไม่ถูกต้อง" } From 5cf44454d2b463fe5543a439992a270398aec3f1 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 7 Jun 2017 18:41:18 +0100 Subject: [PATCH 182/275] fix more punctuation fails --- src/i18n/strings/th.json | 1 + src/i18n/strings/zh_Hans.json | 4 ++-- src/i18n/strings/zh_Hant.json | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 5bafdc97cd..f5564415fc 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -318,6 +318,7 @@ "The file '%(fileName)s' failed to upload": "การอัปโหลดไฟล์ '%(fileName)s' ล้มเหลว", "This Home Server does not support login using email address.": "เซิร์ฟเวอร์บ้านนี้ไม่รองรับการลงชื่อเข้าใช้ด้วยที่อยู่อีเมล", "There was a problem logging in.": "มีปัญหาในการลงชื่อเข้าใช้", + "This room is private or inaccessible to guests. You may be able to join if you register.": "ห้องนี้เป็นส่วนตัวหรือไม่อนุญาตให้แขกเข้าถึง คุณอาจเข้าร่วมได้หากคุณลงทะเบียน", "this invitation?": "คำเชิญนี้?", "This is a preview of this room. Room interactions have been disabled": "นี่คือตัวอย่างของห้อง การตอบสนองภายในห้องถูกปิดใช้งาน", "This phone number is already in use": "หมายเลขโทรศัพท์นี้ถูกใช้งานแล้ว", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 54a6886b35..e0db2b525b 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -76,7 +76,7 @@ "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s 从 %(fromPowerLevel)s 变为 %(toPowerLevel)s", "Guests can't set avatars. Please register.": "游客不能设置头像。请注册。.", "Guest users can't create new rooms. Please register to create room and start a chat.": "游客不能创建聊天室。请注册以创建聊天室和聊天.", - "Guest users can't upload files. Please register to upload": "游客不能上传文件。请注册以上传文件", + "Guest users can't upload files. Please register to upload.": "游客不能上传文件。请注册以上传文件", "Guests can't use labs features. Please register.": "游客不能使用实验性功能。请注册。.", "Guests cannot join this room even if explicitly invited.": "游客不能加入此聊天室,即使有人主动邀请。.", "had": "已经", @@ -138,7 +138,7 @@ "since the point in time of selecting this option": "从选择此选项起", "since they joined": "从他们加入时起", "since they were invited": "从他们被邀请时起", - "Some of your messages have not been sent": "部分消息发送失败", + "Some of your messages have not been sent.": "部分消息发送失败", "Someone": "某个用户", "Sorry, this homeserver is using a login which is not recognised ": "很抱歉,无法识别此主服务器使用的登录方式 ", "Start a chat": "创建聊天", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 250dc23ef3..17901789e9 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -194,7 +194,7 @@ "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s 從 %(fromPowerLevel)s 變為 %(toPowerLevel)s", "Guests can't set avatars. Please register.": "游客不能設置頭像。請注冊。.", "Guest users can't create new rooms. Please register to create room and start a chat.": "游客不能創建聊天室。請注冊以創建聊天室和聊天.", - "Guest users can't upload files. Please register to upload": "游客不能上傳文件。請注冊以上傳文件", + "Guest users can't upload files. Please register to upload.": "游客不能上傳文件。請注冊以上傳文件", "Guests can't use labs features. Please register.": "游客不能使用實驗性功能。請注冊。.", "Guests cannot join this room even if explicitly invited.": "游客不能加入此聊天室,即使有人主動邀請。.", "had": "已經", @@ -265,7 +265,7 @@ "since the point in time of selecting this option": "從選擇此選項起", "since they joined": "從他們加入時起", "since they were invited": "從他們被邀請時起", - "Some of your messages have not been sent": "部分消息發送失敗", + "Some of your messages have not been sent.": "部分消息發送失敗", "Someone": "某個用戶", "Sorry, this homeserver is using a login which is not recognised ": "很抱歉,無法識別此主伺服器使用的登錄方式 ", "Start a chat": "創建聊天", From ca1c0e42b0559b2095b2a99783a0f946f020dc89 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Wed, 7 Jun 2017 18:42:34 +0100 Subject: [PATCH 183/275] oops, merge correctly --- src/i18n/strings/th.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index f5564415fc..5bafdc97cd 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -318,7 +318,6 @@ "The file '%(fileName)s' failed to upload": "การอัปโหลดไฟล์ '%(fileName)s' ล้มเหลว", "This Home Server does not support login using email address.": "เซิร์ฟเวอร์บ้านนี้ไม่รองรับการลงชื่อเข้าใช้ด้วยที่อยู่อีเมล", "There was a problem logging in.": "มีปัญหาในการลงชื่อเข้าใช้", - "This room is private or inaccessible to guests. You may be able to join if you register.": "ห้องนี้เป็นส่วนตัวหรือไม่อนุญาตให้แขกเข้าถึง คุณอาจเข้าร่วมได้หากคุณลงทะเบียน", "this invitation?": "คำเชิญนี้?", "This is a preview of this room. Room interactions have been disabled": "นี่คือตัวอย่างของห้อง การตอบสนองภายในห้องถูกปิดใช้งาน", "This phone number is already in use": "หมายเลขโทรศัพท์นี้ถูกใช้งานแล้ว", From ea02d8841c991e1b595a8e87f166170ddc61b2bb Mon Sep 17 00:00:00 2001 From: RiotTranslate Date: Wed, 7 Jun 2017 19:48:48 +0200 Subject: [PATCH 184/275] Update from Weblate. (#1052) * Added translation using Weblate (Thai) * Translated using Weblate (Thai) Currently translated at 2.6% (22 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (Thai) Currently translated at 8.9% (74 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.8% (826 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Swedish) Currently translated at 35.4% (293 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/sv/ * Translated using Weblate (Thai) Currently translated at 9.7% (81 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 100.0% (827 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Russian) Currently translated at 76.9% (636 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (Hungarian) Currently translated at 0.1% (1 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/hu/ * Translated using Weblate (Thai) Currently translated at 39.2% (325 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.8% (827 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (German) Currently translated at 99.8% (827 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Thai) Currently translated at 39.7% (329 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.8% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Hungarian) Currently translated at 3.1% (26 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/hu/ * Translated using Weblate (Russian) Currently translated at 77.4% (641 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (Thai) Currently translated at 39.7% (329 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (Russian) Currently translated at 100.0% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (German) Currently translated at 100.0% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Russian) Currently translated at 100.0% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (French) Currently translated at 96.5% (821 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ * Translated using Weblate (Thai) Currently translated at 39.0% (332 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/de_DE.json | 109 +++++++++++------ src/i18n/strings/fr.json | 5 +- src/i18n/strings/hu.json | 27 ++++- src/i18n/strings/ru.json | 228 +++++++++++++++++++++++++++++++++--- src/i18n/strings/th.json | 16 ++- 5 files changed, 322 insertions(+), 63 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 6d3abef3e4..f7b3d16ebc 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -6,7 +6,7 @@ "People": "Direkt-Chats", "Rooms": "Räume", "Low priority": "Niedrige Priorität", - "Historical": "Historisch", + "Historical": "Archiv", "New passwords must match each other.": "Die neuen Passwörter müssen identisch sein.", "A new password must be entered.": "Es muss ein neues Passwort eingegeben werden.", "The email address linked to your account must be entered.": "Es muss die Email-Adresse eingeben werden, welche zum Account gehört.", @@ -42,7 +42,7 @@ "Commands": "Kommandos", "Emoji": "Emoji", "Sorry, this homeserver is using a login which is not recognised ": "Entschuldigung, dieser Homeserver nutzt eine Anmeldetechnik, die nicht bekannt ist ", - "Login as guest": "Anmelden als Gast", + "Login as guest": "Als Gast anmelden", "Return to app": "Zurück zur Anwendung", "Sign in": "Anmelden", "Create a new account": "Erstelle einen neuen Benutzer", @@ -75,7 +75,7 @@ "changed the topic to": "änderte das Thema zu", "Changes to who can read history will only apply to future messages in this room": "Änderungen, die bestimmen, wer den Chatverlauf lesen kann, gelten nur für zukünftige Nachrichten in diesem Raum", "Clear Cache and Reload": "Cache leeren und neu laden", - "Click here": "Klicke hier", + "Click here": "Hier klicken,", "Confirm your new password": "Neues Passwort bestätigen", "Continue": "Fortfahren", "Create an account": "Erstelle einen Account", @@ -96,7 +96,7 @@ "End-to-end encryption is in beta and may not be reliable": "Die Ende-zu-Ende-Verschlüsselung befindet sich aktuell im Beta-Stadium und ist eventuell noch nicht hundertprozentig zuverlässig", "Failed to send email": "Fehler beim Senden der E-Mail", "Account": "Konto", - "Add phone number": "Füge Telefonnummer hinzu", + "Add phone number": "Telefonnummer hinzufügen", "an address": "an Adresse", "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "Dein Passwort wurde erfolgreich geändert. Du wirst erst Benachrichtigungen auf anderen Geräten empfangen können, wenn du dich dort erneut anmeldest", "all room members": "Alle Raum-Mitglieder", @@ -111,7 +111,7 @@ "Default": "Standard", "demote": "Berechtigungslevel herabstufen", "Export E2E room keys": "E2E-Raum-Schlüssel exportieren", - "Failed to change password. Is your password correct?": "Passwort-Änderung schlug fehl. Ist dein Passwort korrekt?", + "Failed to change password. Is your password correct?": "Passwortänderung fehlgeschlagen. Ist dein Passwort richtig?", "Failed to forget room": "Vergessen des Raums schlug fehl", "Failed to leave room": "Verlassen des Raums fehlgeschlagen", "Failed to reject invitation": "Fehler beim Abweisen der Einladung", @@ -140,12 +140,12 @@ "is a": "ist ein", "is trusted": "wird vertraut", "Sign in with": "Ich möchte mich anmelden mit", - "joined and left": "trat bei und ging", - "joined": "trat bei", + "joined and left": "hat den Raum betreten und wieder verlassen", + "joined": "hat den Raum betreten", "joined the room": "trat dem Raum bei", "Leave room": "Verlasse Raum", "left and rejoined": "ging(en) und trat(en) erneut bei", - "left": "ging", + "left": "hat den Raum verlassen", "left the room": "verließ den Raum", "Logged in as": "Angemeldet als", "Logout": "Abmelden", @@ -204,7 +204,7 @@ "Signed Out": "Abgemeldet", "Sign out": "Abmelden", "since the point in time of selecting this option": "ab dem Zeitpunkt, an dem diese Option gewählt wird", - "since they joined": "seitdem sie beitraten", + "since they joined": "ab dem Zeitpunkt, an dem sie beigetreten sind", "since they were invited": "seitdem sie eingeladen wurden", "Someone": "Jemand", "Start a chat": "Starte einen Chat", @@ -336,8 +336,8 @@ "Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Passwort zu kurz (min. %(MIN_PASSWORD_LENGTH)s).", "This doesn't look like a valid email address.": "Dies scheint keine gültige E-Mail-Adresse zu sein.", "This doesn't look like a valid phone number.": "Dies scheint keine gültige Telefonnummer zu sein.", - "User names may only contain letters, numbers, dots, hyphens and underscores.": "Benutzernamen sollen nur Buchstaben, Nummern, Binde- und Unterstriche enthalten.", - "An unknown error occurred.": "Ein unbekannter Fehler trat auf.", + "User names may only contain letters, numbers, dots, hyphens and underscores.": "Benutzernamen dürfen nur Buchstaben, Nummern, Punkte, Binde- und Unterstriche enthalten.", + "An unknown error occurred.": "Ein unbekannter Fehler ist aufgetreten.", "I already have an account": "Ich habe bereits einen Account", "An error occurred: %(error_string)s": "Ein Fehler trat auf: %(error_string)s", "Topic": "Thema", @@ -352,7 +352,7 @@ "%(names)s and %(count)s others are typing": "%(names)s und %(count)s weitere Personen schreiben", "%(senderName)s answered the call.": "%(senderName)s hat den Anruf angenommen.", "%(senderName)s banned %(targetName)s.": "%(senderName)s hat %(targetName)s aus dem Raum verbannt.", - "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s hat den Anzeigenamen von %(oldDisplayName)s auf %(displayName)s geändert.", + "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s hat den Anzeigenamen von \"%(oldDisplayName)s\" auf \"%(displayName)s\" geändert.", "%(senderName)s changed their profile picture.": "%(senderName)s hat das Profilbild geändert.", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s hat das Berechtigungslevel von %(powerLevelDiffText)s geändert.", "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s änderte den Raumnamen zu %(roomName)s.", @@ -364,7 +364,7 @@ "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s von %(fromPowerLevel)s zu %(toPowerLevel)s", "%(senderName)s invited %(targetName)s.": "%(senderName)s hat %(targetName)s eingeladen.", "%(displayName)s is typing": "%(displayName)s schreibt", - "%(targetName)s joined the room.": "%(targetName)s trat dem Raum bei.", + "%(targetName)s joined the room.": "%(targetName)s hat den Raum betreten.", "%(senderName)s kicked %(targetName)s.": "%(senderName)s kickte %(targetName)s.", "%(targetName)s left the room.": "%(targetName)s hat den Raum verlassen.", "%(senderName)s made future room history visible to": "%(senderName)s machte die zukünftige Raumhistorie sichtbar für", @@ -378,12 +378,12 @@ "Reason": "Grund", "%(targetName)s rejected the invitation.": "%(targetName)s hat die Einladung abgelehnt.", "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s löschte den Anzeigenamen (%(oldDisplayName)s).", - "%(senderName)s removed their profile picture.": "%(senderName)s löschte das Profilbild.", + "%(senderName)s removed their profile picture.": "%(senderName)s hat das Profilbild gelöscht.", "%(senderName)s requested a VoIP conference.": "%(senderName)s möchte eine VoIP-Konferenz beginnen.", "Room %(roomId)s not visible": "Raum %(roomId)s ist nicht sichtbar", "%(senderDisplayName)s sent an image.": "%(senderDisplayName)s hat ein Bild gesendet.", "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s hat %(targetDisplayName)s in diesen Raum eingeladen.", - "%(senderName)s set a profile picture.": "%(senderName)s setzte ein Profilbild.", + "%(senderName)s set a profile picture.": "%(senderName)s hat ein Profilbild gesetzt.", "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s hat den Anzeigenamen geändert in %(displayName)s.", "This room is not recognised.": "Dieser Raum wurde nicht erkannt.", "These are experimental features that may break in unexpected ways": "Dies sind experimentelle Funktionen, die in unerwarteter Weise Fehler verursachen können", @@ -398,7 +398,7 @@ "There are no visible files in this room": "Es gibt keine sichtbaren Dateien in diesem Raum", "Error changing language": "Fehler beim Ändern der Sprache", "Riot was unable to find the correct Data for the selected Language.": "Riot war nicht in der Lage die korrekten Daten für die ausgewählte Sprache zu finden.", - "Connectivity to the server has been lost.": "Verbindung zum Server untergebrochen.", + "Connectivity to the server has been lost.": "Verbindung zum Server wurde unterbrochen.", "Sent messages will be stored until your connection has returned.": "Gesendete Nachrichten werden gespeichert, bis die Internetverbindung wiederhergestellt wurde.", "Auto-complete": "Autovervollständigung", "Resend all": "Alle erneut senden", @@ -427,7 +427,7 @@ "You're not in any rooms yet! Press": "Du bist noch keinem Raum beigetreten! Drücke", "click to reveal": "Klicke zum anzeigen", "To remove other users' messages": "Um Nachrichten anderer Nutzer zu verbergen", - "You are trying to access %(roomName)s": "Du versuchst auf %(roomName)s zuzugreifen", + "You are trying to access %(roomName)s": "Du versuchst, auf den Raum \"%(roomName)s\" zuzugreifen", "af": "Afrikaans", "ar-ae": "Arabisch (VAE)", "ar-bh": "Arabisch (Bahrain)", @@ -558,7 +558,7 @@ "Are you sure?": "Bist du sicher?", "Attachment": "Anhang", "Ban": "Verbannen", - "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Kann nicht zum Heimserver verbinden - bitte checke eine Verbindung und stelle sicher, dass dem SSL-Zertifikat deines Heimservers vertraut wird.", + "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Verbindungsaufbau zum Heimserver nicht möglich - bitte Internetverbindung überprüfen und sicherstellen, ob das SSL-Zertifikat des Heimservers vertrauenswürdig ist.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Kann nicht zum Heimserver via HTTP verbinden, wenn eine HTTPS-Url in deiner Adresszeile steht. Nutzer HTTPS oder aktiviere unsichere Skripte.", "changing room on a RoomView is not supported": "Das Ändern eines Raumes in einer RaumAnsicht wird nicht unterstützt", "Click to mute audio": "Klicke um den Ton stumm zu stellen", @@ -590,7 +590,7 @@ "'%(alias)s' is not a valid format for an alias": "'%(alias)s' hat kein valides Aliasformat", "Join Room": "Dem Raum beitreten", "Kick": "Kicke", - "Level": "Level", + "Level": "Berechtigungslevel", "Local addresses for this room:": "Lokale Adressen dieses Raumes:", "Markdown is disabled": "Markdown ist deaktiviert", "Markdown is enabled": "Markdown ist aktiviert", @@ -652,25 +652,25 @@ "%(items)s and one other": "%(items)s und ein(e) weitere(r)", "%(items)s and %(lastItem)s": "%(items)s und %(lastItem)s", "%(severalUsers)sjoined %(repeats)s times": "%(severalUsers)ssind dem Raum %(repeats)s mal beigetreten", - "%(oneUser)sjoined %(repeats)s times": "%(oneUser)strat %(repeats)s mal bei", - "%(severalUsers)sjoined": "%(severalUsers)straten bei", - "%(oneUser)sjoined": "%(oneUser)strat bei", + "%(oneUser)sjoined %(repeats)s times": "%(oneUser)shat den Raum %(repeats)s mal betreten", + "%(severalUsers)sjoined": "%(severalUsers)shaben den Raum betreten", + "%(oneUser)sjoined": "%(oneUser)shat den Raum betreten", "%(severalUsers)sleft %(repeats)s times": "%(severalUsers)sverließen %(repeats)s mal den Raum", "%(oneUser)sleft %(repeats)s times": "%(oneUser)sging %(repeats)s mal", "%(severalUsers)sleft": "%(severalUsers)shaben den Raum verlassen", "%(oneUser)sleft": "%(oneUser)sging", - "%(severalUsers)sjoined and left %(repeats)s times": "%(severalUsers)straten bei und gingen %(repeats)s mal", - "%(oneUser)sjoined and left %(repeats)s times": "%(oneUser)strat bei und ging %(repeats)s mal", - "%(severalUsers)sjoined and left": "%(severalUsers)straten bei und gingen", - "%(oneUser)sjoined and left": "%(oneUser)strat bei und ging", + "%(severalUsers)sjoined and left %(repeats)s times": "%(severalUsers)shaben den Raum %(repeats)s mal betreten und wieder verlassen", + "%(oneUser)sjoined and left %(repeats)s times": "%(oneUser)shat den Raum %(repeats)s mal betreten und wieder verlassen", + "%(severalUsers)sjoined and left": "%(severalUsers)shaben den Raum betreten und wieder verlassen", + "%(oneUser)sjoined and left": "%(oneUser)shat den Raum betreten und wieder verlassen", "%(severalUsers)sleft and rejoined %(repeats)s times": "%(severalUsers)shaben den Raum verlassen und %(repeats)s mal neu betreten", - "%(oneUser)sleft and rejoined %(repeats)s times": "%(oneUser)sging und trat %(repeats)s mal erneut bei", - "%(severalUsers)sleft and rejoined": "%(severalUsers)s gingen und traten erneut bei", + "%(oneUser)sleft and rejoined %(repeats)s times": "%(oneUser)shat den Raum %(repeats)s mal verlassen und wieder neu betreten", + "%(severalUsers)sleft and rejoined": "%(severalUsers)shaben den Raum verlassen und wieder neu betreten", "%(oneUser)sleft left and rejoined": "%(oneUser)sging und trat erneut bei", - "%(severalUsers)srejected their invitations %(repeats)s times": "%(severalUsers)s lehnten %(repeats)s mal ihre Einladung ab", + "%(severalUsers)srejected their invitations %(repeats)s times": "%(severalUsers)shaben ihre Einladung %(repeats)s mal abgelehnt", "%(oneUser)srejected their invitation %(repeats)s times": "%(oneUser)shat die Einladung %(repeats)s mal abgelehnt", - "%(severalUsers)srejected their invitations": "%(severalUsers)slehnten ihre Einladung ab", - "%(oneUser)srejected their invitation": "%(oneUser)slehnte seine/ihre Einladung ab", + "%(severalUsers)srejected their invitations": "%(severalUsers)shaben ihre Einladung abgelehnt", + "%(oneUser)srejected their invitation": "%(oneUser)shat die Einladung abgelehnt", "%(severalUsers)shad their invitations withdrawn %(repeats)s times": "%(severalUsers)szogen ihre Einladungen %(repeats)s mal zurück", "%(oneUser)shad their invitation withdrawn %(repeats)s times": "%(oneUser)szog seine/ihre Einladung %(repeats)s mal zurück", "%(severalUsers)shad their invitations withdrawn": "%(severalUsers)szogen ihre Einladungen zurück", @@ -687,16 +687,16 @@ "were kicked %(repeats)s times": "wurden %(repeats)s mal gekickt", "was kicked %(repeats)s times": "wurde %(repeats)s mal gekickt", "were kicked": "wurden aus dem Raum entfernt", - "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)sänderten %(repeats)s mal ihre Namen", - "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)sänderte %(repeats)s mal seinen/ihren Namen", + "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)shaben ihren Namen %(repeats)s mal geändert", + "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)shat den Namen %(repeats)s mal geändert", "%(severalUsers)schanged their name": "%(severalUsers)shaben ihre Namen geändert", - "%(oneUser)schanged their name": "%(oneUser)sänderte seinen/ihren Namen", + "%(oneUser)schanged their name": "%(oneUser)shat den Namen geändert", "%(severalUsers)schanged their avatar %(repeats)s times": "%(severalUsers)shaben %(repeats)s mal ihr Profilbild geändert", "%(oneUser)schanged their avatar %(repeats)s times": "%(oneUser)shat %(repeats)s mal das Profilbild geändert", "%(severalUsers)schanged their avatar": "%(severalUsers)shaben ihr Profilbild geändert", "%(oneUser)schanged their avatar": "%(oneUser)shat das Profilbild geändert", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(day)s. %(monthName)s %(fullYear)s %(time)s", - "%(oneUser)sleft and rejoined": "%(oneUser)sverließ den Raum und trat erneut bei", + "%(oneUser)sleft and rejoined": "%(oneUser)shat den Raum verlassen und wieder neu betreten", "A registered account is required for this action": "Für diese Aktion ist ein registrierter Account notwendig", "Access Token:": "Zugangs-Token:", "Always show message timestamps": "Nachrichten-Zeitstempel immer anzeigen", @@ -727,7 +727,7 @@ "Invalid file%(extra)s": "Ungültige Datei%(extra)s", "Remove %(threePid)s?": "Entferne %(threePid)s?", "Please select the destination room for this message": "Bitte den Raum auswählen, an den diese Nachricht gesendet werden soll", - "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s löschte den Raumnamen.", + "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s hat den Raum-Namen gelöscht.", "Passphrases must match": "Passphrase muss übereinstimmen", "Passphrase must not be empty": "Passphrase darf nicht leer sein", "Export room keys": "Raum-Schlüssel exportieren", @@ -861,8 +861,8 @@ "device id: ": "Geräte-ID: ", "Device key:": "Geräte-Schlüssel:", "Email address (optional)": "E-Mail-Adresse (optional)", - "List this room in %(domain)s's room directory?": "Liste diesen Raum in %(domain)s's Raumverzeichnis?", - "Mobile phone number (optional)": "Handynummer (optional)", + "List this room in %(domain)s's room directory?": "Diesen Raum zum Raum-Verzeichnis von %(domain)s hinzufügen?", + "Mobile phone number (optional)": "Mobilfunknummer (optional)", "Password:": "Passwort:", "Register": "Registrieren", "Save": "Speichern", @@ -888,5 +888,36 @@ "$senderDisplayName changed the room avatar to ": "$senderDisplayName hat das Raum-Bild geändert zu ", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s hat das Raum-Bild für %(roomName)s geändert", "Hide removed messages": "Gelöschte Nachrichten verbergen", - "Start new chat": "Neuen Chat starten" + "Start new chat": "Neuen Chat starten", + "Disable markdown formatting": "Deaktiviere Markdown-Formatierung", + "Add": "Hinzufügen", + "%(count)s new messages.one": "%(count)s neue Nachricht", + "%(count)s new messages.other": "%(count)s neue Nachrichten", + "Error: Problem communicating with the given homeserver.": "Fehler: Problem beim kommunizieren mit dem angegebenen Heimserver.", + "Failed to fetch avatar URL": "Fehler beim holen der Avatar-URL", + "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", + "The phone number entered looks invalid": "Die Telefonnummer, die eingegeben wurde, sieht ungültig aus", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht betretbar. Du kannst evtl. beitreten wenn du dich registrierst.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber du hast keine Berechtigung diese Nachricht zu sehen.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber er konnte nicht gefunden werden.", + "Uploading %(filename)s and %(count)s others.zero": "%(filename)s wird hochgeladen", + "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere werden hochgeladen", + "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere werden hochgeladen", + "You must register to use this functionality": "Du musst dich registrieren um diese Funktionalität zu nutzen", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Sende erneut oder breche alles ab. Du kannst auch auch individuelle Nachrichten erneut senden or abbrechen.", + "Create new room": "Erstelle neuen Raum", + "Welcome page": "Willkommensseite", + "Room directory": "Raum-Verzeichnis", + "Start chat": "Starte Chat", + "New Password": "Neues Passwort", + "Start chatting": "Starte plaudern", + "Start Chatting": "Starte Gespräche", + "Click on the button below to start chatting!": "Klicke den Button unten um das Plaudern zu beginnen!", + "Create a new chat or reuse an existing one": "Erstelle einen neuen Chat oder nutze einen existierenden", + "You already have existing direct chats with this user:": "Du hast bereits direkte Chats mit diesem Nutzer:", + "Username available": "Nutzername verfügbar", + "Username not available": "Nutzername nicht verfügbar", + "Something went wrong!": "Etwas ging schief!", + "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", + "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Konto hast, kannst du ansonsten auch anmelden." } diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index bf05173356..ecbb20fbb7 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -826,5 +826,8 @@ "You have disabled URL previews by default.": "Vous avez désactivé les aperçus d’URL par défaut.", "You have enabled URL previews by default.": "Vous avez activé les aperçus d’URL par défaut.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Vous avez entré un contact invalide. Essayez d’utiliser leur identifiant Matrix ou leur adresse email.", - "Hide removed messages": "Cacher les messages supprimés" + "Hide removed messages": "Cacher les messages supprimés", + "Add": "Ajouter", + "%(count)s new messages.one": "%(count)s nouveau message", + "%(count)s new messages.other": "%(count)s nouveaux messages" } diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 5430737f15..748810f76e 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -1,3 +1,28 @@ { - "Cancel": "Mégse" + "Cancel": "Mégse", + "Search": "Keresés", + "OK": "Rendben", + "Custom Server Options": "Egyedi szerver beállítások", + "Direct Chat": "Közvetlen csevegés", + "Dismiss": "Eltűntet", + "Drop here %(toAction)s": "%(toAction)s -t húzd ide", + "Error": "Hiba", + "Failed to forget room %(errCode)s": "Nem lehet eltávolítani a szobát: %(errCode)s", + "Failed to join the room": "Nem lehet csatlakozni a szobához", + "Favourite": "Kedvenc", + "Mute": "Elnémít", + "Notifications": "Értesítések", + "Operation failed": "Művelet sikertelen", + "Please Register": "Regisztrálj", + "powered by Matrix": "Matrixon alapul", + "Remove": "Töröl", + "Settings": "Beállítások", + "unknown error code": "ismeretlen hiba kód", + "Sunday": "Vasárnap", + "Monday": "Hétfő", + "Tuesday": "Kedd", + "Wednesday": "Szerda", + "Thursday": "Csütörtök", + "Friday": "Péntek", + "Saturday": "Szombat" } diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 58f8e0291c..85b7a6a7f5 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -84,11 +84,11 @@ "Failed to upload file": "Не удалось закачать файл", "Favourite": "Избранное", "favourite": "фаворит", - "Favourites": "Фавориты", + "Favourites": "Избранное", "Filter room members": "Фильтр участников комнаты", "Forget room": "Забыть комнату", "Forgot your password?": "Вы забыли пароль?", - "For security, this session has been signed out. Please sign in again.": "Для обеспечения безопасности, эта сессия была подписана. Войдите в систему еще раз.", + "For security, this session has been signed out. Please sign in again.": "Для обеспечения безопасности эта сессия была завершена. Войдите в систему еще раз.", "Found a bug?": "Нашли ошибку?", "had": "имеет", "Hangup": "Отключение", @@ -153,7 +153,7 @@ "requested a VoIP conference": "requested a VoIP conference", "Return to login screen": "Return to login screen", "Send Reset Email": "Send Reset Email", - "sent an image": "sent an image", + "sent an image": "отправил изображение", "sent an invitation to": "sent an invitation to", "set a profile picture": "set a profile picture", "set their display name to": "set their display name to", @@ -228,7 +228,7 @@ "%(senderName)s banned %(targetName)s.": "%(senderName)s запрещенный %(targetName)s.", "Call Timeout": "Время ожидания вызова", "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s их имя измененное с %(oldDisplayName)s на %(displayName)s.", - "%(senderName)s changed their profile picture.": "%(senderName)s измененное ихнее фото профиля.", + "%(senderName)s changed their profile picture.": "%(senderName)s изменил фото профиля.", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s уровень мощности изменен на %(powerLevelDiffText)s.", "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s имя комнаты измененно на %(roomName)s.", "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s измененная тема на %(topic)s.", @@ -254,7 +254,7 @@ "%(targetName)s joined the room.": "%(targetName)s вошёл в комнату.", "%(senderName)s kicked %(targetName)s.": "%(senderName)s выкинул %(targetName)s.", "%(targetName)s left the room.": "%(targetName)s покинул комнату.", - "%(senderName)s made future room history visible to": "%(senderName)s история сделаной будущей комнаты, видимая для", + "%(senderName)s made future room history visible to": "%(senderName)s сделал видимой для всех будущую историю комнаты", "Missing room_id in request": "Отсутствует room_id в запросе", "Missing user_id in request": "Отсутствует user_id в запросе", "Must be viewing a room": "Комната должна быть посищена", @@ -356,8 +356,8 @@ "Saturday": "Суббота", "Sunday": "Воскресенье", "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", - "Upload an avatar:": "Загрузить аватар", - "You need to be logged in.": "Вы должны быть зарегистрированы", + "Upload an avatar:": "Загрузите аватар:", + "You need to be logged in.": "Вы должны быть зарегистрированы.", "You need to be able to invite users to do that.": "Вам необходимо пригласить пользователей чтобы сделать это.", "You cannot place VoIP calls in this browser.": "Вы не можете сделать вызовы VoIP с этим браузером.", "You are already in a call.": "Вы уже находитесь в разговоре.", @@ -377,7 +377,7 @@ "Oct": "Окт.", "Nov": "Ноя.", "Dec": "Дек.", - "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(time)s", + "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(time)s", "Mon": "Пн", "Sun": "Вс", "Tue": "Вт", @@ -388,8 +388,8 @@ "You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver. This is a once off; sorry for the inconvenience.": "Вам необходимо снова войти в генерировать сквозное шифрование (е2е) ключей для этого устройства и предоставить публичный ключ Вашему домашнему серверу. Это после выключения; приносим извинения за причиненные неудобства.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Ваш адрес электронной почты, кажется, не связан с Matrix ID на этом Homeserver.", "to start a chat with someone": "Начать чат с кем-то", - "to tag direct chat": "отометить прямой чат", - "To use it, just wait for autocomplete results to load and tab through them.": "Для его использования, просто подождите результатов автозаполнения для загрузки на вкладке и через них.", + "to tag direct chat": "отметить прямой чат", + "To use it, just wait for autocomplete results to load and tab through them.": "Для его использования просто подождите загрузки результатов автозаполнения и нажимайте Tab для навигации.", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s включил сквозное шифрование (algorithm %(algorithm)s).", "Unable to restore previous session": "Невозможно востановить предыдущий сеанс", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s запрет отменен %(targetName)s.", @@ -478,7 +478,7 @@ "Always show message timestamps": "Всегда показывать время сообщения", "Authentication": "Авторизация", "olm version:": "версия olm:", - "%(items)s and %(remaining)s others": "%(items)s и %(remaining)s другие", + "%(items)s and %(remaining)s others": "%(items)s и другие %(remaining)s", "%(items)s and one other": "%(items)s и ещё один", "%(items)s and %(lastItem)s": "%(items)s и %(lastItem)s", "and one other...": "и ещё один...", @@ -491,7 +491,7 @@ "Current password": "Текущий пароль", "Email": "Электронная почта", "Failed to kick": "Не удалось выгнать", - "Failed to load timeline position": "Не удалось узнать место во времени", + "Failed to load timeline position": "Не удалось загрузить позицию таймлайна", "Failed to mute user": "Не удалось заглушить", "Failed to reject invite": "Не удалось отклонить приглашение", "Failed to save settings": "Не удалось сохранить настройки", @@ -519,7 +519,7 @@ "New passwords don't match": "Пароли не совпадают", "not set": "не установлено", "not specified": "не указано", - "No devices with registered encryption keys": "Нет устройств с записанными ключами шифрования", + "No devices with registered encryption keys": "Нет устройств с зарегистрированными ключами шифрования", "No more results": "Нет больше результатов", "No results": "Нет результатов", "OK": "ОК", @@ -535,7 +535,7 @@ "rejected": "отклонено", "%(targetName)s rejected the invitation.": "%(targetName)s отклонил приглашение.", "Reject invitation": "Отклонить приглашение", - "Remove Contact Information?": "Убрать контактную информацию?", + "Remove Contact Information?": "Удалить контактную информацию?", "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s убрал своё отображаемое имя (%(oldDisplayName)s).", "%(senderName)s removed their profile picture.": "%(senderName)s убрал своё изображение.", "%(senderName)s requested a VoIP conference.": "%(senderName)s запросил голосовую конференц-связь.", @@ -585,7 +585,7 @@ "This room is not recognised.": "Эта комната не опознана.", "These are experimental features that may break in unexpected ways": "Это экспериментальные функции, которые могут неожиданным образом вызывать ошибки", "This doesn't appear to be a valid email address": "Не похоже, что это правильный адрес электронной почты", - "This is a preview of this room. Room interactions have been disabled": "Это просмотр данной комнаты. Взаимодействия с ней были отключены.", + "This is a preview of this room. Room interactions have been disabled": "Это просмотр данной комнаты. Взаимодействия с ней были отключены", "This phone number is already in use": "Этот телефонный номер уже используется", "This room's internal ID is": "Внутренний ID этой комнаты", "times": "раз", @@ -598,7 +598,7 @@ "Unknown room %(roomId)s": "Неизвестная комната %(roomId)s", "You have been invited to join this room by %(inviterName)s": "Вы были приглашены войти в эту комнату от %(inviterName)s", "You seem to be uploading files, are you sure you want to quit?": "Похоже вы передаёте файлы, вы уверены, что хотите выйти?", - "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s %(time)s", "Make Moderator": "Сделать модератором", "Room": "Комната", "Cancel": "Отмена", @@ -606,7 +606,7 @@ "italic": "наклонный", "strike": "перечёркнутый", "underline": "подчёркнутый", - "code": "текст", + "code": "код", "quote": "цитата", "bullet": "пункт", "numbullet": "нумерация", @@ -672,5 +672,197 @@ "Logged in as:": "Зарегестрирован как:", "Default Device": "Стандартное устройство", "No Webcams detected": "Веб-камера не обнаружена", - "VoIP": "VoIP" + "VoIP": "VoIP", + "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Для обеспечения безопасности выход из системы удалит все ключи шифроования из этого браузера. Если вы хотите иметь возможность расшифровать переписку в будущем - вы должны экспортирвать ключи вручную.", + "Guest access is disabled on this Home Server.": "Гостевой доступ отключен на этом сервере.", + "Guests can't set avatars. Please register.": "Гости не могут устанавливать аватар. Пожалуйста, зарегистрируйтесь.", + "Guests can't use labs features. Please register.": "Гости не могут использовать экспериментальные возможности. Пожалуйста, зарегистрируйтесь.", + "Guests cannot join this room even if explicitly invited.": "Гости не могут заходить в эту комнату если не были приглашены.", + "Missing Media Permissions, click here to request.": "Отсутствуют разрешения, нажмите для запроса.", + "No media permissions": "Нет медиа разрешений", + "You may need to manually permit Riot to access your microphone/webcam": "Вам необходимо предоставить Riot доступ к микрофону или веб-камере вручную", + "Anyone": "Все", + "Are you sure you want to leave the room '%(roomName)s'?": "Вы уверены, что хотите покинуть '%(roomName)s'?", + "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s удалил имя комнаты.", + "Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Смена пароля также сбросит все ключи шифрования на всех устройствах, сделав зашифрованную историю недоступной, если только вы сначала не экспортируете ключи шифрования и не импортируете их потом. В будущем это будет исправлено.", + "Custom level": "Пользовательский уровень", + "(default: %(userName)s)": "(по-умолчанию: %(userName)s)", + "Device already verified!": "Устройство уже верифицировано!", + "Device ID:": "ID устройства:", + "device id: ": "id устройства: ", + "Device key:": "Ключ устройства:", + "disabled": "отключено", + "Disable markdown formatting": "Отключить форматирование Markdown", + "Email address": "Адрес email", + "Email address (optional)": "Адрем email (не обязательно)", + "enabled": "включено", + "Error decrypting attachment": "Ошибка расшифровки файла", + "Export": "Экспорт", + "Failed to register as guest:": "Ошибка регистрации как гостя:", + "Failed to set avatar.": "Не удалось установить аватар.", + "Import": "Импорт", + "Incorrect username and/or password.": "Неверное имя пользователя и/или пароль.", + "Invalid file%(extra)s": "Неправильный файл%(extra)s", + "Invited": "Приглашен", + "Jump to first unread message.": "Перейти к первому непрочитанному сообщению.", + "List this room in %(domain)s's room directory?": "Показывать эту комнату в списке комнат %(domain)s?", + "Message not sent due to unknown devices being present": "Сообщение не было отправлено из-за присутствия неизвестного устройства", + "Mobile phone number (optional)": "Номер мобильного телефона (не обязательно)", + "Once you've followed the link it contains, click below": "Как только вы пройдете по ссылке, нажмите на кнопку ниже", + "Password:": "Пароль:", + "Privacy warning": "Предупреждение приватности", + "Privileged Users": "Привилегированные пользователи", + "Revoke Moderator": "Снять модераторские права", + "Refer a friend to Riot:": "Расскажите другу о Riot:", + "Register": "Регистрация", + "Remote addresses for this room:": "Удаленные адреса для этой комнаты:", + "Remove %(threePid)s?": "Удалить %(threePid)s?", + "Results from DuckDuckGo": "Результаты от DuckDuckGo", + "Save": "Сохранить", + "Searches DuckDuckGo for results": "Ищет результаты через DuckDuckGo", + "Server error": "Ошибка сервера", + "Server may be unavailable or overloaded": "Сервер может быть недоступен или перегружен", + "Server may be unavailable, overloaded, or search timed out :(": "Сервер может быть недоступен, перегружен или поиск прекращен по тайм-ауту :(", + "Server may be unavailable, overloaded, or the file too big": "Сервер может быть недоступен, перегружен или размер файла слишком большой", + "Server may be unavailable, overloaded, or you hit a bug.": "Сервер может быть недоступен, перегружен или вы нашли баг.", + "Server unavailable, overloaded, or something else went wrong.": "Сервер может быть недоступен, перегружен или произошло что-то страшное.", + "Session ID": "ID сессии", + "%(senderName)s set a profile picture.": "%(senderName)s установил картинку профиля.", + "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s установил отображаемое имя %(displayName)s.", + "Setting a user name will create a fresh account": "Установка имени пользователя создаст новую учетную запись", + "Signed Out": "Вышли", + "Sorry, this homeserver is using a login which is not recognised ": "Извините, этот Home Server использует логин, который не удалось распознать ", + "Tagged as: ": "Теги: ", + "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "Ключ, предоставленный вами, совпадает с ключем, полученным от устройства %(userId)s с ID %(deviceId)s. Устройство помечено как верифицированное.", + "%(actionVerb)s this person?": "%(actionVerb)s этого пользователя?", + "The file '%(fileName)s' exceeds this home server's size limit for uploads": "Файл '%(fileName)s' превышает ограничение размера загрузок на этом Home Server'е", + "This Home Server does not support login using email address.": "Этот Home Server не поддерживает вход по адресу email.", + "There was a problem logging in.": "Возникла проблема входа в учетную запись.", + "The visibility of existing history will be unchanged": "Видимость текущей истории не будет изменена", + "this invitation?": "это приглашение?", + "This room is not accessible by remote Matrix servers": "Это комната закрыта для других серверов Matrix", + "To ban users": "Забанить пользователей", + "to browse the directory": "просматривать директорию", + "To configure the room": "Конфигурировать комнату", + "To invite users into the room": "Приглашать пользователей в комнату", + "to join the discussion": "присоединиться к дискуссии", + "To kick users": "Выгонять пользователей", + "To link to a room it must have": "Для создания ссылки на комнату она должна иметь", + "to make a room or": "создать комнату или", + "To remove other users' messages": "Удалять сообщения других пользователей", + "To reset your password, enter the email address linked to your account": "Чтобы сбросить ваш пароль введите адрес email, который используется аккаунтом", + "to tag as %(tagName)s": "отметить как %(tagName)s", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Вы попытались загрузить указанное сообщение в комнате, однако у вас нету разрешений для его просмотра", + "Tried to load a specific point in this room's timeline, but was unable to find it": "Вы попытались загрузить указанное сообщение в комнате, однако сервер не смог его найти", + "Unable to load device list": "Невозможно загрузить список устройств", + "Unknown (user, device) pair:": "Неизвестная пара пользователь-устройство:", + "Unmute": "Разглушить", + "Unrecognised command:": "Неизвестная команда:", + "Unrecognised room alias:": "Неизвестный псевдоним комнаты:", + "Verified key": "Верифицированный ключ", + "WARNING: Device already verified, but keys do NOT MATCH!": "ВНИМАНИЕ: устройство уже было верифицировано, однако ключи НЕ СОВПАДАЮТ!", + "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "ВНИМАНИЕ: ОШИБКА ВЕРИФИКАЦИИ КЛЮЧЕЙ! Ключ для подписки устройства %(deviceId)s пользователя %(userId)s: \"%(fprint)s\", однако он не совпадает с предоставленным ключем \"%(fingerprint)s\". Это может означать перехват вашего канала коммуникации!", + "You have disabled URL previews by default.": "Предпросмотр ссылок отключен по-умолчанию.", + "You have enabled URL previews by default.": "Предпросмотр ссылок включен по-умолчанию.", + "You have entered an invalid contact. Try using their Matrix ID or email address.": "Вы ввели неправильный адрес. Попробуйте использовать Matrix ID или адрес email.", + "You need to enter a user name.": "Необходимо ввести имя пользователя.", + "You seem to be in a call, are you sure you want to quit?": "Вы учавствуете в звонке, вы уверены, что хотите выйти?", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "Вы не сможете отменить это действие так как даете пользователю такой же уровень доступа как и у вас", + "Set a Display Name": "Установить отображаемое имя", + "(~%(searchCount)s results)": "(~%(searchCount)s результатов)", + "%(severalUsers)shad their invitations withdrawn %(repeats)s times": "%(severalUsers)s отозвали свои приглашения %(repeats)s раз", + "%(oneUser)shad their invitation withdrawn %(repeats)s times": "%(oneUser)s отозвал свои приглашения %(repeats)s раз", + "%(severalUsers)shad their invitations withdrawn": "%(severalUsers)s отозвали свои приглашения", + "%(oneUser)shad their invitation withdrawn": "%(oneUser)s отозвал свое приглашение", + "Please select the destination room for this message": "Выберите комнату назначения для этого сообщения", + "Options": "Настройки", + "Passphrases must match": "Пароли должны совпадать", + "Passphrase must not be empty": "Пароль не должен быть пустым", + "Export room keys": "Экспортировать ключи", + "Enter passphrase": "Введите пароль", + "Confirm passphrase": "Подтвердите пароль", + "Import room keys": "Импортировать ключи", + "File to import": "Файл для импорта", + "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Этот процесс позволяет вам экспортировать ключи для сообщений, которые вы получили в комнатах с шифрованием, в локальный файл. Вы сможете импортировать эти ключи в другой клиент Matrix чтобы расшифровать эти сообщения.", + "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "Экспортированный файл позволит любому пользователю расшифровать и зашифровать сообщения, которые вы видите, поэтому вы должны быть крайне осторожны и держать файл в надежном месте. Чтобы поспособствовать этому вы должны ввести пароль, который будет использоваться для шифрования ключей. Вы сможете импоортировать ключи только зная этот пароль.", + "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "Этот процесс позволяем вам импортировать ключи шифрования, которые вы экспортировали ранее из клиента Matrix. После импорта вы сможете читать зашифрованную переписку и отправлять шифрованные сообщения.", + "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Экспортированный файл защищен паролем. Вы должны ввести этот пароль для расшифровки.", + "You must join the room to see its files": "Вы должны зайти в комнату для просмотра файлов", + "Reject all %(invitedRooms)s invites": "Отклонить все %(invitedRooms)s приглашения", + "Start new chat": "Начать новый чат", + "Guest users can't invite users. Please register.": "Гости не могут приглашать пользователей. Пожалуйста, зарегистрируйтесь.", + "Failed to invite": "Ошибка приглашения", + "Failed to invite user": "Ошибка приглашения пользователя", + "Failed to invite the following users to the %(roomName)s room:": "Ошибка приглашения следующих пользователей в %(roomName)s:", + "Confirm Removal": "Подтвердите удаление", + "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Вы уверены, что хотите удалить этот эвент? Обратите внимание, что если это смена имени комнаты или топика, то удаление отменит это изменение.", + "Unknown error": "Неизвестная ошибка", + "Incorrect password": "Неправильный пароль", + "This will make your account permanently unusable. You will not be able to re-register the same user ID.": "Это сделает вашу учетную запись нерабочей. Вы не сможете зарегистрироваться снова с тем же ID.", + "This action is irreversible.": "Это действие необратимо.", + "To continue, please enter your password.": "Для продолжения введите ваш пароль.", + "To verify that this device can be trusted, please contact its owner using some other means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings for this device matches the key below:": "Для верификации устройства, пожалуйста, свяжитесь с владельцем используя другие методы коммуникации (например, лично или по телефону) и попросите его подтвердить, что он видит такой же ключ как написанный ниже:", + "Device name": "Имя устройства", + "Device key": "Ключ устройства", + "If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.": "Если совпадают, то нажмите кнопку верификации ниже. Если нет, то кто-то перехватил это устройство или ключ и вы, скорее всего, захотите внести его в черный список.", + "In future this verification process will be more sophisticated.": "В будущем процесс верификации будет усложнен.", + "Verify device": "Верифицировать устройство", + "I verify that the keys match": "Я верифицирую - ключи совпадают", + "We encountered an error trying to restore your previous session. If you continue, you will need to log in again, and encrypted chat history will be unreadable.": "Обнаружена ошибка при восстановлении вашей предыдущей сессии. Вам необходимо зайти снова, шифрованные сообщения будут нечитаемы.", + "Unable to restore session": "Невозможно восстановить сессию", + "If you have previously used a more recent version of Riot, your session may be incompatible with this version. Close this window and return to the more recent version.": "Если вы использовали более новую версию Riot, то ваша сессия может быть несовместима с текущей. Закройте это окно и вернитесь к использованию более новой версии.", + "Continue anyway": "Все равно продолжить", + "Your display name is how you'll appear to others when you speak in rooms. What would you like it to be?": "Отображаемое имя - это то, как вы отображаетесь в чате. Какое имя вы хотите?", + "You are currently blacklisting unverified devices; to send messages to these devices you must verify them.": "Пока что вы вносите неверифицированные устройства в черный список автоматически. Для отправки сообщений на эти устройства вам необходимо их верифицировать.", + "We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.": "Рекомендуется сначала верифицировать устройства для подтверждения их владения правильным пользователем, но вы можете отправить сообщение без верификации, если хотите.", + "\"%(RoomName)s\" contains devices that you haven't seen before.": "\"%(RoomName)s\" содержит неизвестные прежде устройства.", + "Unknown Address": "Неизвестный адрес", + "Unblacklist": "Удалить из черного списка", + "Blacklist": "Добавить в черный список", + "Unverify": "Убрать верификацию", + "Verify...": "Верифицировать...", + "ex. @bob:example.com": "например @bob:example.com", + "Add User": "Добавить пользователя", + "This Home Server would like to make sure you are not a robot": "Этот Home Server хочет удостовериться что вы не робот", + "Sign in with CAS": "Войти с помощью CAS", + "You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "Вы можете использовать пользовательские настройки сервера для использования другого Home Server'а при помощи указания его URL.", + "This allows you to use this app with an existing Matrix account on a different home server.": "Это позволяет использовать это приложение с существующей учетной записью на другом Home Server'е.", + "You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "Вы также можете указать пользовательский сервер идентификации, но это обычно ломает возможность общаться с пользователями с помощью адреса email.", + "Please check your email to continue registration.": "Проверьте свою почту для продолжения регистрации.", + "Token incorrect": "Неправильный токен", + "A text message has been sent to": "Текстовое сообщение было отправлено", + "Please enter the code it contains:": "Введите содержащийся код:", + "If you don't specify an email address, you won't be able to reset your password. Are you sure?": "Если вы не укажете адрес email, то вы не сможете сбросить свой пароль в будущем. Вы уверены?", + "You are registering with %(SelectedTeamName)s": "Вы регистрируетесь на %(SelectedTeamName)s", + "Default server": "Сервер по-умолчанию", + "Custom server": "Пользовательский сервер", + "Home server URL": "URL Home Server'а", + "Identity server URL": "URL сервера идентификации", + "What does this mean?": "Что это значит?", + "Error decrypting audio": "Ошибка расшифровки аудио", + "Error decrypting image": "Ошибка расшифровки изображения", + "Image '%(Body)s' cannot be displayed.": "Изображение '%(Body)s' не может быть отображено.", + "This image cannot be displayed.": "Это изображение не может быть отображено.", + "Error decrypting video": "Ошибка расшифровки видео", + "Add an Integration": "Добавить интеграцию", + "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "Вы будете перенаправлены на внешний сайт, где вы сможете аутентифицировать свою учетную запись для использования с %(integrationsUrl)s. Вы хотите продолжить?", + "Removed or unknown message type": "Удаленный или неизвестный тип сообщения", + "Disable URL previews by default for participants in this room": "Отключить предпросмотр URL для участников этой комнаты по-умолчанию", + "URL previews are %(globalDisableUrlPreview)s by default for participants in this room.": "Предпросмотр URL %(globalDisableUrlPreview)s по-умолчанию для участников этой комнаты.", + "URL Previews": "Предпросмотр URL", + "Enable URL previews for this room (affects only you)": "Включить предпросмотр URL в этой комнате (только для вас)", + "Drop file here to upload": "Перетащите файл сюда для загрузки", + " (unsupported)": " (не поддерживается)", + "Ongoing conference call%(supportedText)s. %(joinText)s": "Идет конференц-звонок%(supportedText)s. %(joinText)s", + "for %(amount)ss": "для %(amount)s", + "for %(amount)sm": "для %(amount)s", + "for %(amount)sh": "для %(amount)s", + "for %(amount)sd": "для %(amount)s", + "Online": "В сети", + "Idle": "Отошел", + "Offline": "Не в сети", + "Disable URL previews for this room (affects only you)": "Отключить предпросмотр URL в этой комнате (только для вас)", + "$senderDisplayName changed the room avatar to ": "$senderDisplayName сменил аватар комнаты на ", + "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s удалил аватар комнаты.", + "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s сменил аватар для %(roomName)s" } diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 5bafdc97cd..6608219faa 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -25,7 +25,7 @@ "(default: %(userName)s)": "(ค่าเริ่มต้น: %(userName)s)", "Default Device": "อุปกรณ์เริ่มต้น", "%(senderName)s banned %(targetName)s.": "%(senderName)s แบน %(targetName)s แล้ว", - "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s เปลี่ยนหัวข้อเป็น \"%(topic)s\" แล้ว", + "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s เปลี่ยนหัวข้อเป็น \"%(topic)s\"", "Decrypt %(text)s": "ถอดรหัส %(text)s", "Device ID": "ID อุปกรณ์", "Device ID:": "ID อุปกรณ์:", @@ -96,8 +96,8 @@ "all room members, from the point they are invited": "สมาชิกทั้งหมด นับตั้งแต่เมื่อได้รับคำเชิญ", "all room members, from the point they joined": "สมาชิกทั้งหมด นับตั้งแต่เมื่อเข้าร่วมห้อง", "an address": "ที่อยู่", - "%(items)s and %(remaining)s others": "%(items)s และอีก %(remaining)s อย่าง", - "%(items)s and one other": "%(items)s และอีกหนึ่งอย่าง", + "%(items)s and %(remaining)s others": "%(items)s และอีก %(remaining)s ผู้ใช้", + "%(items)s and one other": "%(items)s และอีกหนึ่งผู้ใช้", "%(items)s and %(lastItem)s": "%(items)s และ %(lastItem)s", "and %(overflowCount)s others...": "และอีก %(overflowCount)s ผู้ใช้...", "and one other...": "และอีกหนึ่งผู้ใช้...", @@ -322,5 +322,13 @@ "This is a preview of this room. Room interactions have been disabled": "นี่คือตัวอย่างของห้อง การตอบสนองภายในห้องถูกปิดใช้งาน", "This phone number is already in use": "หมายเลขโทรศัพท์นี้ถูกใช้งานแล้ว", "This room's internal ID is": "ID ภายในของห้องนี้คือ", - "times": "เวลา" + "times": "เวลา", + "%(oneUser)schanged their name": "%(oneUser)sเปลี่ยนชื่อของเขาแล้ว", + "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)sเปลี่ยนชื่อของพวกเขา %(repeats)s ครั้ง", + "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)sเปลี่ยนชื่อของเขา %(repeats)s ครั้ง", + "%(severalUsers)schanged their name": "%(severalUsers)sเปลี่ยนชื่อของพวกเขาแล้ว", + "Create new room": "สร้างห้องใหม่", + "Room directory": "ไดเรกทอรีห้อง", + "Start chat": "เริ่มแชท", + "Welcome page": "หน้าต้อนรับ" } From 93fcd0aa4047db9edaa3dd435d9aa5e05fce70d0 Mon Sep 17 00:00:00 2001 From: Amandine Date: Wed, 7 Jun 2017 18:02:20 +0000 Subject: [PATCH 185/275] Translated using Weblate (French) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index c7bff8977b..4d01492815 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -834,5 +834,30 @@ "Disable markdown formatting": "Désactiver le formattage markdown", "Error: Problem communicating with the given homeserver.": "Erreur: Problème de communication avec le homeserveur.", "Failed to fetch avatar URL": "Échec lors de la récupération de l’URL de l’avatar", - "The phone number entered looks invalid": "Le numéro de téléphone entré semble être invalide" + "The phone number entered looks invalid": "Le numéro de téléphone entré semble être invalide", + "Guest users can't upload files. Please register to upload.": "Les visiteurs ne peuvent pas télécharger de fichier. Veuillez vous enregistrer pour télécharger.", + "Some of your messages have not been sent.": "Certains de vos messages n’ont pas été envoyés.", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Ce salon est privé ou interdits aux visiteurs. Vous pourrez peut-être le joindre si vous vous enregistrez.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Un instant donné de la chronologie n’a pu être chargé car vous n’avez pas la permission de le visualiser.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Un instant donné de la chronologie n’a pu être chargé car il n’a pas pu être trouvé.", + "Uploading %(filename)s and %(count)s others.zero": "Téléchargement de %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "Téléchargement de %(filename)s et %(count)s autre", + "Uploading %(filename)s and %(count)s others.other": "Téléchargement de %(filename)s et %(count)s autres", + "You must register to use this functionality": "Vous devez vous inscrire pour utiliser cette fonctionnalité", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Tout renvoyer or tout annuler maintenant. Vous pouvez aussi sélectionner des messages individuels à envoyer ou annuler.", + "Create new room": "Créer un nouveau salon", + "Welcome page": "Page d'accueil", + "Room directory": "Répertoire des salons", + "Start chat": "Démarrer une discussion", + "New Password": "Nouveau mot de passe", + "Start chatting": "Démarrer une discussion", + "Start Chatting": "Démarrer une discussion", + "Click on the button below to start chatting!": "Cliquer sur le bouton ci-dessous pour commencer une discussion !", + "Create a new chat or reuse an existing one": "Démarrer une nouvelle discussion ou en réutiliser une existante", + "You already have existing direct chats with this user:": "Vous avez déjà des discussions en cours avec cet utilisateur :", + "Username available": "Nom d'utilisateur disponible", + "Username not available": "Nom d'utilisateur indisponible", + "Something went wrong!": "Quelque chose s’est mal passé !", + "This will be your account name on the homeserver, or you can pick a different server.": "Cela sera le nom de votre compte sur le serveur , ou vous pouvez sélectionner un autre serveur.", + "If you already have a Matrix account you can log in instead.": "Si vous avez déjà un compte Matrix vous pouvez vous identifier à la place." } From 8833dc64b7267aa7491c407e3115762431456030 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Wed, 7 Jun 2017 18:02:34 +0000 Subject: [PATCH 186/275] Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 0d952ffcd9..abf1eea088 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -182,7 +182,7 @@ "Once you've followed the link it contains, click below": "Nachdem du dem darin enthaltenen Link gefolgt bist, klicke unten", "rejected the invitation.": "lehnte die Einladung ab.", "Reject invitation": "Einladung ablehnen", - "Remove Contact Information?": "Kontakt-Informationen löschen?", + "Remove Contact Information?": "Kontakt-Informationen entfernen?", "removed their display name": "löschte den eigenen Anzeigenamen", "Remove": "Entfernen", "requested a VoIP conference": "hat eine VoIP-Konferenz angefordert", @@ -271,7 +271,7 @@ "Who would you like to communicate with?": "Mit wem möchtest du kommunizieren?", "Would you like to": "Möchtest du", "You do not have permission to post to this room": "Du hast keine Berechtigung an diesen Raum etwas zu senden", - "You have been invited to join this room by %(inviterName)s": "Du wurdest von %(inviterName)s in diesen Raum eingeladen", + "You have been invited to join this room by %(inviterName)s": "%(inviterName)s hat dich in diesen Raum eingeladen", "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Du wurdest auf allen Geräten abgemeldet und wirst keine Push-Benachrichtigungen mehr erhalten. Um die Benachrichtigungen zu reaktivieren, musst du dich auf jedem Gerät neu anmelden", "you must be a": "nötige Rolle", "Your password has been reset": "Dein Passwort wurde zurückgesetzt", @@ -377,7 +377,7 @@ "Power level must be positive integer.": "Berechtigungslevel muss eine positive ganze Zahl sein.", "Reason": "Grund", "%(targetName)s rejected the invitation.": "%(targetName)s hat die Einladung abgelehnt.", - "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s löschte den Anzeigenamen (%(oldDisplayName)s).", + "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s hat den Anzeigenamen entfernt (%(oldDisplayName)s).", "%(senderName)s removed their profile picture.": "%(senderName)s hat das Profilbild gelöscht.", "%(senderName)s requested a VoIP conference.": "%(senderName)s möchte eine VoIP-Konferenz beginnen.", "Room %(roomId)s not visible": "Raum %(roomId)s ist nicht sichtbar", @@ -902,8 +902,8 @@ "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber du hast keine Berechtigung diese Nachricht zu sehen.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber er konnte nicht gefunden werden.", "Uploading %(filename)s and %(count)s others.zero": "%(filename)s wird hochgeladen", - "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere werden hochgeladen", - "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere werden hochgeladen", + "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere Dateien werden hochgeladen", + "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere Dateien werden hochgeladen", "You must register to use this functionality": "Du musst dich registrieren um diese Funktionalität zu nutzen", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Sende erneut oder breche alles ab. Du kannst auch auch individuelle Nachrichten erneut senden or abbrechen.", "Create new room": "Neuen Raum erstellen", @@ -920,5 +920,5 @@ "Username not available": "Nutzername nicht verfügbar", "Something went wrong!": "Etwas ging schief!", "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", - "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Konto hast, kannst du ansonsten auch anmelden." + "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden." } From 6ae8172fa2a91f8ba90142d1f74eb0593e0ee5a1 Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Wed, 7 Jun 2017 18:03:05 +0000 Subject: [PATCH 187/275] Translated using Weblate (Thai) Currently translated at 49.5% (421 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 76 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 2f64cdaf71..716cdb34e2 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -346,5 +346,79 @@ "to favourite": "ไปยังรายการโปรด", "to demote": "เพื่อลดขั้น", "The default role for new room members is": "บทบาทเริ่มต้นของสมาชิกใหม่คือ", - "The phone number entered looks invalid": "ดูเหมือนว่าหมายเลขโทรศัพท์ที่กรอกรมาไม่ถูกต้อง" + "The phone number entered looks invalid": "ดูเหมือนว่าหมายเลขโทรศัพท์ที่กรอกรมาไม่ถูกต้อง", + "The email address linked to your account must be entered.": "กรุณากรอกที่อยู่อีเมลที่เชื่อมกับบัญชีของคุณ", + "The file '%(fileName)s' exceeds this home server's size limit for uploads": "ไฟล์ '%(fileName)s' มีขนาดใหญ่เกินจำกัดของเซิร์ฟเวอร์บ้าน", + "To send messages": "เพื่อส่งข้อความ", + "to start a chat with someone": "เพื่อเริ่มแชทกับผู้อื่น", + "to tag as %(tagName)s": "เพื่อแท็กว่า %(tagName)s", + "to tag direct chat": "เพื่อแทกว่าแชทตรง", + "Turn Markdown off": "ปิด markdown", + "Turn Markdown on": "เปิด markdown", + "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s ได้เปิดใช้งานการเข้ารหัสจากปลายทางถึงปลายทาง (อัลกอริทึม%(algorithm)s).", + "Unable to add email address": "ไมาสามารถเพิ่มที่อยู่อีเมล", + "Unable to verify email address.": "ไม่สามารถยืนยันที่อยู่อีเมล", + "Unban": "ปลดแบน", + "%(senderName)s unbanned %(targetName)s.": "%(senderName)s ปลดแบน %(targetName)s แล้ว", + "Unable to capture screen": "ไม่สามารถจับภาพหน้าจอ", + "Unable to enable Notifications": "ไม่สามารถเปิดใช้งานการแจ้งเตือน", + "Unable to load device list": "ไม่สามารถโหลดรายชื่ออุปกรณ์", + "Unencrypted room": "ห้องที่ไม่เข้ารหัส", + "unencrypted": "ยังไม่ได้เข้ารหัส", + "Unknown command": "คำสั่งที่ไม่รู้จัก", + "unknown device": "อุปกรณ์ที่ไม่รู้จัก", + "Unknown room %(roomId)s": "ห้องที่ไม่รู้จัก %(roomId)s", + "Unknown (user, device) pair:": "คู่ (ผู้ใช้, อุปกรณ์) ที่ไม่รู้จัก:", + "unknown": "ไม่รู้จัก", + "Unrecognised command:": "คำสั่งที่ไม่รู้จัก:", + "Unrecognised room alias:": "นามแฝงห้องที่ไม่รู้จัก:", + "Uploading %(filename)s and %(count)s others.zero": "กำลังอัปโหลด %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "กำลังอัปโหลด %(filename)s และอีก %(count)s ไฟล์", + "Uploading %(filename)s and %(count)s others.other": "กำลังอัปโหลด %(filename)s และอีก %(count)s ไฟล์", + "uploaded a file": "อัปโหลดไฟล์", + "Upload Failed": "การอัปโหลดล้มเหลว", + "Upload Files": "อัปโหลดไฟล์", + "Upload file": "อัปโหลดไฟล์", + "Usage": "การใช้งาน", + "User ID": "ID ผู้ใช้", + "User Interface": "อินเตอร์เฟสผู้ใช้", + "User name": "ชื่อผู้ใช้", + "User": "ผู้ใช้", + "Warning!": "คำเตือน!", + "Who can access this room?": "ใครสามารถเข้าถึงห้องนี้ได้?", + "Who can read history?": "ใครสามารถอ่านประวัติแชทได้?", + "Who would you like to add to this room?": "คุณต้องการเพิ่มใครเข้าห้องนี้?", + "Who would you like to communicate with?": "คุณต้องการสื่อสารกับใคร?", + "You're not in any rooms yet! Press": "คุณยังไม่ได้อยู่ในห้องใดเลย! กด", + "You are trying to access %(roomName)s": "คุณกำลังพยายามเข้าสู่ %(roomName)s", + "You have disabled URL previews by default.": "ค่าเริ่มต้นของคุณปิดใช้งานตัวอย่าง URL เอาไว้", + "You have enabled URL previews by default.": "ค่าเริ่มต้นของคุณเปิดใช้งานตัวอย่าง URL เอาไว้", + "you must be a": "คุณต้องเป็น", + "You must register to use this functionality": "คุณต้องลงทะเบียนเพื่อใช้ฟังก์ชันนี้", + "You need to be logged in.": "คุณต้องเข้าสู่ระบบก่อน", + "You need to enter a user name.": "คุณต้องกรอกชื่อผู้ใช้ก่อน", + "Your password has been reset": "รหัสผ่านถูกรีเซ็ตแล้ว", + "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "การเปลี่ยนรหัสผ่านเสร็จสมบูณณ์ คุณจะไม่ได้รับการแจ้งเตือนบนอุปกรณ์อื่น ๆ จนกว่าคุณจะกลับเข้าสู่ระบบในอุปกรณ์เหล่านั้น", + "Sun": "อา.", + "Mon": "จ.", + "Tue": "อ.", + "Wed": "พ.", + "Thu": "พฤ.", + "Fri": "ศ.", + "Sat": "ส.", + "Jan": "ม.ค.", + "Feb": "ก.พ.", + "Mar": "มี.ค.", + "Apr": "เม.ย.", + "May": "พ.ค.", + "Jun": "มิ.ย.", + "Jul": "ก.ค.", + "Aug": "ส.ค.", + "Sep": "ก.ย.", + "Oct": "ต.ค.", + "Nov": "พ.ย.", + "Dec": "ธ.ค.", + "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s %(day)s %(monthName)s %(time)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "วัน%(weekDayName)sที่ %(day)s %(monthName)s %(fullYear)s เวลา %(time)s", + "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s" } From e21a8d384b5b4b9440da12766fe52473e7951216 Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Wed, 7 Jun 2017 18:36:25 +0000 Subject: [PATCH 188/275] Translated using Weblate (Thai) Currently translated at 56.0% (476 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 61 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 716cdb34e2..f7ed3aa550 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -201,7 +201,7 @@ "Hangup": "วางสาย", "Historical": "ประวัติแชทเก่า", "Homeserver is": "เซิร์ฟเวอร์บ้านคือ", - "Identity Server is": "เซิร์ฟเวอร์ยืนยันตัวตนคือ", + "Identity Server is": "เซิร์ฟเวอร์ระบุตัวตนคือ", "I have verified my email address": "ฉันยืนยันที่อยู่อีเมลแล้ว", "Import": "นำเข้า", "Incorrect username and/or password.": "ชื่อผู้ใช้และ/หรือรหัสผ่านไม่ถูกต้อง", @@ -419,6 +419,61 @@ "Nov": "พ.ย.", "Dec": "ธ.ค.", "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s %(day)s %(monthName)s %(time)s", - "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "วัน%(weekDayName)sที่ %(day)s %(monthName)s %(fullYear)s เวลา %(time)s", - "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s" + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s %(day)s %(monthName)s %(fullYear)s %(time)s", + "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", + "Set a display name:": "ตั้งชื่อที่แสดง:", + "Set a Display Name": "ตั้งชื่อที่แสดง", + "Passwords don't match.": "รหัสผ่านไม่ตรงกัน", + "Password too short (min %(MIN_PASSWORD_LENGTH)s).": "รหัสผ่านสั้นเกินไป (ขึ้นต่ำ %(MIN_PASSWORD_LENGTH)s ตัวอักษร)", + "An unknown error occurred.": "เกิดข้อผิดพลาดที่ไม่รู้จัก", + "I already have an account": "ฉันมีบัญชีอยู่แล้ว", + "An error occured: %(error_string)s": "เกิดข้อผิดพลาด: %(error_string)s", + "Topic": "หัวข้อ", + "Make Moderator": "เลื่อนขั้นเป็นผู้ช่วยดูแล", + "Make this room private": "ทำให้ห้องนี้เป็นส่วนตัว", + "Share message history with new users": "แบ่งประวัติแชทให้ผู้ใช้ใหม่", + "Encrypt room": "เข้ารหัสห้อง", + "Room": "ห้อง", + "(~%(searchCount)s results)": "(~%(searchCount)s ผลลัพธ์)", + "or": "หรือ", + "bold": "หนา", + "italic": "เอียง", + "strike": "ขีดทับ", + "underline": "ขีดเส้นใต้", + "code": "โค๊ด", + "quote": "อ้างอิง", + "were kicked %(repeats)s times": "ถูกเตะ %(repeats)s ครั้ง", + "was kicked %(repeats)s times": "ถูกเตะ %(repeats)s ครั้ง", + "were kicked": "ถูกเตะ", + "was kicked": "ถูกเตะ", + "New Password": "รหัสผ่านใหม่", + "Options": "ตัวเลือก", + "Export room keys": "ส่งออกกุณแจห้อง", + "Confirm passphrase": "ยืนยันรหัสผ่าน", + "Import room keys": "นำเข้ากุณแจห้อง", + "File to import": "ไฟล์ที่จะนำเข้า", + "Start new chat": "เริ่มแชทใหม่", + "Failed to invite": "การเชิญล้มเหลว", + "Failed to invite user": "การเชิญผู้ใช้ล้มเหลว", + "Failed to invite the following users to the %(roomName)s room:": "การเชิญผู้ใช้เหล่านี้เข้าสู่ห้อง %(roomName)s ล้มเหลว:", + "Confirm Removal": "ยืนยันการลบ", + "Unknown error": "ข้อผิดพลาดที่ไม่รู้จัก", + "Incorrect password": "รหัสผ่านไม่ถูกต้อง", + "Device name": "ชื่ออุปกรณ์", + "Device key": "Key อุปกรณ์", + "Unknown devices": "อุปกรณ์ที่ไม่รู้จัก", + "Unknown Address": "ที่อยู่ที่ไม่รู้จัก", + "Unblacklist": "ถอดบัญชีดำ", + "Blacklist": "ขึ้นบัญชีดำ", + "ex. @bob:example.com": "เช่น @bob:example.com", + "Add User": "เพิ่มผู้ใช้", + "This Home Server would like to make sure you are not a robot": "เซิร์ฟเวอร์บ้านต้องการยืนยันว่าคุณไม่ใช่หุ่นยนต์", + "Sign in with CAS": "เข้าสู่ระบบด้วย CAS", + "You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "คุณสามารถกำหนดเซิร์ฟเวอร์บ้านเองได้โดยใส่ URL ของเซิร์ฟเวอร์นั้น เพื่อเข้าสู่ระบบของเซิร์ฟเวอร์ Matrix อื่น", + "This allows you to use this app with an existing Matrix account on a different home server.": "ทั้งนี่เพื่อให้คุณสามารถใช้ Riot กับบัญชี Matrix ที่มีอยู่แล้วบนเซิร์ฟเวอร์บ้านอื่น ๆ ได้", + "You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "คุณอาจเลือกเซิร์ฟเวอร์ระบุตัวตนเองด้วยก็ได้ แต่คุณจะไม่สามารถเชิญผู้ใช้อื่นด้วยที่อยู่อีเมล หรือรับคำเชิญจากผู้ใช้อื่นทางที่อยู่อีเมลได้", + "Default server": "เซิร์ฟเวอร์เริ่มต้น", + "Custom server": "เซิร์ฟเวอร์ที่กำหนดเอง", + "Home server URL": "URL เซิร์ฟเวอร์บ้าน", + "Identity server URL": "URL เซิร์ฟเวอร์ระบุตัวตน" } From 566fb2caebc604c90c3073a97482fa6873043e7b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Wed, 7 Jun 2017 22:41:02 +0100 Subject: [PATCH 189/275] Add some logging around switching rooms ... which I wish had been there when I was staring at a rageshake. --- src/components/structures/MatrixChat.js | 11 +++++++++++ src/components/structures/TimelinePanel.js | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index efb2b38d6e..d11e100f26 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -644,6 +644,17 @@ module.exports = React.createClass({ } } + if (roomInfo.room_alias) { + console.log( + `Switching to room alias ${roomInfo.room_alias} at event ` + + newState.initialEventId, + ); + } else { + console.log(`Switching to room id ${roomInfo.room_id} at event ` + + newState.initialEventId, + ); + } + // Wait for the first sync to complete so that if a room does have an alias, // it would have been retrieved. let waitFor = q(null); diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index f0e6810b6b..928e2405aa 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -902,6 +902,9 @@ var TimelinePanel = React.createClass({ var onError = (error) => { this.setState({timelineLoading: false}); + console.error( + `Error loading timeline panel at ${eventId}: ${error}`, + ); var msg = error.message ? error.message : JSON.stringify(error); var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); From 0f4028da07f05682950ac47489d7f5bafebc2f0f Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Jun 2017 09:44:58 +0100 Subject: [PATCH 190/275] Add more translations.. --- src/components/views/create_room/Presets.js | 7 ++++--- src/components/views/create_room/RoomAlias.js | 3 ++- src/components/views/dialogs/ChatCreateOrReuseDialog.js | 4 ++-- src/components/views/dialogs/ChatInviteDialog.js | 2 +- src/components/views/dialogs/DeactivateAccountDialog.js | 2 +- src/i18n/strings/en_EN.json | 7 +++++++ 6 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/components/views/create_room/Presets.js b/src/components/views/create_room/Presets.js index 6d40be9d32..c4d7ca0cdb 100644 --- a/src/components/views/create_room/Presets.js +++ b/src/components/views/create_room/Presets.js @@ -17,6 +17,7 @@ limitations under the License. 'use strict'; var React = require('react'); +import { _t } from '../../../languageHandler'; var Presets = { PrivateChat: "private_chat", @@ -46,9 +47,9 @@ module.exports = React.createClass({ render: function() { return ( ); } diff --git a/src/components/views/create_room/RoomAlias.js b/src/components/views/create_room/RoomAlias.js index 6d311db593..e1cb7e4094 100644 --- a/src/components/views/create_room/RoomAlias.js +++ b/src/components/views/create_room/RoomAlias.js @@ -15,6 +15,7 @@ limitations under the License. */ var React = require('react'); +import { _t } from '../../../languageHandler'; module.exports = React.createClass({ displayName: 'RoomAlias', @@ -94,7 +95,7 @@ module.exports = React.createClass({ render: function() { return ( - ); diff --git a/src/components/views/dialogs/ChatCreateOrReuseDialog.js b/src/components/views/dialogs/ChatCreateOrReuseDialog.js index 55caa52299..e83333556d 100644 --- a/src/components/views/dialogs/ChatCreateOrReuseDialog.js +++ b/src/components/views/dialogs/ChatCreateOrReuseDialog.js @@ -96,10 +96,10 @@ export default class ChatCreateOrReuseDialog extends React.Component { onFinished={() => { this.props.onFinished(false) }} - title='Create a new chat or reuse an existing one' + title={_t('Create a new chat or reuse an existing one')} >
- You already have existing direct chats with this user: + {_t("You already have existing direct chats with this user:")}
{tiles} {startNewChat} diff --git a/src/components/views/dialogs/ChatInviteDialog.js b/src/components/views/dialogs/ChatInviteDialog.js index cd294a123d..c411c42392 100644 --- a/src/components/views/dialogs/ChatInviteDialog.js +++ b/src/components/views/dialogs/ChatInviteDialog.js @@ -490,7 +490,7 @@ module.exports = React.createClass({ error =
{_t("You have entered an invalid contact. Try using their Matrix ID or email address.")}
; } else { const addressSelectorHeader =
- Searching known users + {_t("Searching known users")}
; addressSelector = ( {this.addressSelector = ref;}} diff --git a/src/components/views/dialogs/DeactivateAccountDialog.js b/src/components/views/dialogs/DeactivateAccountDialog.js index da74e6b716..e3b7cca078 100644 --- a/src/components/views/dialogs/DeactivateAccountDialog.js +++ b/src/components/views/dialogs/DeactivateAccountDialog.js @@ -86,7 +86,7 @@ export default class DeactivateAccountDialog extends React.Component { passwordBoxClass = 'error'; } - const okLabel = this.state.busy ? : 'Deactivate Account'; + const okLabel = this.state.busy ? : _t('Deactivate Account'); const okEnabled = this.state.confirmButtonEnabled && !this.state.busy; let cancelButton = null; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 56f38cc87c..36d220dca5 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -145,6 +145,7 @@ "Hide removed messages": "Hide removed messages", "Always show message timestamps": "Always show message timestamps", "Authentication": "Authentication", + "Alias (optional)": "Alias (optional)", "all room members": "all room members", "all room members, from the point they are invited": "all room members, from the point they are invited", "all room members, from the point they joined": "all room members, from the point they joined", @@ -218,11 +219,13 @@ "one": "%(count)s new message", "other": "%(count)s new messages" }, + "Create a new chat or reuse an existing one": "Create a new chat or reuse an existing one", "Create an account": "Create an account", "Create Room": "Create Room", "Cryptography": "Cryptography", "Current password": "Current password", "Curve25519 identity key": "Curve25519 identity key", + "Custom": "Custom", "Custom level": "Custom level", "/ddg is not a command": "/ddg is not a command", "Deactivate Account": "Deactivate Account", @@ -420,8 +423,10 @@ "Power level must be positive integer.": "Power level must be positive integer.", "Press": "Press", "Privacy warning": "Privacy warning", + "Private Chat": "Private Chat", "Privileged Users": "Privileged Users", "Profile": "Profile", + "Public Chat": "Public Chat", "Reason": "Reason", "Revoke Moderator": "Revoke Moderator", "Refer a friend to Riot:": "Refer a friend to Riot:", @@ -456,6 +461,7 @@ "Search": "Search", "Search failed": "Search failed", "Searches DuckDuckGo for results": "Searches DuckDuckGo for results", + "Searching known users": "Searching known users", "Send a message (unencrypted)": "Send a message (unencrypted)", "Send an encrypted message": "Send an encrypted message", "Sender device information": "Sender device information", @@ -601,6 +607,7 @@ "Who would you like to communicate with?": "Who would you like to communicate with?", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.", "Would you like to": "Would you like to", + "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", "You are already in a call.": "You are already in a call.", "You're not in any rooms yet! Press": "You're not in any rooms yet! Press", "You are trying to access %(roomName)s": "You are trying to access %(roomName)s", From bc0eb4294c7f4c45754ef02cc19d1444743653a4 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 8 Jun 2017 10:27:35 +0100 Subject: [PATCH 191/275] rename welcome page to home --- src/components/views/elements/HomeButton.js | 2 +- src/i18n/strings/en_EN.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/HomeButton.js b/src/components/views/elements/HomeButton.js index 80c64c6a60..4877f5dd43 100644 --- a/src/components/views/elements/HomeButton.js +++ b/src/components/views/elements/HomeButton.js @@ -23,7 +23,7 @@ const HomeButton = function(props) { const ActionButton = sdk.getComponent('elements.ActionButton'); return ( Date: Thu, 8 Jun 2017 09:56:30 +0000 Subject: [PATCH 192/275] Translated using Weblate (Russian) Currently translated at 100.0% (852 of 852 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 46 +++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 85b7a6a7f5..647fbfe1d5 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -92,14 +92,14 @@ "Found a bug?": "Нашли ошибку?", "had": "имеет", "Hangup": "Отключение", - "Historical": "Исторический", + "Historical": "История", "Homeserver is": "Домашний сервер является", "Identity Server is": "Регистрационный сервер", "I have verified my email address": "Я проверил мой адрес электронной почты", "Import E2E room keys": "Импортировать E2E ключ комнаты", "Invalid Email Address": "Недействительный адрес электронной почты", "invited": "invited", - "Invite new room members": "Прегласить новых учасников комнаты", + "Invite new room members": "Пригласить новых учасников в комнату", "Invites": "Приглашать", "Invites user with given id to current room": "Пригласить пользователя с данным id в текущую комнату", "is a": "является", @@ -119,13 +119,13 @@ "Logout": "Выход из системы", "Low priority": "Низкий приоритет", "made future room history visible to": "made future room history visible to", - "Manage Integrations": "Управление интеграций", + "Manage Integrations": "Управление интеграциями", "Members only": "Только участники", "Mobile phone number": "Номер мобильного телефона", "Moderator": "Ведущий", "my Matrix ID": "мой Matrix ID", "Name": "Имя", - "Never send encrypted messages to unverified devices from this device": "Никогда не отправляйте зашифрованные сообщения в непроверенные устройства с этого устройства", + "Never send encrypted messages to unverified devices from this device": "Никогда не отправлять зашифрованные сообщения на неверифицированные устроства с этого устройства", "Never send encrypted messages to unverified devices in this room from this device": "Никогда не отправляйте зашифрованные сообщения в непроверенные устройства в этой комнате из этого устройства", "New password": "Новый пароль", "New passwords must match each other.": "Новые пароли должны соответствовать друг другу.", @@ -190,7 +190,7 @@ "Voice call": "Голосовой вызов", "VoIP conference finished.": "VoIP конференция закончилась.", "VoIP conference started.": "VoIP Конференция стартовала.", - "(warning: cannot be disabled again!)": "(предупреждение: не может быть снова отключен!)", + "(warning: cannot be disabled again!)": "(предупреждение: не может быть отключено!)", "Warning!": "Предупреждение!", "was banned": "запрещен", "was invited": "приглашенный", @@ -200,7 +200,7 @@ "were": "быть", "Who can access this room?": "Кто может получить доступ к этой комнате?", "Who can read history?": "Кто может читать историю?", - "Who would you like to add to this room?": "Кого хотели бы Вы добавлять к этой комнате?", + "Who would you like to add to this room?": "Кого бы вы хотели пригласить в эту комнату?", "Who would you like to communicate with?": "С кем хотели бы Вы связываться?", "withdrawn": "уходить", "Would you like to": "Хотели бы Вы", @@ -658,7 +658,7 @@ "powered by Matrix": "управляемый с Matrix", "Add a topic": "Добавить тему", "Show timestamps in 12 hour format (e.g. 2:30pm)": "Времея отображать в 12 часовом формате (напр. 2:30pm)", - "Use compact timeline layout": "Используйте компактным указанием времени", + "Use compact timeline layout": "Компактное отображение", "Hide removed messages": "Скрыть удаленное сообщение", "No Microphones detected": "Микрофоны не обнаружены", "Unknown devices": "Незнакомое устройство", @@ -864,5 +864,35 @@ "Disable URL previews for this room (affects only you)": "Отключить предпросмотр URL в этой комнате (только для вас)", "$senderDisplayName changed the room avatar to ": "$senderDisplayName сменил аватар комнаты на ", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s удалил аватар комнаты.", - "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s сменил аватар для %(roomName)s" + "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s сменил аватар для %(roomName)s", + "Create new room": "Создать комнату", + "Room directory": "Каталог комнат", + "Start chat": "Начать чат", + "Welcome page": "Домашняя страница", + "Add": "Добавить", + "%(count)s new messages.one": "%(count)s новое сообщение", + "%(count)s new messages.other": "%(count)s новых сообщений", + "Error: Problem communicating with the given homeserver.": "Ошибка: проблема коммуникаций с указанным Home Server'ом.", + "Failed to fetch avatar URL": "Ошибка получения аватара", + "The phone number entered looks invalid": "Введенный номер телефона выглядит неправильным", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Ошибка загрузки истории комнаты: недостаточно прав.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Ошибка загрузки истории комнаты: запрошенный элемент не найден.", + "Uploading %(filename)s and %(count)s others.zero": "Загрузка %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "Загрузка %(filename)s и %(count)s другой файл", + "Uploading %(filename)s and %(count)s others.other": "Загрузка %(filename)s и %(count)s других файлов", + "Username invalid: %(errMessage)s": "Неверное имя пользователя: %(errMessage)s", + "Searching known users": "Искать известных пользователей", + "You must register to use this functionality": "Вы должны зарегистрироваться для использования этой функции", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Отослать снова или отменить отправку. Вы также можете выбрать на отправку или отмену отдельные сообщения.", + "New Password": "Новый пароль", + "Start chatting": "Начать общение", + "Start Chatting": "Начать общение", + "Click on the button below to start chatting!": "Нажмите на кнопку ниже для того, чтобы начать общение!", + "Create a new chat or reuse an existing one": "Создать новый чат или использовать уже существующий", + "You already have existing direct chats with this user:": "У вас уже есть существующие приватные чаты с этим пользователем:", + "Username available": "Имя пользователя доступно", + "Username not available": "Имя пользователя недоступно", + "Something went wrong!": "Что-то пошло не так!", + "This will be your account name on the homeserver, or you can pick a different server.": "Это будет ваше имя пользователя на , или вы можете выбрать другой сервер.", + "If you already have a Matrix account you can log in instead.": "Если вы уже имеете учетную запись Matrix, то вы можете войти." } From 96e471adc6ae522b58442bbe6307de7b1bff3ce3 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Wed, 7 Jun 2017 22:03:11 +0000 Subject: [PATCH 193/275] Translated using Weblate (German) Currently translated at 99.7% (850 of 852 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index ee8478c0c8..2845a5021c 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -127,7 +127,7 @@ "Found a bug?": "Fehler gefunden?", "Guests cannot join this room even if explicitly invited.": "Gäste können diesem Raum nicht beitreten, auch wenn sie explizit eingeladen wurden.", "Guests can't set avatars. Please register.": "Gäste können kein Profilbild setzen. Bitte registrieren.", - "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte registrieren um hochzuladen.", + "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte zunächst registrieren.", "had": "hatte", "Hangup": "Auflegen", "Homeserver is": "Der Homeserver ist", @@ -227,7 +227,7 @@ "to join the discussion": "um an der Diskussion teilzunehmen", "To kick users": "Um Nutzer zu entfernen", "Admin": "Administrator", - "Server may be unavailable, overloaded, or you hit a bug.": "Server könnte nicht verfügbar oder überlastet sein oder du bist auf einen Fehler gestoßen.", + "Server may be unavailable, overloaded, or you hit a bug.": "Server ist nicht verfügbar, überlastet oder du bist auf einen Fehler gestoßen.", "Could not connect to the integration server": "Konnte keine Verbindung zum Integrations-Server herstellen", "Disable inline URL previews by default": "URL-Vorschau im Chat standardmäßig deaktivieren", "Guests can't use labs features. Please register.": "Gäste können keine Labor-Funktionen nutzen. Bitte registrieren.", @@ -281,14 +281,14 @@ "Bulk Options": "Bulk-Optionen", "Call Timeout": "Anruf-Timeout", "Conference call failed.": "Konferenzgespräch fehlgeschlagen.", - "Conference calling is in development and may not be reliable.": "Konferenzgespräche sind in Entwicklung und evtl. nicht zuverlässig.", + "Conference calling is in development and may not be reliable.": "Konferenzgespräche befinden sich noch in der Entwicklungsphase und sind möglicherweise nicht zuverlässig nutzbar.", "Conference calls are not supported in encrypted rooms": "Konferenzgespräche werden in verschlüsselten Räumen nicht unterstützt", "Conference calls are not supported in this client": "Konferenzgespräche werden von diesem Client nicht unterstützt", "Existing Call": "Bereits bestehender Anruf", "Failed to set up conference call": "Konferenzgespräch konnte nicht gestartet werden", "Failed to verify email address: make sure you clicked the link in the email": "Verifizierung der E-Mail-Adresse fehlgeschlagen: Bitte stelle sicher, dass du den Link in der E-Mail angeklickt hast", "Failure to create room": "Raumerstellung fehlgeschlagen", - "Guest users can't create new rooms. Please register to create room and start a chat.": "Gäste können keine neuen Räume erstellen. Bitte registrieren um einen Raum zu erstellen und einen Chat zu starten.", + "Guest users can't create new rooms. Please register to create room and start a chat.": "Gastnutzer können keine neuen Räume erstellen. Bitte registriere dich um Räume zu erstellen und Chats zu starten.", "Riot does not have permission to send you notifications - please check your browser settings": "Riot hat keine Berechtigung Benachrichtigungen zu senden - bitte prüfe deine Browser-Einstellungen", "Riot was not given permission to send notifications - please try again": "Riot hat das Recht nicht bekommen Benachrichtigungen zu senden. Bitte erneut probieren", "This email address is already in use": "Diese E-Mail-Adresse wird bereits verwendet", @@ -302,11 +302,11 @@ "Unable to enable Notifications": "Benachrichtigungen konnten nicht aktiviert werden", "Upload Failed": "Upload fehlgeschlagen", "VoIP is unsupported": "VoIP wird nicht unterstützt", - "You are already in a call.": "Du bist bereits bei einem Anruf.", + "You are already in a call.": "Du bist bereits in einem Gespräch.", "You cannot place a call with yourself.": "Du kannst keinen Anruf mit dir selbst starten.", - "You cannot place VoIP calls in this browser.": "Du kannst kein VoIP-Gespräch in diesem Browser starten.", + "You cannot place VoIP calls in this browser.": "Du kannst keine VoIP-Gespräche in diesem Browser starten.", "You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver. This is a once off; sorry for the inconvenience.": "Du musst dich erneut anmelden, um Ende-zu-Ende-Verschlüsselungs-Schlüssel für dieses Gerät zu generieren und um den öffentlichen Schlüssel auf deinem Homeserver zu hinterlegen. Dies muss nur einmal durchgeführt werden, bitte entschuldige die Unannehmlichkeiten.", - "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Homeserver verknüpft zu sein.", + "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Heimserver verbunden zu sein.", "Sun": "So", "Mon": "Mo", "Tue": "Di", @@ -581,7 +581,6 @@ "Failed to save settings": "Einstellungen konnten nicht gespeichert werden", "Failed to set display name": "Anzeigename konnte nicht gesetzt werden", "Fill screen": "Fülle Bildschirm", - "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte zunächst registrieren.", "Hide Text Formatting Toolbar": "Verberge Text-Formatierungs-Toolbar", "Incorrect verification code": "Falscher Verifizierungscode", "Invalid alias format": "Ungültiges Alias-Format", @@ -608,8 +607,8 @@ "Server error": "Server-Fehler", "Server may be unavailable, overloaded, or search timed out :(": "Der Server ist entweder nicht verfügbar, überlastet oder die Suche wurde wegen Zeitüberschreitung abgebrochen :(", "Server may be unavailable, overloaded, or the file too big": "Server ist entweder nicht verfügbar, überlastet oder die Datei ist zu groß", - "Server unavailable, overloaded, or something else went wrong.": "Der Server ist entweder nicht verfügbar, überlastet oder es liegt ein anderweitiger Fehler vor.", - "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden noch nicht gesendet.", + "Server unavailable, overloaded, or something else went wrong.": "Server nicht verfügbar, überlastet oder etwas anderes lief falsch.", + "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", "Submit": "Absenden", "The main address for this room is: %(canonical_alias_section)s": "Die Hauptadresse für diesen Raum ist: %(canonical_alias_section)s", "This action cannot be performed by a guest user. Please register to be able to do this": "Diese Aktion kann nicht von einem Gast ausgeführt werden. Bitte registriere dich um dies zu tun", @@ -726,7 +725,7 @@ "Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Eine Änderung des Passworts setzt derzeit alle Schlüssel für die E2E-Verschlüsselung auf allen verwendeten Geräten zurück. Bereits verschlüsselte Chat-Inhalte sind somit nur noch lesbar, wenn du zunächst alle Schlüssel exportierst und später wieder importierst. Wir arbeiten an einer Verbesserung dieser momentan noch notwendigen Vorgehensweise.", "Unmute": "Stummschalten aufheben", "Invalid file%(extra)s": "Ungültige Datei%(extra)s", - "Remove %(threePid)s?": "Entferne %(threePid)s?", + "Remove %(threePid)s?": "%(threePid)s entfernen?", "Please select the destination room for this message": "Bitte den Raum auswählen, an den diese Nachricht gesendet werden soll", "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s hat den Raum-Namen gelöscht.", "Passphrases must match": "Passphrase muss übereinstimmen", @@ -736,7 +735,6 @@ "Confirm passphrase": "Bestätige Passphrase", "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Die Export-Datei wird mit einer Passphrase geschützt sein. Du solltest die Passphrase hier eingeben um die Datei zu entschlüsseln.", "You must join the room to see its files": "Du musst dem Raum beitreten, um die Raum-Dateien sehen zu können", - "Server may be unavailable, overloaded, or you hit a bug.": "Server ist nicht verfügbar, überlastet oder du bist auf einen Fehler gestoßen.", "Reject all %(invitedRooms)s invites": "Alle %(invitedRooms)s Einladungen ablehnen", "Start new Chat": "Starte neuen Chat", "Guest users can't invite users. Please register.": "Gäste können keine Nutzer einladen. Bitte registrieren.", @@ -841,17 +839,13 @@ "Default Device": "Standard-Gerät", "Microphone": "Mikrofon", "Camera": "Kamera", - "Conference call failed.": "Konferenzgespräch fehlgeschlagen.", - "Conference calling is in development and may not be reliable.": "Konferenzgespräche befinden sich noch in der Entwicklungsphase und sind möglicherweise nicht zuverlässig nutzbar.", "Device already verified!": "Gerät bereits verifiziert!", "Export": "Export", "Failed to register as guest:": "Registrieren als Gast schlug fehl:", "Guest access is disabled on this Home Server.": "Gastzugang ist auf diesem Heimserver deaktivert.", - "Guest users can't create new rooms. Please register to create room and start a chat.": "Gastnutzer können keine neuen Räume erstellen. Bitte registriere dich um Räume zu erstellen und Chats zu starten.", "Import": "Import", "Incorrect username and/or password.": "Inkorrekter Nutzername und/oder Passwort.", "Results from DuckDuckGo": "Ergebnisse von DuckDuckGo", - "Server unavailable, overloaded, or something else went wrong.": "Server nicht verfügbar, überlastet oder etwas anderes lief falsch.", "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "Den Signaturschlüssel den du bereitstellst stimmt mit dem Schlüssel den du von %(userId)s's Gerät %(deviceId)s empfangen hast überein. Gerät als verifiziert markiert.", "Add a topic": "Thema hinzufügen", "Anyone": "Jeder", @@ -879,13 +873,9 @@ "Verified key": "Verifizierter Schlüssel", "WARNING: Device already verified, but keys do NOT MATCH!": "WARNUNG: Gerät bereits verifiziert, aber Schlüssel sind NICHT GLEICH!", "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "WARNUNG: SCHLÜSSEL-VERIFIZIERUNG FEHLGESCHLAGEN! Der Signatur-Schlüssel für %(userId)s und Gerät %(deviceId)s ist \"%(fprint)s\" welche nicht dem bereitgestellten Schlüssel \"%(fingerprint)s\" übereinstimmen. Dies kann bedeuten, dass deine Kommunikation abgefangen wird!", - "You are already in a call.": "Du bist bereits in einem Gespräch.", - "You cannot place a call with yourself.": "Du kannst keinen Anruf mit dir selbst starten.", - "You cannot place VoIP calls in this browser.": "Du kannst keine VoIP-Gespräche in diesem Browser starten.", "You have disabled URL previews by default.": "Du hast die URL-Vorschau standardmäßig deaktiviert.", "You have enabled URL previews by default.": "Du hast die URL-Vorschau standardmäßig aktiviert.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Du hast einen ungültigen Kontakt eingegeben. Versuche es mit der Matrix-ID oder der E-Mail-Adresse.", - "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Heimserver verbunden zu sein.", "$senderDisplayName changed the room avatar to ": "$senderDisplayName hat das Raum-Bild geändert zu ", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s hat das Raum-Bild für %(roomName)s geändert", "Hide removed messages": "Gelöschte Nachrichten verbergen", @@ -896,7 +886,6 @@ "%(count)s new messages.other": "%(count)s neue Nachrichten", "Error: Problem communicating with the given homeserver.": "Fehler: Problem beim kommunizieren mit dem angegebenen Heimserver.", "Failed to fetch avatar URL": "Fehler beim holen der Avatar-URL", - "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", "The phone number entered looks invalid": "Die Telefonnummer, die eingegeben wurde, sieht ungültig aus", "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht betretbar. Du kannst evtl. beitreten wenn du dich registrierst.", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber du hast keine Berechtigung diese Nachricht zu sehen.", From db647fa6678128d11ea7e5cf81d3c061dba8302e Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Wed, 7 Jun 2017 22:05:27 +0000 Subject: [PATCH 194/275] Translated using Weblate (Thai) Currently translated at 56.2% (479 of 852 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 877a177c17..f97b6b8d50 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -229,7 +229,7 @@ "Leave room": "ออกจากห้อง", "left and rejoined": "ออกแล้วกลับเข้าร่วมอีกครั้ง", "left": "ออกไปแล้ว", - "%(targetName)s left the room.": "%(targetName)s ออกจากห้องไปแล้ว", + "%(targetName)s left the room.": "%(targetName)s ออกจากห้องแล้ว", "List this room in %(domain)s's room directory?": "แสดงห้องนี้ในไดเรกทอรีห้องของ %(domain)s?", "Logged in as:": "เข้าสู่ระบบในชื่อ:", "Login as guest": "เข้าสู่ระบบในฐานะแขก", @@ -474,5 +474,9 @@ "Default server": "เซิร์ฟเวอร์เริ่มต้น", "Custom server": "เซิร์ฟเวอร์ที่กำหนดเอง", "Home server URL": "URL เซิร์ฟเวอร์บ้าน", - "Identity server URL": "URL เซิร์ฟเวอร์ระบุตัวตน" + "Identity server URL": "URL เซิร์ฟเวอร์ระบุตัวตน", + "%(severalUsers)sleft %(repeats)s times": "%(targetName)sออกจากห้อง %(repeats)s ครั้ง", + "%(oneUser)sleft %(repeats)s times": "%(oneUser)sออกจากห้อง %(repeats)s ครั้ง", + "%(severalUsers)sleft": "%(severalUsers)sออกจากห้องแล้ว", + "%(oneUser)sleft": "%(oneUser)sออกจากห้องแล้ว" } From 2bed5bae174eeb045f81f12f3616c9b5cac23f4f Mon Sep 17 00:00:00 2001 From: Bamstam Date: Wed, 7 Jun 2017 22:03:11 +0000 Subject: [PATCH 195/275] Translated using Weblate (German) Currently translated at 99.7% (851 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 2845a5021c..7013ccabb6 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -909,5 +909,6 @@ "Username not available": "Nutzername nicht verfügbar", "Something went wrong!": "Etwas ging schief!", "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", - "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden." + "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", + "Home": "Start" } From 5686eb75d46eb7629ad8f4083d21470dfe91c35d Mon Sep 17 00:00:00 2001 From: Bamstam Date: Wed, 7 Jun 2017 22:03:11 +0000 Subject: [PATCH 196/275] Translated using Weblate (German) Currently translated at 99.7% (851 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 7013ccabb6..b81b3ef1e4 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -910,5 +910,6 @@ "Something went wrong!": "Etwas ging schief!", "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", - "Home": "Start" + "Home": "Start", + "Username invalid: %(errMessage)s": "Nutzername falsch:" } From 811901097d77ff50d75b4427cc7d6fd5a1249b09 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Wed, 7 Jun 2017 22:03:11 +0000 Subject: [PATCH 197/275] Translated using Weblate (German) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index b81b3ef1e4..4102d7be56 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -911,5 +911,5 @@ "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", "Home": "Start", - "Username invalid: %(errMessage)s": "Nutzername falsch:" + "Username invalid: %(errMessage)s": "Nutzername falsch: %(errMessage)s" } From ec9a436625d70e4af616a4fadb19d16d9577bdef Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 11:56:48 +0100 Subject: [PATCH 198/275] Formatting --- src/Login.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Login.js b/src/Login.js index 87731744e9..659fdb92bb 100644 --- a/src/Login.js +++ b/src/Login.js @@ -161,8 +161,7 @@ export default class Login { error.friendlyText = ( _t('This Home Server does not support login using email address.') ); - } - else if (error.httpStatus === 403) { + } else if (error.httpStatus === 403) { error.friendlyText = ( _t('Incorrect username and/or password.') ); @@ -185,8 +184,7 @@ export default class Login { throw error; }); } - } - else { + } else { error.friendlyText = ( _t("There was a problem logging in.") + ' (HTTP ' + error.httpStatus + ")" ); From c9f723b16052d2e215ba716ab23196dbd7c9ae70 Mon Sep 17 00:00:00 2001 From: RiotTranslate Date: Thu, 8 Jun 2017 13:05:02 +0200 Subject: [PATCH 199/275] Update from Weblate. (#1053) * Added translation using Weblate (Thai) * Translated using Weblate (Thai) Currently translated at 2.6% (22 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (Thai) Currently translated at 8.9% (74 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.8% (826 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Swedish) Currently translated at 35.4% (293 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/sv/ * Translated using Weblate (Thai) Currently translated at 9.7% (81 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 100.0% (827 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Russian) Currently translated at 76.9% (636 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (Hungarian) Currently translated at 0.1% (1 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/hu/ * Translated using Weblate (Thai) Currently translated at 39.2% (325 of 827 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.8% (827 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (German) Currently translated at 99.8% (827 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Thai) Currently translated at 39.7% (329 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.8% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Hungarian) Currently translated at 3.1% (26 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/hu/ * Translated using Weblate (Russian) Currently translated at 77.4% (641 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (Thai) Currently translated at 39.7% (329 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (Russian) Currently translated at 100.0% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (German) Currently translated at 100.0% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Russian) Currently translated at 100.0% (828 of 828 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (French) Currently translated at 96.5% (821 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ * Translated using Weblate (Thai) Currently translated at 39.0% (332 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (French) Currently translated at 97.0% (825 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ * Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Thai) Currently translated at 40.8% (347 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (French) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ * Translated using Weblate (German) Currently translated at 100.0% (850 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Thai) Currently translated at 49.5% (421 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (Thai) Currently translated at 56.0% (476 of 850 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (Russian) Currently translated at 100.0% (852 of 852 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (German) Currently translated at 99.7% (850 of 852 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Thai) Currently translated at 56.2% (479 of 852 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ * Translated using Weblate (German) Currently translated at 99.7% (851 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (German) Currently translated at 99.7% (851 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (German) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 62 +++++++------- src/i18n/strings/fr.json | 31 ++++++- src/i18n/strings/ru.json | 46 +++++++++-- src/i18n/strings/th.json | 156 +++++++++++++++++++++++++++++++++++- 4 files changed, 247 insertions(+), 48 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index f7b3d16ebc..4102d7be56 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -114,7 +114,7 @@ "Failed to change password. Is your password correct?": "Passwortänderung fehlgeschlagen. Ist dein Passwort richtig?", "Failed to forget room": "Vergessen des Raums schlug fehl", "Failed to leave room": "Verlassen des Raums fehlgeschlagen", - "Failed to reject invitation": "Fehler beim Abweisen der Einladung", + "Failed to reject invitation": "Einladung konnte nicht abgelehnt werden", "Failed to set avatar.": "Fehler beim Setzen des Profilbilds.", "Failed to unban": "Entbannen fehlgeschlagen", "Failed to upload file": "Datei-Upload fehlgeschlagen", @@ -127,7 +127,7 @@ "Found a bug?": "Fehler gefunden?", "Guests cannot join this room even if explicitly invited.": "Gäste können diesem Raum nicht beitreten, auch wenn sie explizit eingeladen wurden.", "Guests can't set avatars. Please register.": "Gäste können kein Profilbild setzen. Bitte registrieren.", - "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte registrieren um hochzuladen.", + "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte zunächst registrieren.", "had": "hatte", "Hangup": "Auflegen", "Homeserver is": "Der Homeserver ist", @@ -182,7 +182,7 @@ "Once you've followed the link it contains, click below": "Nachdem du dem darin enthaltenen Link gefolgt bist, klicke unten", "rejected the invitation.": "lehnte die Einladung ab.", "Reject invitation": "Einladung ablehnen", - "Remove Contact Information?": "Kontakt-Informationen löschen?", + "Remove Contact Information?": "Kontakt-Informationen entfernen?", "removed their display name": "löschte den eigenen Anzeigenamen", "Remove": "Entfernen", "requested a VoIP conference": "hat eine VoIP-Konferenz angefordert", @@ -227,7 +227,7 @@ "to join the discussion": "um an der Diskussion teilzunehmen", "To kick users": "Um Nutzer zu entfernen", "Admin": "Administrator", - "Server may be unavailable, overloaded, or you hit a bug.": "Server könnte nicht verfügbar oder überlastet sein oder du bist auf einen Fehler gestoßen.", + "Server may be unavailable, overloaded, or you hit a bug.": "Server ist nicht verfügbar, überlastet oder du bist auf einen Fehler gestoßen.", "Could not connect to the integration server": "Konnte keine Verbindung zum Integrations-Server herstellen", "Disable inline URL previews by default": "URL-Vorschau im Chat standardmäßig deaktivieren", "Guests can't use labs features. Please register.": "Gäste können keine Labor-Funktionen nutzen. Bitte registrieren.", @@ -271,7 +271,7 @@ "Who would you like to communicate with?": "Mit wem möchtest du kommunizieren?", "Would you like to": "Möchtest du", "You do not have permission to post to this room": "Du hast keine Berechtigung an diesen Raum etwas zu senden", - "You have been invited to join this room by %(inviterName)s": "Du wurdest von %(inviterName)s in diesen Raum eingeladen", + "You have been invited to join this room by %(inviterName)s": "%(inviterName)s hat dich in diesen Raum eingeladen", "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Du wurdest auf allen Geräten abgemeldet und wirst keine Push-Benachrichtigungen mehr erhalten. Um die Benachrichtigungen zu reaktivieren, musst du dich auf jedem Gerät neu anmelden", "you must be a": "nötige Rolle", "Your password has been reset": "Dein Passwort wurde zurückgesetzt", @@ -281,14 +281,14 @@ "Bulk Options": "Bulk-Optionen", "Call Timeout": "Anruf-Timeout", "Conference call failed.": "Konferenzgespräch fehlgeschlagen.", - "Conference calling is in development and may not be reliable.": "Konferenzgespräche sind in Entwicklung und evtl. nicht zuverlässig.", + "Conference calling is in development and may not be reliable.": "Konferenzgespräche befinden sich noch in der Entwicklungsphase und sind möglicherweise nicht zuverlässig nutzbar.", "Conference calls are not supported in encrypted rooms": "Konferenzgespräche werden in verschlüsselten Räumen nicht unterstützt", "Conference calls are not supported in this client": "Konferenzgespräche werden von diesem Client nicht unterstützt", "Existing Call": "Bereits bestehender Anruf", "Failed to set up conference call": "Konferenzgespräch konnte nicht gestartet werden", "Failed to verify email address: make sure you clicked the link in the email": "Verifizierung der E-Mail-Adresse fehlgeschlagen: Bitte stelle sicher, dass du den Link in der E-Mail angeklickt hast", "Failure to create room": "Raumerstellung fehlgeschlagen", - "Guest users can't create new rooms. Please register to create room and start a chat.": "Gäste können keine neuen Räume erstellen. Bitte registrieren um einen Raum zu erstellen und einen Chat zu starten.", + "Guest users can't create new rooms. Please register to create room and start a chat.": "Gastnutzer können keine neuen Räume erstellen. Bitte registriere dich um Räume zu erstellen und Chats zu starten.", "Riot does not have permission to send you notifications - please check your browser settings": "Riot hat keine Berechtigung Benachrichtigungen zu senden - bitte prüfe deine Browser-Einstellungen", "Riot was not given permission to send notifications - please try again": "Riot hat das Recht nicht bekommen Benachrichtigungen zu senden. Bitte erneut probieren", "This email address is already in use": "Diese E-Mail-Adresse wird bereits verwendet", @@ -302,11 +302,11 @@ "Unable to enable Notifications": "Benachrichtigungen konnten nicht aktiviert werden", "Upload Failed": "Upload fehlgeschlagen", "VoIP is unsupported": "VoIP wird nicht unterstützt", - "You are already in a call.": "Du bist bereits bei einem Anruf.", + "You are already in a call.": "Du bist bereits in einem Gespräch.", "You cannot place a call with yourself.": "Du kannst keinen Anruf mit dir selbst starten.", - "You cannot place VoIP calls in this browser.": "Du kannst kein VoIP-Gespräch in diesem Browser starten.", + "You cannot place VoIP calls in this browser.": "Du kannst keine VoIP-Gespräche in diesem Browser starten.", "You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver. This is a once off; sorry for the inconvenience.": "Du musst dich erneut anmelden, um Ende-zu-Ende-Verschlüsselungs-Schlüssel für dieses Gerät zu generieren und um den öffentlichen Schlüssel auf deinem Homeserver zu hinterlegen. Dies muss nur einmal durchgeführt werden, bitte entschuldige die Unannehmlichkeiten.", - "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Homeserver verknüpft zu sein.", + "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Heimserver verbunden zu sein.", "Sun": "So", "Mon": "Mo", "Tue": "Di", @@ -377,7 +377,7 @@ "Power level must be positive integer.": "Berechtigungslevel muss eine positive ganze Zahl sein.", "Reason": "Grund", "%(targetName)s rejected the invitation.": "%(targetName)s hat die Einladung abgelehnt.", - "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s löschte den Anzeigenamen (%(oldDisplayName)s).", + "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s hat den Anzeigenamen entfernt (%(oldDisplayName)s).", "%(senderName)s removed their profile picture.": "%(senderName)s hat das Profilbild gelöscht.", "%(senderName)s requested a VoIP conference.": "%(senderName)s möchte eine VoIP-Konferenz beginnen.", "Room %(roomId)s not visible": "Raum %(roomId)s ist nicht sichtbar", @@ -418,7 +418,7 @@ "Press": "Drücke", "tag as %(tagName)s": "als %(tagName)s taggen", "to browse the directory": "um das Raum-Verzeichnis zu durchsuchen", - "to demote": "um die Priorität herabzusetzen", + "to demote": "um das Berechtigungslevel herabzusetzen", "to favourite": "zum Favorisieren", "to make a room or": "um einen Raum zu erstellen, oder", "to restore": "zum wiederherstellen", @@ -581,7 +581,6 @@ "Failed to save settings": "Einstellungen konnten nicht gespeichert werden", "Failed to set display name": "Anzeigename konnte nicht gesetzt werden", "Fill screen": "Fülle Bildschirm", - "Guest users can't upload files. Please register to upload.": "Gäste können keine Dateien hochladen. Bitte zunächst registrieren.", "Hide Text Formatting Toolbar": "Verberge Text-Formatierungs-Toolbar", "Incorrect verification code": "Falscher Verifizierungscode", "Invalid alias format": "Ungültiges Alias-Format", @@ -608,16 +607,17 @@ "Server error": "Server-Fehler", "Server may be unavailable, overloaded, or search timed out :(": "Der Server ist entweder nicht verfügbar, überlastet oder die Suche wurde wegen Zeitüberschreitung abgebrochen :(", "Server may be unavailable, overloaded, or the file too big": "Server ist entweder nicht verfügbar, überlastet oder die Datei ist zu groß", - "Server unavailable, overloaded, or something else went wrong.": "Der Server ist entweder nicht verfügbar, überlastet oder es liegt ein anderweitiger Fehler vor.", - "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden noch nicht gesendet.", + "Server unavailable, overloaded, or something else went wrong.": "Server nicht verfügbar, überlastet oder etwas anderes lief falsch.", + "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", "Submit": "Absenden", "The main address for this room is: %(canonical_alias_section)s": "Die Hauptadresse für diesen Raum ist: %(canonical_alias_section)s", "This action cannot be performed by a guest user. Please register to be able to do this": "Diese Aktion kann nicht von einem Gast ausgeführt werden. Bitte registriere dich um dies zu tun", "%(actionVerb)s this person?": "Diese Person %(actionVerb)s?", "This room has no local addresses": "Dieser Raum hat keine lokale Adresse", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen.", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden.", - "Turn Markdown off": "Markdown abschalten", + "This room is private or inaccessible to guests. You may be able to join if you register": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen", + "Tried to load a specific point in this room's timeline, but was unable to find it": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden", + "Turn Markdown off": "Markdown deaktiveren", "Turn Markdown on": "Markdown einschalten", "Unable to load device list": "Geräteliste konnte nicht geladen werden", "Unknown command": "Unbekannter Befehl", @@ -725,7 +725,7 @@ "Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Eine Änderung des Passworts setzt derzeit alle Schlüssel für die E2E-Verschlüsselung auf allen verwendeten Geräten zurück. Bereits verschlüsselte Chat-Inhalte sind somit nur noch lesbar, wenn du zunächst alle Schlüssel exportierst und später wieder importierst. Wir arbeiten an einer Verbesserung dieser momentan noch notwendigen Vorgehensweise.", "Unmute": "Stummschalten aufheben", "Invalid file%(extra)s": "Ungültige Datei%(extra)s", - "Remove %(threePid)s?": "Entferne %(threePid)s?", + "Remove %(threePid)s?": "%(threePid)s entfernen?", "Please select the destination room for this message": "Bitte den Raum auswählen, an den diese Nachricht gesendet werden soll", "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s hat den Raum-Namen gelöscht.", "Passphrases must match": "Passphrase muss übereinstimmen", @@ -735,7 +735,6 @@ "Confirm passphrase": "Bestätige Passphrase", "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Die Export-Datei wird mit einer Passphrase geschützt sein. Du solltest die Passphrase hier eingeben um die Datei zu entschlüsseln.", "You must join the room to see its files": "Du musst dem Raum beitreten, um die Raum-Dateien sehen zu können", - "Server may be unavailable, overloaded, or you hit a bug.": "Server ist nicht verfügbar, überlastet oder du bist auf einen Fehler gestoßen.", "Reject all %(invitedRooms)s invites": "Alle %(invitedRooms)s Einladungen ablehnen", "Start new Chat": "Starte neuen Chat", "Guest users can't invite users. Please register.": "Gäste können keine Nutzer einladen. Bitte registrieren.", @@ -785,7 +784,7 @@ "This image cannot be displayed.": "Dieses Bild kann nicht angezeigt werden.", "Error decrypting video": "Video-Entschlüsselung fehlgeschlagen", "Import room keys": "Importiere Raum-Schlüssel", - "File to import": "Datei zum Importieren", + "File to import": "Zu importierende Datei", "Failed to invite the following users to the %(roomName)s room:": "Das Einladen der folgenden Nutzer in den Raum \"%(roomName)s\" ist fehlgeschlagen:", "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Bist du sicher, dass du dieses Ereignis entfernen (löschen) möchtest? Wenn du die Änderung eines Raum-Namens oder eines Raum-Themas löscht, kann dies dazu führen, dass die ursprüngliche Änderung rückgängig gemacht wird.", "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Dieser Prozess erlaubt es dir, die Schlüssel für in verschlüsselten Räumen empfangene Nachrichten in eine lokale Datei zu exportieren. In Zukunft wird es möglich sein, diese Datei in einen anderen Matrix-Client zu importieren, sodass dieser Client ebenfalls diese Nachrichten entschlüsseln kann.", @@ -827,7 +826,7 @@ "Invited": "Eingeladen", "Set a Display Name": "Setze einen Anzeigenamen", "for %(amount)ss": "für %(amount)ss", - "for %(amount)sm": "für %(amount)sm", + "for %(amount)sm": "seit %(amount)smin", "for %(amount)sh": "für %(amount)sh", "for %(amount)sd": "für %(amount)sd", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s hat das Raum-Bild entfernt.", @@ -840,17 +839,13 @@ "Default Device": "Standard-Gerät", "Microphone": "Mikrofon", "Camera": "Kamera", - "Conference call failed.": "Konferenzgespräch fehlgeschlagen.", - "Conference calling is in development and may not be reliable.": "Konferenzgespräche befinden sich noch in der Entwicklungsphase und sind möglicherweise nicht zuverlässig nutzbar.", "Device already verified!": "Gerät bereits verifiziert!", "Export": "Export", "Failed to register as guest:": "Registrieren als Gast schlug fehl:", "Guest access is disabled on this Home Server.": "Gastzugang ist auf diesem Heimserver deaktivert.", - "Guest users can't create new rooms. Please register to create room and start a chat.": "Gastnutzer können keine neuen Räume erstellen. Bitte registriere dich um Räume zu erstellen und Chats zu starten.", "Import": "Import", "Incorrect username and/or password.": "Inkorrekter Nutzername und/oder Passwort.", "Results from DuckDuckGo": "Ergebnisse von DuckDuckGo", - "Server unavailable, overloaded, or something else went wrong.": "Server nicht verfügbar, überlastet oder etwas anderes lief falsch.", "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "Den Signaturschlüssel den du bereitstellst stimmt mit dem Schlüssel den du von %(userId)s's Gerät %(deviceId)s empfangen hast überein. Gerät als verifiziert markiert.", "Add a topic": "Thema hinzufügen", "Anyone": "Jeder", @@ -878,13 +873,9 @@ "Verified key": "Verifizierter Schlüssel", "WARNING: Device already verified, but keys do NOT MATCH!": "WARNUNG: Gerät bereits verifiziert, aber Schlüssel sind NICHT GLEICH!", "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "WARNUNG: SCHLÜSSEL-VERIFIZIERUNG FEHLGESCHLAGEN! Der Signatur-Schlüssel für %(userId)s und Gerät %(deviceId)s ist \"%(fprint)s\" welche nicht dem bereitgestellten Schlüssel \"%(fingerprint)s\" übereinstimmen. Dies kann bedeuten, dass deine Kommunikation abgefangen wird!", - "You are already in a call.": "Du bist bereits in einem Gespräch.", - "You cannot place a call with yourself.": "Du kannst keinen Anruf mit dir selbst starten.", - "You cannot place VoIP calls in this browser.": "Du kannst keine VoIP-Gespräche in diesem Browser starten.", "You have disabled URL previews by default.": "Du hast die URL-Vorschau standardmäßig deaktiviert.", "You have enabled URL previews by default.": "Du hast die URL-Vorschau standardmäßig aktiviert.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Du hast einen ungültigen Kontakt eingegeben. Versuche es mit der Matrix-ID oder der E-Mail-Adresse.", - "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Heimserver verbunden zu sein.", "$senderDisplayName changed the room avatar to ": "$senderDisplayName hat das Raum-Bild geändert zu ", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s hat das Raum-Bild für %(roomName)s geändert", "Hide removed messages": "Gelöschte Nachrichten verbergen", @@ -895,17 +886,16 @@ "%(count)s new messages.other": "%(count)s neue Nachrichten", "Error: Problem communicating with the given homeserver.": "Fehler: Problem beim kommunizieren mit dem angegebenen Heimserver.", "Failed to fetch avatar URL": "Fehler beim holen der Avatar-URL", - "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", "The phone number entered looks invalid": "Die Telefonnummer, die eingegeben wurde, sieht ungültig aus", "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht betretbar. Du kannst evtl. beitreten wenn du dich registrierst.", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber du hast keine Berechtigung diese Nachricht zu sehen.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber er konnte nicht gefunden werden.", "Uploading %(filename)s and %(count)s others.zero": "%(filename)s wird hochgeladen", - "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere werden hochgeladen", - "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere werden hochgeladen", + "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere Dateien werden hochgeladen", + "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere Dateien werden hochgeladen", "You must register to use this functionality": "Du musst dich registrieren um diese Funktionalität zu nutzen", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Sende erneut oder breche alles ab. Du kannst auch auch individuelle Nachrichten erneut senden or abbrechen.", - "Create new room": "Erstelle neuen Raum", + "Create new room": "Neuen Raum erstellen", "Welcome page": "Willkommensseite", "Room directory": "Raum-Verzeichnis", "Start chat": "Starte Chat", @@ -919,5 +909,7 @@ "Username not available": "Nutzername nicht verfügbar", "Something went wrong!": "Etwas ging schief!", "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", - "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Konto hast, kannst du ansonsten auch anmelden." + "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", + "Home": "Start", + "Username invalid: %(errMessage)s": "Nutzername falsch: %(errMessage)s" } diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ecbb20fbb7..ffd1ef5885 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -829,5 +829,34 @@ "Hide removed messages": "Cacher les messages supprimés", "Add": "Ajouter", "%(count)s new messages.one": "%(count)s nouveau message", - "%(count)s new messages.other": "%(count)s nouveaux messages" + "%(count)s new messages.other": "%(count)s nouveaux messages", + "Disable markdown formatting": "Désactiver le formattage markdown", + "Error: Problem communicating with the given homeserver.": "Erreur: Problème de communication avec le homeserveur.", + "Failed to fetch avatar URL": "Échec lors de la récupération de l’URL de l’avatar", + "The phone number entered looks invalid": "Le numéro de téléphone entré semble être invalide", + "Guest users can't upload files. Please register to upload.": "Les visiteurs ne peuvent pas télécharger de fichier. Veuillez vous enregistrer pour télécharger.", + "Some of your messages have not been sent.": "Certains de vos messages n’ont pas été envoyés.", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Ce salon est privé ou interdits aux visiteurs. Vous pourrez peut-être le joindre si vous vous enregistrez.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Un instant donné de la chronologie n’a pu être chargé car vous n’avez pas la permission de le visualiser.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Un instant donné de la chronologie n’a pu être chargé car il n’a pas pu être trouvé.", + "Uploading %(filename)s and %(count)s others.zero": "Téléchargement de %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "Téléchargement de %(filename)s et %(count)s autre", + "Uploading %(filename)s and %(count)s others.other": "Téléchargement de %(filename)s et %(count)s autres", + "You must register to use this functionality": "Vous devez vous inscrire pour utiliser cette fonctionnalité", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Tout renvoyer or tout annuler maintenant. Vous pouvez aussi sélectionner des messages individuels à envoyer ou annuler.", + "Create new room": "Créer un nouveau salon", + "Welcome page": "Page d'accueil", + "Room directory": "Répertoire des salons", + "Start chat": "Démarrer une discussion", + "New Password": "Nouveau mot de passe", + "Start chatting": "Démarrer une discussion", + "Start Chatting": "Démarrer une discussion", + "Click on the button below to start chatting!": "Cliquer sur le bouton ci-dessous pour commencer une discussion !", + "Create a new chat or reuse an existing one": "Démarrer une nouvelle discussion ou en réutiliser une existante", + "You already have existing direct chats with this user:": "Vous avez déjà des discussions en cours avec cet utilisateur :", + "Username available": "Nom d'utilisateur disponible", + "Username not available": "Nom d'utilisateur indisponible", + "Something went wrong!": "Quelque chose s’est mal passé !", + "This will be your account name on the homeserver, or you can pick a different server.": "Cela sera le nom de votre compte sur le serveur , ou vous pouvez sélectionner un autre serveur.", + "If you already have a Matrix account you can log in instead.": "Si vous avez déjà un compte Matrix vous pouvez vous identifier à la place." } diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 85b7a6a7f5..647fbfe1d5 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -92,14 +92,14 @@ "Found a bug?": "Нашли ошибку?", "had": "имеет", "Hangup": "Отключение", - "Historical": "Исторический", + "Historical": "История", "Homeserver is": "Домашний сервер является", "Identity Server is": "Регистрационный сервер", "I have verified my email address": "Я проверил мой адрес электронной почты", "Import E2E room keys": "Импортировать E2E ключ комнаты", "Invalid Email Address": "Недействительный адрес электронной почты", "invited": "invited", - "Invite new room members": "Прегласить новых учасников комнаты", + "Invite new room members": "Пригласить новых учасников в комнату", "Invites": "Приглашать", "Invites user with given id to current room": "Пригласить пользователя с данным id в текущую комнату", "is a": "является", @@ -119,13 +119,13 @@ "Logout": "Выход из системы", "Low priority": "Низкий приоритет", "made future room history visible to": "made future room history visible to", - "Manage Integrations": "Управление интеграций", + "Manage Integrations": "Управление интеграциями", "Members only": "Только участники", "Mobile phone number": "Номер мобильного телефона", "Moderator": "Ведущий", "my Matrix ID": "мой Matrix ID", "Name": "Имя", - "Never send encrypted messages to unverified devices from this device": "Никогда не отправляйте зашифрованные сообщения в непроверенные устройства с этого устройства", + "Never send encrypted messages to unverified devices from this device": "Никогда не отправлять зашифрованные сообщения на неверифицированные устроства с этого устройства", "Never send encrypted messages to unverified devices in this room from this device": "Никогда не отправляйте зашифрованные сообщения в непроверенные устройства в этой комнате из этого устройства", "New password": "Новый пароль", "New passwords must match each other.": "Новые пароли должны соответствовать друг другу.", @@ -190,7 +190,7 @@ "Voice call": "Голосовой вызов", "VoIP conference finished.": "VoIP конференция закончилась.", "VoIP conference started.": "VoIP Конференция стартовала.", - "(warning: cannot be disabled again!)": "(предупреждение: не может быть снова отключен!)", + "(warning: cannot be disabled again!)": "(предупреждение: не может быть отключено!)", "Warning!": "Предупреждение!", "was banned": "запрещен", "was invited": "приглашенный", @@ -200,7 +200,7 @@ "were": "быть", "Who can access this room?": "Кто может получить доступ к этой комнате?", "Who can read history?": "Кто может читать историю?", - "Who would you like to add to this room?": "Кого хотели бы Вы добавлять к этой комнате?", + "Who would you like to add to this room?": "Кого бы вы хотели пригласить в эту комнату?", "Who would you like to communicate with?": "С кем хотели бы Вы связываться?", "withdrawn": "уходить", "Would you like to": "Хотели бы Вы", @@ -658,7 +658,7 @@ "powered by Matrix": "управляемый с Matrix", "Add a topic": "Добавить тему", "Show timestamps in 12 hour format (e.g. 2:30pm)": "Времея отображать в 12 часовом формате (напр. 2:30pm)", - "Use compact timeline layout": "Используйте компактным указанием времени", + "Use compact timeline layout": "Компактное отображение", "Hide removed messages": "Скрыть удаленное сообщение", "No Microphones detected": "Микрофоны не обнаружены", "Unknown devices": "Незнакомое устройство", @@ -864,5 +864,35 @@ "Disable URL previews for this room (affects only you)": "Отключить предпросмотр URL в этой комнате (только для вас)", "$senderDisplayName changed the room avatar to ": "$senderDisplayName сменил аватар комнаты на ", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s удалил аватар комнаты.", - "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s сменил аватар для %(roomName)s" + "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s сменил аватар для %(roomName)s", + "Create new room": "Создать комнату", + "Room directory": "Каталог комнат", + "Start chat": "Начать чат", + "Welcome page": "Домашняя страница", + "Add": "Добавить", + "%(count)s new messages.one": "%(count)s новое сообщение", + "%(count)s new messages.other": "%(count)s новых сообщений", + "Error: Problem communicating with the given homeserver.": "Ошибка: проблема коммуникаций с указанным Home Server'ом.", + "Failed to fetch avatar URL": "Ошибка получения аватара", + "The phone number entered looks invalid": "Введенный номер телефона выглядит неправильным", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Ошибка загрузки истории комнаты: недостаточно прав.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Ошибка загрузки истории комнаты: запрошенный элемент не найден.", + "Uploading %(filename)s and %(count)s others.zero": "Загрузка %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "Загрузка %(filename)s и %(count)s другой файл", + "Uploading %(filename)s and %(count)s others.other": "Загрузка %(filename)s и %(count)s других файлов", + "Username invalid: %(errMessage)s": "Неверное имя пользователя: %(errMessage)s", + "Searching known users": "Искать известных пользователей", + "You must register to use this functionality": "Вы должны зарегистрироваться для использования этой функции", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Отослать снова или отменить отправку. Вы также можете выбрать на отправку или отмену отдельные сообщения.", + "New Password": "Новый пароль", + "Start chatting": "Начать общение", + "Start Chatting": "Начать общение", + "Click on the button below to start chatting!": "Нажмите на кнопку ниже для того, чтобы начать общение!", + "Create a new chat or reuse an existing one": "Создать новый чат или использовать уже существующий", + "You already have existing direct chats with this user:": "У вас уже есть существующие приватные чаты с этим пользователем:", + "Username available": "Имя пользователя доступно", + "Username not available": "Имя пользователя недоступно", + "Something went wrong!": "Что-то пошло не так!", + "This will be your account name on the homeserver, or you can pick a different server.": "Это будет ваше имя пользователя на , или вы можете выбрать другой сервер.", + "If you already have a Matrix account you can log in instead.": "Если вы уже имеете учетную запись Matrix, то вы можете войти." } diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 6608219faa..f97b6b8d50 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -201,7 +201,7 @@ "Hangup": "วางสาย", "Historical": "ประวัติแชทเก่า", "Homeserver is": "เซิร์ฟเวอร์บ้านคือ", - "Identity Server is": "เซิร์ฟเวอร์ยืนยันตัวตนคือ", + "Identity Server is": "เซิร์ฟเวอร์ระบุตัวตนคือ", "I have verified my email address": "ฉันยืนยันที่อยู่อีเมลแล้ว", "Import": "นำเข้า", "Incorrect username and/or password.": "ชื่อผู้ใช้และ/หรือรหัสผ่านไม่ถูกต้อง", @@ -229,7 +229,7 @@ "Leave room": "ออกจากห้อง", "left and rejoined": "ออกแล้วกลับเข้าร่วมอีกครั้ง", "left": "ออกไปแล้ว", - "%(targetName)s left the room.": "%(targetName)s ออกจากห้องไปแล้ว", + "%(targetName)s left the room.": "%(targetName)s ออกจากห้องแล้ว", "List this room in %(domain)s's room directory?": "แสดงห้องนี้ในไดเรกทอรีห้องของ %(domain)s?", "Logged in as:": "เข้าสู่ระบบในชื่อ:", "Login as guest": "เข้าสู่ระบบในฐานะแขก", @@ -322,7 +322,7 @@ "This is a preview of this room. Room interactions have been disabled": "นี่คือตัวอย่างของห้อง การตอบสนองภายในห้องถูกปิดใช้งาน", "This phone number is already in use": "หมายเลขโทรศัพท์นี้ถูกใช้งานแล้ว", "This room's internal ID is": "ID ภายในของห้องนี้คือ", - "times": "เวลา", + "times": "ครั้ง", "%(oneUser)schanged their name": "%(oneUser)sเปลี่ยนชื่อของเขาแล้ว", "%(severalUsers)schanged their name %(repeats)s times": "%(severalUsers)sเปลี่ยนชื่อของพวกเขา %(repeats)s ครั้ง", "%(oneUser)schanged their name %(repeats)s times": "%(oneUser)sเปลี่ยนชื่อของเขา %(repeats)s ครั้ง", @@ -330,5 +330,153 @@ "Create new room": "สร้างห้องใหม่", "Room directory": "ไดเรกทอรีห้อง", "Start chat": "เริ่มแชท", - "Welcome page": "หน้าต้อนรับ" + "Welcome page": "หน้าต้อนรับ", + "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "ไม่สามารถเชื่อมต่อไปยังเซิร์ฟเวอร์บ้านผ่านทาง HTTP ได้เนื่องจาก URL ที่อยู่บนเบราว์เซอร์เป็น HTTPS กรุณาใช้ HTTPS หรือเปิดใช้งานสคริปต์ที่ไม่ปลอดภัย.", + "%(count)s new messages.one": "มี %(count)s ข้อความใหม่", + "%(count)s new messages.other": "มี %(count)s ข้อความใหม่", + "Disable inline URL previews by default": "ตั้งค่าเริ่มต้นให้ไม่แสดงตัวอย่าง URL ในแชท", + "Disable markdown formatting": "ปิดใช้งานการจัดรูปแบบ markdown", + "End-to-end encryption information": "ข้อมูลการเข้ารหัสจากปลายทางถึงปลายทาง", + "End-to-end encryption is in beta and may not be reliable": "การเข้ารหัสจากปลายทางถึงปลายทางยังอยู่ในเบต้า และอาจพึ่งพาไม่ได้", + "Error: Problem communicating with the given homeserver.": "ข้อผิดพลาด: มีปัญหาในการติดต่อกับเซิร์ฟเวอร์บ้านที่กำหนด", + "Export E2E room keys": "ส่งออกกุญแจถอดรหัส E2E", + "Failed to change power level": "การเปลี่ยนระดับอำนาจล้มเหลว", + "Import E2E room keys": "นำเข้ากุญแจถอดรหัส E2E", + "to favourite": "ไปยังรายการโปรด", + "to demote": "เพื่อลดขั้น", + "The default role for new room members is": "บทบาทเริ่มต้นของสมาชิกใหม่คือ", + "The phone number entered looks invalid": "ดูเหมือนว่าหมายเลขโทรศัพท์ที่กรอกรมาไม่ถูกต้อง", + "The email address linked to your account must be entered.": "กรุณากรอกที่อยู่อีเมลที่เชื่อมกับบัญชีของคุณ", + "The file '%(fileName)s' exceeds this home server's size limit for uploads": "ไฟล์ '%(fileName)s' มีขนาดใหญ่เกินจำกัดของเซิร์ฟเวอร์บ้าน", + "To send messages": "เพื่อส่งข้อความ", + "to start a chat with someone": "เพื่อเริ่มแชทกับผู้อื่น", + "to tag as %(tagName)s": "เพื่อแท็กว่า %(tagName)s", + "to tag direct chat": "เพื่อแทกว่าแชทตรง", + "Turn Markdown off": "ปิด markdown", + "Turn Markdown on": "เปิด markdown", + "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s ได้เปิดใช้งานการเข้ารหัสจากปลายทางถึงปลายทาง (อัลกอริทึม%(algorithm)s).", + "Unable to add email address": "ไมาสามารถเพิ่มที่อยู่อีเมล", + "Unable to verify email address.": "ไม่สามารถยืนยันที่อยู่อีเมล", + "Unban": "ปลดแบน", + "%(senderName)s unbanned %(targetName)s.": "%(senderName)s ปลดแบน %(targetName)s แล้ว", + "Unable to capture screen": "ไม่สามารถจับภาพหน้าจอ", + "Unable to enable Notifications": "ไม่สามารถเปิดใช้งานการแจ้งเตือน", + "Unable to load device list": "ไม่สามารถโหลดรายชื่ออุปกรณ์", + "Unencrypted room": "ห้องที่ไม่เข้ารหัส", + "unencrypted": "ยังไม่ได้เข้ารหัส", + "Unknown command": "คำสั่งที่ไม่รู้จัก", + "unknown device": "อุปกรณ์ที่ไม่รู้จัก", + "Unknown room %(roomId)s": "ห้องที่ไม่รู้จัก %(roomId)s", + "Unknown (user, device) pair:": "คู่ (ผู้ใช้, อุปกรณ์) ที่ไม่รู้จัก:", + "unknown": "ไม่รู้จัก", + "Unrecognised command:": "คำสั่งที่ไม่รู้จัก:", + "Unrecognised room alias:": "นามแฝงห้องที่ไม่รู้จัก:", + "Uploading %(filename)s and %(count)s others.zero": "กำลังอัปโหลด %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "กำลังอัปโหลด %(filename)s และอีก %(count)s ไฟล์", + "Uploading %(filename)s and %(count)s others.other": "กำลังอัปโหลด %(filename)s และอีก %(count)s ไฟล์", + "uploaded a file": "อัปโหลดไฟล์", + "Upload Failed": "การอัปโหลดล้มเหลว", + "Upload Files": "อัปโหลดไฟล์", + "Upload file": "อัปโหลดไฟล์", + "Usage": "การใช้งาน", + "User ID": "ID ผู้ใช้", + "User Interface": "อินเตอร์เฟสผู้ใช้", + "User name": "ชื่อผู้ใช้", + "User": "ผู้ใช้", + "Warning!": "คำเตือน!", + "Who can access this room?": "ใครสามารถเข้าถึงห้องนี้ได้?", + "Who can read history?": "ใครสามารถอ่านประวัติแชทได้?", + "Who would you like to add to this room?": "คุณต้องการเพิ่มใครเข้าห้องนี้?", + "Who would you like to communicate with?": "คุณต้องการสื่อสารกับใคร?", + "You're not in any rooms yet! Press": "คุณยังไม่ได้อยู่ในห้องใดเลย! กด", + "You are trying to access %(roomName)s": "คุณกำลังพยายามเข้าสู่ %(roomName)s", + "You have disabled URL previews by default.": "ค่าเริ่มต้นของคุณปิดใช้งานตัวอย่าง URL เอาไว้", + "You have enabled URL previews by default.": "ค่าเริ่มต้นของคุณเปิดใช้งานตัวอย่าง URL เอาไว้", + "you must be a": "คุณต้องเป็น", + "You must register to use this functionality": "คุณต้องลงทะเบียนเพื่อใช้ฟังก์ชันนี้", + "You need to be logged in.": "คุณต้องเข้าสู่ระบบก่อน", + "You need to enter a user name.": "คุณต้องกรอกชื่อผู้ใช้ก่อน", + "Your password has been reset": "รหัสผ่านถูกรีเซ็ตแล้ว", + "Your password was successfully changed. You will not receive push notifications on other devices until you log back in to them": "การเปลี่ยนรหัสผ่านเสร็จสมบูณณ์ คุณจะไม่ได้รับการแจ้งเตือนบนอุปกรณ์อื่น ๆ จนกว่าคุณจะกลับเข้าสู่ระบบในอุปกรณ์เหล่านั้น", + "Sun": "อา.", + "Mon": "จ.", + "Tue": "อ.", + "Wed": "พ.", + "Thu": "พฤ.", + "Fri": "ศ.", + "Sat": "ส.", + "Jan": "ม.ค.", + "Feb": "ก.พ.", + "Mar": "มี.ค.", + "Apr": "เม.ย.", + "May": "พ.ค.", + "Jun": "มิ.ย.", + "Jul": "ก.ค.", + "Aug": "ส.ค.", + "Sep": "ก.ย.", + "Oct": "ต.ค.", + "Nov": "พ.ย.", + "Dec": "ธ.ค.", + "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s %(day)s %(monthName)s %(time)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s %(day)s %(monthName)s %(fullYear)s %(time)s", + "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", + "Set a display name:": "ตั้งชื่อที่แสดง:", + "Set a Display Name": "ตั้งชื่อที่แสดง", + "Passwords don't match.": "รหัสผ่านไม่ตรงกัน", + "Password too short (min %(MIN_PASSWORD_LENGTH)s).": "รหัสผ่านสั้นเกินไป (ขึ้นต่ำ %(MIN_PASSWORD_LENGTH)s ตัวอักษร)", + "An unknown error occurred.": "เกิดข้อผิดพลาดที่ไม่รู้จัก", + "I already have an account": "ฉันมีบัญชีอยู่แล้ว", + "An error occured: %(error_string)s": "เกิดข้อผิดพลาด: %(error_string)s", + "Topic": "หัวข้อ", + "Make Moderator": "เลื่อนขั้นเป็นผู้ช่วยดูแล", + "Make this room private": "ทำให้ห้องนี้เป็นส่วนตัว", + "Share message history with new users": "แบ่งประวัติแชทให้ผู้ใช้ใหม่", + "Encrypt room": "เข้ารหัสห้อง", + "Room": "ห้อง", + "(~%(searchCount)s results)": "(~%(searchCount)s ผลลัพธ์)", + "or": "หรือ", + "bold": "หนา", + "italic": "เอียง", + "strike": "ขีดทับ", + "underline": "ขีดเส้นใต้", + "code": "โค๊ด", + "quote": "อ้างอิง", + "were kicked %(repeats)s times": "ถูกเตะ %(repeats)s ครั้ง", + "was kicked %(repeats)s times": "ถูกเตะ %(repeats)s ครั้ง", + "were kicked": "ถูกเตะ", + "was kicked": "ถูกเตะ", + "New Password": "รหัสผ่านใหม่", + "Options": "ตัวเลือก", + "Export room keys": "ส่งออกกุณแจห้อง", + "Confirm passphrase": "ยืนยันรหัสผ่าน", + "Import room keys": "นำเข้ากุณแจห้อง", + "File to import": "ไฟล์ที่จะนำเข้า", + "Start new chat": "เริ่มแชทใหม่", + "Failed to invite": "การเชิญล้มเหลว", + "Failed to invite user": "การเชิญผู้ใช้ล้มเหลว", + "Failed to invite the following users to the %(roomName)s room:": "การเชิญผู้ใช้เหล่านี้เข้าสู่ห้อง %(roomName)s ล้มเหลว:", + "Confirm Removal": "ยืนยันการลบ", + "Unknown error": "ข้อผิดพลาดที่ไม่รู้จัก", + "Incorrect password": "รหัสผ่านไม่ถูกต้อง", + "Device name": "ชื่ออุปกรณ์", + "Device key": "Key อุปกรณ์", + "Unknown devices": "อุปกรณ์ที่ไม่รู้จัก", + "Unknown Address": "ที่อยู่ที่ไม่รู้จัก", + "Unblacklist": "ถอดบัญชีดำ", + "Blacklist": "ขึ้นบัญชีดำ", + "ex. @bob:example.com": "เช่น @bob:example.com", + "Add User": "เพิ่มผู้ใช้", + "This Home Server would like to make sure you are not a robot": "เซิร์ฟเวอร์บ้านต้องการยืนยันว่าคุณไม่ใช่หุ่นยนต์", + "Sign in with CAS": "เข้าสู่ระบบด้วย CAS", + "You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.": "คุณสามารถกำหนดเซิร์ฟเวอร์บ้านเองได้โดยใส่ URL ของเซิร์ฟเวอร์นั้น เพื่อเข้าสู่ระบบของเซิร์ฟเวอร์ Matrix อื่น", + "This allows you to use this app with an existing Matrix account on a different home server.": "ทั้งนี่เพื่อให้คุณสามารถใช้ Riot กับบัญชี Matrix ที่มีอยู่แล้วบนเซิร์ฟเวอร์บ้านอื่น ๆ ได้", + "You can also set a custom identity server but this will typically prevent interaction with users based on email address.": "คุณอาจเลือกเซิร์ฟเวอร์ระบุตัวตนเองด้วยก็ได้ แต่คุณจะไม่สามารถเชิญผู้ใช้อื่นด้วยที่อยู่อีเมล หรือรับคำเชิญจากผู้ใช้อื่นทางที่อยู่อีเมลได้", + "Default server": "เซิร์ฟเวอร์เริ่มต้น", + "Custom server": "เซิร์ฟเวอร์ที่กำหนดเอง", + "Home server URL": "URL เซิร์ฟเวอร์บ้าน", + "Identity server URL": "URL เซิร์ฟเวอร์ระบุตัวตน", + "%(severalUsers)sleft %(repeats)s times": "%(targetName)sออกจากห้อง %(repeats)s ครั้ง", + "%(oneUser)sleft %(repeats)s times": "%(oneUser)sออกจากห้อง %(repeats)s ครั้ง", + "%(severalUsers)sleft": "%(severalUsers)sออกจากห้องแล้ว", + "%(oneUser)sleft": "%(oneUser)sออกจากห้องแล้ว" } From 1c58a9cd5e1ef9625fb4a2b753b6639ec00027ce Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Jun 2017 12:33:29 +0100 Subject: [PATCH 200/275] Everything but src/components/views/rooms --- .../views/dialogs/InteractiveAuthDialog.js | 2 +- .../dialogs/SessionRestoreErrorDialog.js | 9 +++++--- .../views/dialogs/SetDisplayNameDialog.js | 2 +- .../views/dialogs/UnknownDeviceDialog.js | 4 ++-- .../views/elements/TruncatedList.js | 3 ++- .../login/InteractiveAuthEntryComponents.js | 2 +- .../views/login/RegistrationForm.js | 4 ++-- .../views/room_settings/ColorSettings.js | 5 +++-- .../views/settings/AddPhoneNumber.js | 2 +- src/components/views/settings/ChangeAvatar.js | 5 +++-- .../views/settings/ChangeDisplayName.js | 3 ++- .../views/settings/ChangePassword.js | 2 +- src/components/views/settings/DevicesPanel.js | 11 +++++----- .../settings/EnableNotificationsButton.js | 5 +++-- src/components/views/voip/CallView.js | 7 +++++- src/components/views/voip/IncomingCallBox.js | 22 +++++++++++++++---- src/i18n/strings/en_EN.json | 22 +++++++++++++++++++ 17 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/components/views/dialogs/InteractiveAuthDialog.js b/src/components/views/dialogs/InteractiveAuthDialog.js index 945e0a9d69..363ce89b57 100644 --- a/src/components/views/dialogs/InteractiveAuthDialog.js +++ b/src/components/views/dialogs/InteractiveAuthDialog.js @@ -78,7 +78,7 @@ export default React.createClass({ - Dismiss + {_t("Dismiss")}
); diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index e7f6e19db7..51651b4aaa 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -18,7 +18,7 @@ import React from 'react'; import sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import Modal from '../../../Modal'; -import { _t } from '../../../languageHandler'; +import { _t, _tJsx } from '../../../languageHandler'; export default React.createClass({ @@ -44,8 +44,11 @@ export default React.createClass({ if (SdkConfig.get().bug_report_endpoint_url) { bugreport = ( -

Otherwise, - click here to send a bug report. +

+ {_tJsx( + "Otherwise, click here to send a bug report.", + /(.*?)<\/a>/, (sub) => {sub} + )}

); } diff --git a/src/components/views/dialogs/SetDisplayNameDialog.js b/src/components/views/dialogs/SetDisplayNameDialog.js index 1134b1f8cd..0d6f486e0e 100644 --- a/src/components/views/dialogs/SetDisplayNameDialog.js +++ b/src/components/views/dialogs/SetDisplayNameDialog.js @@ -80,7 +80,7 @@ export default React.createClass({ />
- +
diff --git a/src/components/views/dialogs/UnknownDeviceDialog.js b/src/components/views/dialogs/UnknownDeviceDialog.js index 8f91b84519..6ebd0c3efc 100644 --- a/src/components/views/dialogs/UnknownDeviceDialog.js +++ b/src/components/views/dialogs/UnknownDeviceDialog.js @@ -145,7 +145,7 @@ export default React.createClass({ console.log("UnknownDeviceDialog closed by escape"); this.props.onFinished(); }} - title='Room contains unknown devices' + title={_t('Room contains unknown devices')} >

@@ -162,7 +162,7 @@ export default React.createClass({ this.props.onFinished(); Resend.resendUnsentEvents(this.props.room); }}> - Send anyway + {_t("Send anyway")} ); } else { return ( ); } diff --git a/src/components/views/voip/CallView.js b/src/components/views/voip/CallView.js index 6cab7531b7..b53794637f 100644 --- a/src/components/views/voip/CallView.js +++ b/src/components/views/voip/CallView.js @@ -18,6 +18,7 @@ var dis = require("../../../dispatcher"); var CallHandler = require("../../../CallHandler"); var sdk = require('../../../index'); var MatrixClientPeg = require("../../../MatrixClientPeg"); +import { _t } from '../../../languageHandler'; module.exports = React.createClass({ displayName: 'CallView', @@ -130,7 +131,11 @@ module.exports = React.createClass({ var voice; if (this.state.call && this.state.call.type === "voice" && this.props.showVoice) { var callRoom = MatrixClientPeg.get().getRoom(this.state.call.roomId); - voice =
Active call ({ callRoom.name })
; + voice = ( +
+ {_t("Active call (%(roomName)s)", {roomName: callRoom.name})} +
+ ); } return ( diff --git a/src/components/views/voip/IncomingCallBox.js b/src/components/views/voip/IncomingCallBox.js index 6cd19538f0..1b806fc5b3 100644 --- a/src/components/views/voip/IncomingCallBox.js +++ b/src/components/views/voip/IncomingCallBox.js @@ -17,6 +17,7 @@ var React = require('react'); var MatrixClientPeg = require('../../../MatrixClientPeg'); var dis = require("../../../dispatcher"); var CallHandler = require("../../../CallHandler"); +import { _t } from '../../../languageHandler'; module.exports = React.createClass({ displayName: 'IncomingCallBox', @@ -45,23 +46,36 @@ module.exports = React.createClass({ room = MatrixClientPeg.get().getRoom(this.props.incomingCall.roomId); } - var caller = room ? room.name : "unknown"; + var caller = room ? room.name : _t("unknown caller"); + + let incomingCallText = null; + if (this.props.incomingCall) { + if (this.props.incomingCall.type === "voice") { + incomingCallText = _t("Incoming voice call from %(name)s", {name: caller}); + } + else if (this.props.incomingCall.type === "video") { + incomingCallText = _t("Incoming video call from %(name)s", {name: caller}); + } + else { + incomingCallText = _t("Incoming call from %(name)s", {name: caller}); + } + } return (
- Incoming { this.props.incomingCall ? this.props.incomingCall.type : '' } call from { caller } + {incomingCallText}
- Decline + {_t("Decline")}
- Accept + {_t("Accept")}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 36d220dca5..de1adc539d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -122,15 +122,18 @@ "A registered account is required for this action": "A registered account is required for this action", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains", "accept": "accept", + "Accept": "Accept", "%(targetName)s accepted an invitation.": "%(targetName)s accepted an invitation.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s accepted the invitation for %(displayName)s.", "Account": "Account", "Access Token:": "Access Token:", + "Active call (%(roomName)s)": "Active call (%(roomName)s)", "Add": "Add", "Add a topic": "Add a topic", "Add email address": "Add email address", "Add phone number": "Add phone number", "Admin": "Admin", + "And %(count)s more...": "And %(count)s more...", "VoIP": "VoIP", "Missing Media Permissions, click here to request.": "Missing Media Permissions, click here to request.", "No Microphones detected": "No Microphones detected", @@ -230,6 +233,7 @@ "/ddg is not a command": "/ddg is not a command", "Deactivate Account": "Deactivate Account", "Deactivate my account": "Deactivate my account", + "Decline": "Decline", "decline": "decline", "Decrypt %(text)s": "Decrypt %(text)s", "Decryption error": "Decryption error", @@ -247,6 +251,7 @@ "Devices will not yet be able to decrypt history from before they joined the room": "Devices will not yet be able to decrypt history from before they joined the room", "Direct Chat": "Direct Chat", "Direct chats": "Direct chats", + "Disable Notifications": "Disable Notifications", "disabled": "disabled", "Disable inline URL previews by default": "Disable inline URL previews by default", "Disable markdown formatting": "Disable markdown formatting", @@ -264,6 +269,7 @@ "Email, name or matrix ID": "Email, name or matrix ID", "Emoji": "Emoji", "Enable encryption": "Enable encryption", + "Enable Notifications": "Enable Notifications", "enabled": "enabled", "Encrypted messages will not be visible on clients that do not yet implement encryption": "Encrypted messages will not be visible on clients that do not yet implement encryption", "Encrypted room": "Encrypted room", @@ -303,6 +309,7 @@ "Failed to toggle moderator status": "Failed to toggle moderator status", "Failed to unban": "Failed to unban", "Failed to upload file": "Failed to upload file", + "Failed to upload profile picture!": "Failed to upload profile picture!", "Failed to verify email address: make sure you clicked the link in the email": "Failed to verify email address: make sure you clicked the link in the email", "Failure to create room": "Failure to create room", "Favourite": "Favourite", @@ -332,6 +339,9 @@ "I have verified my email address": "I have verified my email address", "Import": "Import", "Import E2E room keys": "Import E2E room keys", + "Incoming call from %(name)s": "Incoming call from %(name)s", + "Incoming video call from %(name)s": "Incoming video call from %(name)s", + "Incoming voice call from %(name)s": "Incoming voice call from %(name)s", "Incorrect username and/or password.": "Incorrect username and/or password.", "Incorrect verification code": "Incorrect verification code", "Interface Language": "Interface Language", @@ -359,6 +369,7 @@ "Kick": "Kick", "Kicks user with given id": "Kicks user with given id", "Labs": "Labs", + "Last seen": "Last seen", "Leave room": "Leave room", "left and rejoined": "left and rejoined", "left": "left", @@ -402,6 +413,7 @@ "": "", "NOT verified": "NOT verified", "No devices with registered encryption keys": "No devices with registered encryption keys", + "No display name": "No display name", "No more results": "No more results", "No results": "No results", "No users have specific privileges in this room": "No users have specific privileges in this room", @@ -411,6 +423,7 @@ "Once you've followed the link it contains, click below": "Once you've followed the link it contains, click below", "Only people who have been invited": "Only people who have been invited", "Operation failed": "Operation failed", + "Otherwise, click here to send a bug report.": "Otherwise, click here to send a bug report.", "Password": "Password", "Password:": "Password:", "Passwords can't be empty": "Passwords can't be empty", @@ -453,9 +466,11 @@ "riot-web version:": "riot-web version:", "Room %(roomId)s not visible": "Room %(roomId)s not visible", "Room Colour": "Room Colour", + "Room contains unknown devices": "Room contains unknown devices", "Room name (optional)": "Room name (optional)", "Rooms": "Rooms", "Save": "Save", + "Saving room color settings is only available to registered users": "Saving room color settings is only available to registered users", "Scroll to bottom of page": "Scroll to bottom of page", "Scroll to unread messages": "Scroll to unread messages", "Search": "Search", @@ -464,6 +479,7 @@ "Searching known users": "Searching known users", "Send a message (unencrypted)": "Send a message (unencrypted)", "Send an encrypted message": "Send an encrypted message", + "Send anyway": "Send anyway", "Sender device information": "Sender device information", "Send Invites": "Send Invites", "Send Reset Email": "Send Reset Email", @@ -480,6 +496,7 @@ "Session ID": "Session ID", "%(senderName)s set a profile picture.": "%(senderName)s set a profile picture.", "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s set their display name to %(displayName)s.", + "Set": "Set", "Setting a user name will create a fresh account": "Setting a user name will create a fresh account", "Settings": "Settings", "Show panel": "Show panel", @@ -494,6 +511,7 @@ "Someone": "Someone", "Sorry, this homeserver is using a login which is not recognised ": "Sorry, this homeserver is using a login which is not recognised ", "Start a chat": "Start a chat", + "Start authentication": "Start authentication", "Start Chat": "Start Chat", "Submit": "Submit", "Success": "Success", @@ -561,6 +579,7 @@ "Unable to load device list": "Unable to load device list", "Unencrypted room": "Unencrypted room", "unencrypted": "unencrypted", + "unknown caller": "unknown caller", "Unknown command": "Unknown command", "unknown device": "unknown device", "unknown error code": "unknown error code", @@ -580,6 +599,7 @@ "Upload Failed": "Upload Failed", "Upload Files": "Upload Files", "Upload file": "Upload file", + "Upload new:": "Upload new:", "Usage": "Usage", "Use compact timeline layout": "Use compact timeline layout", "Use with caution": "Use with caution", @@ -633,6 +653,7 @@ "You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?", "You should not yet trust it to secure data": "You should not yet trust it to secure data", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself", + "Your home server does not support device management.": "Your home server does not support device management.", "Sun": "Sun", "Mon": "Mon", "Tue": "Tue", @@ -780,6 +801,7 @@ "To continue, please enter your password.": "To continue, please enter your password.", "To verify that this device can be trusted, please contact its owner using some other means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings for this device matches the key below:": "To verify that this device can be trusted, please contact its owner using some other means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings for this device matches the key below:", "Device name": "Device name", + "Device Name": "Device Name", "Device key": "Device key", "If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.": "If it matches, press the verify button below. If it doesn't, then someone else is intercepting this device and you probably want to press the blacklist button instead.", "In future this verification process will be more sophisticated.": "In future this verification process will be more sophisticated.", From 7e7b5a6dc03c36a831dcbad40744fe669f22de6c Mon Sep 17 00:00:00 2001 From: Vladi Date: Thu, 8 Jun 2017 11:46:42 +0000 Subject: [PATCH 201/275] Translated using Weblate (Russian) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 647fbfe1d5..4f1939ffcc 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -667,7 +667,7 @@ "Desktop specific": "Специфический десктоп", "Start automatically after system login": "Автостарт после входа в систему", "Analytics": "Аналитика", - "Riot collects anonymous analytics to allow us to improve the application.": "Riot собирет анонимные данные, чтобы улутшыть эту програму.", + "Riot collects anonymous analytics to allow us to improve the application.": "Riot собирает анонимные данные, чтобы улучшить эту программу.", "Opt out of analytics": "Подтвердить отказ передачи аналитических данных", "Logged in as:": "Зарегестрирован как:", "Default Device": "Стандартное устройство", @@ -894,5 +894,6 @@ "Username not available": "Имя пользователя недоступно", "Something went wrong!": "Что-то пошло не так!", "This will be your account name on the homeserver, or you can pick a different server.": "Это будет ваше имя пользователя на , или вы можете выбрать другой сервер.", - "If you already have a Matrix account you can log in instead.": "Если вы уже имеете учетную запись Matrix, то вы можете войти." + "If you already have a Matrix account you can log in instead.": "Если вы уже имеете учетную запись Matrix, то вы можете войти.", + "Home": "Старт" } From 9bda212cb189939066f389ec7d2d7d3677d4219c Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 8 Jun 2017 13:52:52 +0100 Subject: [PATCH 202/275] Make travis/jenkins check for lint on files which are clean to start with --- .eslintignore.errorfiles | 187 ++++++++++++++++++++++ .travis.yml | 4 +- jenkins.sh | 5 + scripts/generate-eslint-error-ignore-file | 21 +++ scripts/travis.sh | 11 ++ 5 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 .eslintignore.errorfiles create mode 100755 scripts/generate-eslint-error-ignore-file create mode 100755 scripts/travis.sh diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles new file mode 100644 index 0000000000..f1b63d7367 --- /dev/null +++ b/.eslintignore.errorfiles @@ -0,0 +1,187 @@ +# autogenerated file: run scripts/generate-eslint-error-ignore-file to update. + +src/AddThreepid.js +src/async-components/views/dialogs/EncryptedEventDialog.js +src/autocomplete/AutocompleteProvider.js +src/autocomplete/Autocompleter.js +src/autocomplete/Components.js +src/autocomplete/DuckDuckGoProvider.js +src/autocomplete/EmojiProvider.js +src/autocomplete/RoomProvider.js +src/autocomplete/UserProvider.js +src/Avatar.js +src/BasePlatform.js +src/CallHandler.js +src/component-index.js +src/components/structures/ContextualMenu.js +src/components/structures/CreateRoom.js +src/components/structures/FilePanel.js +src/components/structures/InteractiveAuth.js +src/components/structures/LoggedInView.js +src/components/structures/login/ForgotPassword.js +src/components/structures/login/Login.js +src/components/structures/login/PostRegistration.js +src/components/structures/login/Registration.js +src/components/structures/MatrixChat.js +src/components/structures/MessagePanel.js +src/components/structures/NotificationPanel.js +src/components/structures/RoomStatusBar.js +src/components/structures/RoomView.js +src/components/structures/ScrollPanel.js +src/components/structures/TimelinePanel.js +src/components/structures/UploadBar.js +src/components/structures/UserSettings.js +src/components/views/avatars/BaseAvatar.js +src/components/views/avatars/MemberAvatar.js +src/components/views/avatars/RoomAvatar.js +src/components/views/create_room/CreateRoomButton.js +src/components/views/create_room/Presets.js +src/components/views/create_room/RoomAlias.js +src/components/views/dialogs/ChatCreateOrReuseDialog.js +src/components/views/dialogs/ChatInviteDialog.js +src/components/views/dialogs/DeactivateAccountDialog.js +src/components/views/dialogs/InteractiveAuthDialog.js +src/components/views/dialogs/SetMxIdDialog.js +src/components/views/dialogs/UnknownDeviceDialog.js +src/components/views/elements/AccessibleButton.js +src/components/views/elements/ActionButton.js +src/components/views/elements/AddressSelector.js +src/components/views/elements/AddressTile.js +src/components/views/elements/CreateRoomButton.js +src/components/views/elements/DeviceVerifyButtons.js +src/components/views/elements/DirectorySearchBox.js +src/components/views/elements/Dropdown.js +src/components/views/elements/EditableText.js +src/components/views/elements/EditableTextContainer.js +src/components/views/elements/HomeButton.js +src/components/views/elements/LanguageDropdown.js +src/components/views/elements/MemberEventListSummary.js +src/components/views/elements/PowerSelector.js +src/components/views/elements/ProgressBar.js +src/components/views/elements/RoomDirectoryButton.js +src/components/views/elements/SettingsButton.js +src/components/views/elements/StartChatButton.js +src/components/views/elements/TintableSvg.js +src/components/views/elements/TruncatedList.js +src/components/views/elements/UserSelector.js +src/components/views/login/CaptchaForm.js +src/components/views/login/CasLogin.js +src/components/views/login/CountryDropdown.js +src/components/views/login/CustomServerDialog.js +src/components/views/login/InteractiveAuthEntryComponents.js +src/components/views/login/LoginHeader.js +src/components/views/login/PasswordLogin.js +src/components/views/login/RegistrationForm.js +src/components/views/login/ServerConfig.js +src/components/views/messages/MAudioBody.js +src/components/views/messages/MessageEvent.js +src/components/views/messages/MFileBody.js +src/components/views/messages/MImageBody.js +src/components/views/messages/MVideoBody.js +src/components/views/messages/RoomAvatarEvent.js +src/components/views/messages/TextualBody.js +src/components/views/messages/TextualEvent.js +src/components/views/room_settings/AliasSettings.js +src/components/views/room_settings/ColorSettings.js +src/components/views/room_settings/UrlPreviewSettings.js +src/components/views/rooms/Autocomplete.js +src/components/views/rooms/AuxPanel.js +src/components/views/rooms/EntityTile.js +src/components/views/rooms/EventTile.js +src/components/views/rooms/LinkPreviewWidget.js +src/components/views/rooms/MemberDeviceInfo.js +src/components/views/rooms/MemberInfo.js +src/components/views/rooms/MemberList.js +src/components/views/rooms/MemberTile.js +src/components/views/rooms/MessageComposer.js +src/components/views/rooms/MessageComposerInput.js +src/components/views/rooms/MessageComposerInputOld.js +src/components/views/rooms/PresenceLabel.js +src/components/views/rooms/ReadReceiptMarker.js +src/components/views/rooms/RoomHeader.js +src/components/views/rooms/RoomList.js +src/components/views/rooms/RoomNameEditor.js +src/components/views/rooms/RoomPreviewBar.js +src/components/views/rooms/RoomSettings.js +src/components/views/rooms/RoomTile.js +src/components/views/rooms/RoomTopicEditor.js +src/components/views/rooms/SearchableEntityList.js +src/components/views/rooms/SearchResultTile.js +src/components/views/rooms/TabCompleteBar.js +src/components/views/rooms/TopUnreadMessagesBar.js +src/components/views/rooms/UserTile.js +src/components/views/settings/AddPhoneNumber.js +src/components/views/settings/ChangeAvatar.js +src/components/views/settings/ChangeDisplayName.js +src/components/views/settings/ChangePassword.js +src/components/views/settings/DevicesPanel.js +src/components/views/settings/DevicesPanelEntry.js +src/components/views/settings/EnableNotificationsButton.js +src/components/views/voip/CallView.js +src/components/views/voip/IncomingCallBox.js +src/components/views/voip/VideoFeed.js +src/components/views/voip/VideoView.js +src/ContentMessages.js +src/createRoom.js +src/DateUtils.js +src/email.js +src/Entities.js +src/extend.js +src/HtmlUtils.js +src/ImageUtils.js +src/Invite.js +src/languageHandler.js +src/linkify-matrix.js +src/Login.js +src/Markdown.js +src/MatrixClientPeg.js +src/Modal.js +src/Notifier.js +src/ObjectUtils.js +src/PasswordReset.js +src/PlatformPeg.js +src/Presence.js +src/ratelimitedfunc.js +src/Resend.js +src/RichText.js +src/Roles.js +src/RoomListSorter.js +src/RoomNotifs.js +src/Rooms.js +src/RtsClient.js +src/ScalarAuthClient.js +src/ScalarMessaging.js +src/SdkConfig.js +src/Skinner.js +src/SlashCommands.js +src/stores/LifecycleStore.js +src/TabComplete.js +src/TabCompleteEntries.js +src/TextForEvent.js +src/Tinter.js +src/UiEffects.js +src/Unread.js +src/UserActivity.js +src/utils/DecryptFile.js +src/utils/DMRoomMap.js +src/utils/FormattingUtils.js +src/utils/MultiInviter.js +src/utils/Receipt.js +src/Velociraptor.js +src/VelocityBounce.js +src/WhoIsTyping.js +src/wrappers/WithMatrixClient.js +test/all-tests.js +test/components/structures/login/Registration-test.js +test/components/structures/MessagePanel-test.js +test/components/structures/ScrollPanel-test.js +test/components/structures/TimelinePanel-test.js +test/components/stub-component.js +test/components/views/dialogs/InteractiveAuthDialog-test.js +test/components/views/elements/MemberEventListSummary-test.js +test/components/views/login/RegistrationForm-test.js +test/components/views/rooms/MessageComposerInput-test.js +test/mock-clock.js +test/skinned-sdk.js +test/stores/RoomViewStore-test.js +test/test-utils.js diff --git a/.travis.yml b/.travis.yml index a405b9ef35..918cec696b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,4 @@ install: - npm install - (cd node_modules/matrix-js-sdk && npm install) script: - # don't run the riot tests unless the react-sdk tests pass, otherwise - # the output is confusing. - - npm run test && ./.travis-test-riot.sh + ./scripts/travis.sh diff --git a/jenkins.sh b/jenkins.sh index 6a77911c27..d9bb62855b 100755 --- a/jenkins.sh +++ b/jenkins.sh @@ -21,6 +21,11 @@ npm run test # run eslint npm run lintall -- -f checkstyle -o eslint.xml || true +# re-run the linter, excluding any files known to have errors or warnings. +./node_modules/.bin/eslint --max-warnings 0 \ + --ignore-path .eslintignore.errorfiles \ + src test + # delete the old tarball, if it exists rm -f matrix-react-sdk-*.tgz diff --git a/scripts/generate-eslint-error-ignore-file b/scripts/generate-eslint-error-ignore-file new file mode 100755 index 0000000000..3a635f5a7d --- /dev/null +++ b/scripts/generate-eslint-error-ignore-file @@ -0,0 +1,21 @@ +#!/bin/sh +# +# generates .eslintignore.errorfiles to list the files which have errors in, +# so that they can be ignored in future automated linting. + +out=.eslintignore.errorfiles + +cd `dirname $0`/.. + +echo "generating $out" + +{ + cat < 0) | .filePath' | + sed -e 's/.*matrix-react-sdk\///'; +} > "$out" diff --git a/scripts/travis.sh b/scripts/travis.sh new file mode 100755 index 0000000000..f349b06ad5 --- /dev/null +++ b/scripts/travis.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -ex + +npm run test +./.travis-test-riot.sh + +# run the linter, but exclude any files known to have errors or warnings. +./node_modules/.bin/eslint --max-warnings 0 \ + --ignore-path .eslintignore.errorfiles \ + src test From 00df956ca24b39134641573ea9456bbdd7d63565 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Jun 2017 14:08:51 +0100 Subject: [PATCH 203/275] Add remaining translations! Every file has now been manually vetted by me. Due to the extent of the changes, I've been unable to test all scenarios to make sure this all works. :( --- src/components/views/rooms/AuxPanel.js | 15 +++-- src/components/views/rooms/EntityTile.js | 5 +- src/components/views/rooms/EventTile.js | 10 ++-- .../views/rooms/MemberDeviceInfo.js | 6 +- src/components/views/rooms/MemberInfo.js | 8 +-- src/components/views/rooms/MemberTile.js | 3 +- src/components/views/rooms/MessageComposer.js | 6 +- .../views/rooms/ReadReceiptMarker.js | 7 ++- src/components/views/rooms/RoomHeader.js | 4 +- src/components/views/rooms/RoomNameEditor.js | 5 +- src/components/views/rooms/RoomPreviewBar.js | 58 +++++++++++++------ src/components/views/rooms/RoomSettings.js | 14 +++-- .../views/rooms/SimpleRoomHeader.js | 3 +- .../views/rooms/TopUnreadMessagesBar.js | 2 +- src/i18n/strings/en_EN.json | 53 ++++++++++++----- 15 files changed, 130 insertions(+), 69 deletions(-) diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index f53512e684..7e7a670aea 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -19,7 +19,7 @@ import MatrixClientPeg from "../../../MatrixClientPeg"; import sdk from '../../../index'; import dis from "../../../dispatcher"; import ObjectUtils from '../../../ObjectUtils'; -import { _t } from '../../../languageHandler'; +import { _t, _tJsx} from '../../../languageHandler'; module.exports = React.createClass({ @@ -78,7 +78,7 @@ module.exports = React.createClass({ fileDropTarget = (
+ title={_t("Drop File Here")}>
{_t("Drop file here to upload")} @@ -95,9 +95,14 @@ module.exports = React.createClass({ } else { joinText = ( - Join as { this.onConferenceNotificationClick(event, 'voice');}} - href="#">voice or { this.onConferenceNotificationClick(event, 'video'); }} - href="#">video. + {_tJsx( + "Join as voice or video.", + [/(.*?)<\/a>/, /(.*?)<\/a>/], + [ + (sub) => { this.onConferenceNotificationClick(event, 'voice');}} href="#">{sub}, + (sub) => { this.onConferenceNotificationClick(event, 'video');}} href="#">{sub}, + ] + )} ); } diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js index 71e8fb0be7..015b7b4603 100644 --- a/src/components/views/rooms/EntityTile.js +++ b/src/components/views/rooms/EntityTile.js @@ -21,6 +21,7 @@ var React = require('react'); var MatrixClientPeg = require('../../../MatrixClientPeg'); var sdk = require('../../../index'); import AccessibleButton from '../elements/AccessibleButton'; +import { _t } from '../../../languageHandler'; var PRESENCE_CLASS = { @@ -140,10 +141,10 @@ module.exports = React.createClass({ var power; var powerLevel = this.props.powerLevel; if (powerLevel >= 50 && powerLevel < 99) { - power = Mod; + power = {_t("Moderator")}/; } if (powerLevel >= 99) { - power = Admin; + power = {_t("Admin")}/; } diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index e527f53170..80f062aef7 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -487,22 +487,22 @@ module.exports = WithMatrixClient(React.createClass({ let e2e; // cosmetic padlocks: if ((e2eEnabled && this.props.eventSendStatus) || this.props.mxEvent.getType() === 'm.room.encryption') { - e2e = Encrypted by verified device; + e2e = {_t("Encrypted; } // real padlocks else if (this.props.mxEvent.isEncrypted() || (e2eEnabled && this.props.eventSendStatus)) { if (this.props.mxEvent.getContent().msgtype === 'm.bad.encrypted') { - e2e = Undecryptable; + e2e = {_t("Undecryptable")}; } else if (this.state.verified == true || (e2eEnabled && this.props.eventSendStatus)) { - e2e = Encrypted by verified device; + e2e = {_t("Encrypted; } else { - e2e = Encrypted by unverified device; + e2e = {_t("Encrypted; } } else if (e2eEnabled) { - e2e = Unencrypted message; + e2e = {_t("Unencrypted; } const timestamp = this.props.mxEvent.getTs() ? : null; diff --git a/src/components/views/rooms/MemberDeviceInfo.js b/src/components/views/rooms/MemberDeviceInfo.js index af44bf7f99..33b919835c 100644 --- a/src/components/views/rooms/MemberDeviceInfo.js +++ b/src/components/views/rooms/MemberDeviceInfo.js @@ -26,19 +26,19 @@ export default class MemberDeviceInfo extends React.Component { if (this.props.device.isBlocked()) { indicator = (
- Blacklisted + {_t("Blacklisted")}/
); } else if (this.props.device.isVerified()) { indicator = (
- Verified + {_t("Verified")}/
); } else { indicator = (
- Unverified + {_t("Unverified")}/
); } diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index 86d39f91ec..0c66dd4f11 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -378,7 +378,7 @@ module.exports = WithMatrixClient(React.createClass({ var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog"); Modal.createDialog(NeedToRegisterDialog, { title: _t("Please Register"), - description: _t("This action cannot be performed by a guest user. Please register to be able to do this") + ".", + description: _t("This action cannot be performed by a guest user. Please register to be able to do this."), }); } else { console.error("Toggle moderator error:" + err); @@ -436,7 +436,7 @@ module.exports = WithMatrixClient(React.createClass({ title: _t("Warning!"), description:
- { _t("You will not be able to undo this change as you are promoting the user to have the same power level as yourself") }.
+ { _t("You will not be able to undo this change as you are promoting the user to have the same power level as yourself.") }
{ _t("Are you sure?") }
, button: _t("Continue"), @@ -705,7 +705,7 @@ module.exports = WithMatrixClient(React.createClass({ if (kickButton || banButton || muteButton || giveModButton) { adminTools =
-

Admin tools

+

{_t("Admin tools")}

{muteButton} @@ -743,7 +743,7 @@ module.exports = WithMatrixClient(React.createClass({ { this.props.member.userId }
- { _t("Level") }: + { _t("Level:") }
- {files[i].name || 'Attachment'} + {files[i].name || _t('Attachment')} ); } @@ -291,7 +291,7 @@ export default class MessageComposer extends React.Component { const formattingButton = (  { _t("(~%(searchCount)s results)", { searchCount: this.props.searchInfo.searchCount }) }
; + searchStatus =
 { _t("(~%(count)s results)", { count: this.props.searchInfo.searchCount }) }
; } // XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'... @@ -288,7 +288,7 @@ module.exports = React.createClass({ var settings_button; if (this.props.onSettingsClick) { settings_button = - + ; } diff --git a/src/components/views/rooms/RoomNameEditor.js b/src/components/views/rooms/RoomNameEditor.js index 773b713584..0fc2d1669c 100644 --- a/src/components/views/rooms/RoomNameEditor.js +++ b/src/components/views/rooms/RoomNameEditor.js @@ -19,6 +19,7 @@ limitations under the License. var React = require('react'); var sdk = require('../../../index'); var MatrixClientPeg = require('../../../MatrixClientPeg'); +import { _t } from '../../../languageHandler'; module.exports = React.createClass({ displayName: 'RoomNameEditor', @@ -35,8 +36,8 @@ module.exports = React.createClass({ this._initialName = name ? name.getContent().name : ''; - this._placeholderName = "Unnamed Room"; - if (defaultName && defaultName !== 'Empty room') { + this._placeholderName = _t("Unnamed Room"); + if (defaultName && defaultName !== 'Empty room') { // default name from JS SDK, needs no translation as we don't ever show it. this._placeholderName += " (" + defaultName + ")"; } }, diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index b20b2ef58e..8aa1f353a6 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -21,7 +21,7 @@ var React = require('react'); var sdk = require('../../../index'); var MatrixClientPeg = require('../../../MatrixClientPeg'); -import { _t } from '../../../languageHandler'; +import { _t, _tJsx } from '../../../languageHandler'; module.exports = React.createClass({ displayName: 'RoomPreviewBar', @@ -84,7 +84,7 @@ module.exports = React.createClass({ }, _roomNameElement: function(fallback) { - fallback = fallback || 'a room'; + fallback = fallback || _t('a room'); const name = this.props.room ? this.props.room.name : (this.props.room_alias || ""); return name ? name : fallback; }, @@ -114,8 +114,7 @@ module.exports = React.createClass({ if (this.props.invitedEmail) { if (this.state.threePidFetchError) { emailMatchBlock =
- Unable to ascertain that the address this invite was - sent to matches one associated with your account. + {_t("Unable to ascertain that the address this invite was sent to matches one associated with your account.")}
; } else if (this.state.invitedEmailMxid != MatrixClientPeg.get().credentials.userId) { emailMatchBlock = @@ -124,28 +123,35 @@ module.exports = React.createClass({ /!\\
- This invitation was sent to {this.props.invitedEmail}, which is not associated with this account.
- You may wish to login with a different account, or add this email to this account. + {_t("This invitation was sent to an email address which is not associated with this account:")} + {this.props.invitedEmail} +
+ {_t("You may wish to login with a different account, or add this email to this account.")}
; } } - // TODO: find a way to respect HTML in counterpart! joinBlock = (
{ _t('You have been invited to join this room by %(inviterName)s', {inviterName: this.props.inviterName}) }
- { _t('Would you like to') } { _t('accept') } { _t('or') } { _t('decline') } { _t('this invitation?') } + { _tJsx( + 'Would you like to accept or decline this invitation?', + [/(.*?)<\/a>/, /(.*?)<\/a>/], + [ + (sub) => {sub}, + (sub) => {sub} + ] + )}
{emailMatchBlock}
); } else if (kicked || banned) { - const verb = kicked ? 'kicked' : 'banned'; - const roomName = this._roomNameElement('this room'); + const roomName = this._roomNameElement(_t('This room')); const kickerMember = this.props.room.currentState.getMember( myMember.events.member.getSender() ); @@ -153,29 +159,39 @@ module.exports = React.createClass({ kickerMember.name : myMember.events.member.getSender(); let reason; if (myMember.events.member.getContent().reason) { - reason =
Reason: {myMember.events.member.getContent().reason}
+ reason =
{_t("Reason: %(reasonText)s", {reasonText: myMember.events.member.getContent().reason})}
} let rejoinBlock; if (!banned) { - rejoinBlock = ; + rejoinBlock = ; } + + let actionText; + if (kicked) { + actionText = _t("You have been kicked from %(roomName)s by %(userName)s.", {roomName: roomName, userName: kickerName}); + } + else if (banned) { + actionText = _t("You have been banned from %(roomName)s by %(userName)s.", {roomName: roomName, userName: kickerName}); + } // no other options possible due to the kicked || banned check above. + joinBlock = (
- You have been {verb} from {roomName} by {kickerName}.
+ {actionText} +
{reason} {rejoinBlock} - Forget + {_t("Forget room")}
); } else if (this.props.error) { - var name = this.props.roomAlias || "This room"; + var name = this.props.roomAlias || _t("This room"); var error; if (this.props.error.errcode == 'M_NOT_FOUND') { - error = name + " does not exist"; + error = _t("%(roomName)s does not exist.", {roomName: name}); } else { - error = name + " is not accessible at this time"; + error = _t("%(roomName)s is not accessible at this time.", {roomName: name}); } joinBlock = (
@@ -189,8 +205,12 @@ module.exports = React.createClass({ joinBlock = (
- { _t('You are trying to access %(roomName)s', {roomName: name}) }.
- { _t('Click here') } { _t('to join the discussion') }! + { _t('You are trying to access %(roomName)s.', {roomName: name}) } +
+ { _tJsx("Click here to join the discussion!", + /(.*?)<\/a>/, + (sub) => {sub} + )}
); diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index 205f614ba2..f31fc68afc 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -17,7 +17,7 @@ limitations under the License. import q from 'q'; import React from 'react'; -import { _t } from '../../../languageHandler'; +import { _t, _tJsx } from '../../../languageHandler'; import MatrixClientPeg from '../../../MatrixClientPeg'; import SdkConfig from '../../../SdkConfig'; import sdk from '../../../index'; @@ -46,7 +46,7 @@ const BannedUser = React.createClass({ const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog"); Modal.createDialog(ConfirmUserActionDialog, { member: this.props.member, - action: 'Unban', + action: _t('Unban'), danger: false, onFinished: (proceed) => { if (!proceed) return; @@ -597,7 +597,7 @@ module.exports = React.createClass({ ? : } - { isEncrypted ? "Encryption is enabled in this room" : "Encryption is not enabled in this room" }. + { isEncrypted ? _t("Encryption is enabled in this room") : _t("Encryption is not enabled in this room") }. { settings }
@@ -653,7 +653,7 @@ module.exports = React.createClass({ {Object.keys(user_levels).map(function(user, i) { return (
  • - { user } { _t('is a') } + { _t("%(user)s is a", {user: user}) }
  • ); })} @@ -754,7 +754,11 @@ module.exports = React.createClass({ if (this.state.join_rule === "public" && aliasCount == 0) { addressWarning =
    - { _t('To link to a room it must have') } { _t('an address') }. + { _tJsx( + 'To link to a room it must have an address.', + /(.*?)<\/a>/, + (sub) => {sub} + )}
    ; } diff --git a/src/components/views/rooms/SimpleRoomHeader.js b/src/components/views/rooms/SimpleRoomHeader.js index a6f342af86..44ec7c29aa 100644 --- a/src/components/views/rooms/SimpleRoomHeader.js +++ b/src/components/views/rooms/SimpleRoomHeader.js @@ -20,6 +20,7 @@ import React from 'react'; import dis from '../../../dispatcher'; import AccessibleButton from '../elements/AccessibleButton'; import sdk from '../../../index'; +import { _t } from '../../../languageHandler'; // cancel button which is shared between room header and simple room header export function CancelButton(props) { @@ -28,7 +29,7 @@ export function CancelButton(props) { return ( Cancel + width="18" height="18" alt={_t("Cancel")}/> ); } diff --git a/src/components/views/rooms/TopUnreadMessagesBar.js b/src/components/views/rooms/TopUnreadMessagesBar.js index 45aba66633..aa1f86483e 100644 --- a/src/components/views/rooms/TopUnreadMessagesBar.js +++ b/src/components/views/rooms/TopUnreadMessagesBar.js @@ -41,7 +41,7 @@ module.exports = React.createClass({
    Close
    ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index de1adc539d..6026298cd6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -120,8 +120,8 @@ "zh-tw":"Chinese (Taiwan)", "zu":"Zulu", "A registered account is required for this action": "A registered account is required for this action", + "a room": "a room", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains", - "accept": "accept", "Accept": "Accept", "%(targetName)s accepted an invitation.": "%(targetName)s accepted an invitation.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s accepted the invitation for %(displayName)s.", @@ -133,6 +133,7 @@ "Add email address": "Add email address", "Add phone number": "Add phone number", "Admin": "Admin", + "Admin tools": "Admin tools", "And %(count)s more...": "And %(count)s more...", "VoIP": "VoIP", "Missing Media Permissions, click here to request.": "Missing Media Permissions, click here to request.", @@ -152,7 +153,6 @@ "all room members": "all room members", "all room members, from the point they are invited": "all room members, from the point they are invited", "all room members, from the point they joined": "all room members, from the point they joined", - "an address": "an address", "and": "and", "%(items)s and %(remaining)s others": "%(items)s and %(remaining)s others", "%(items)s and one other": "%(items)s and one other", @@ -201,13 +201,14 @@ "Claimed Ed25519 fingerprint key": "Claimed Ed25519 fingerprint key", "Clear Cache and Reload": "Clear Cache and Reload", "Clear Cache": "Clear Cache", - "Click here": "Click here", + "Click here to join the discussion!": "Click here to join the discussion!", "Click here to fix": "Click here to fix", "Click to mute audio": "Click to mute audio", "Click to mute video": "Click to mute video", "click to reveal": "click to reveal", "Click to unmute video": "Click to unmute video", "Click to unmute audio": "Click to unmute audio", + "Close": "Close", "Command error": "Command error", "Commands": "Commands", "Conference call failed.": "Conference call failed.", @@ -234,7 +235,6 @@ "Deactivate Account": "Deactivate Account", "Deactivate my account": "Deactivate my account", "Decline": "Decline", - "decline": "decline", "Decrypt %(text)s": "Decrypt %(text)s", "Decryption error": "Decryption error", "(default: %(userName)s)": "(default: %(userName)s)", @@ -260,6 +260,7 @@ "Displays action": "Displays action", "Don't send typing notifications": "Don't send typing notifications", "Download %(text)s": "Download %(text)s", + "Drop File Here": "Drop File Here", "Drop here %(toAction)s": "Drop here %(toAction)s", "Drop here to tag %(section)s": "Drop here to tag %(section)s", "Ed25519 fingerprint": "Ed25519 fingerprint", @@ -271,8 +272,12 @@ "Enable encryption": "Enable encryption", "Enable Notifications": "Enable Notifications", "enabled": "enabled", + "Encrypted by a verified device": "Encrypted by a verified device", + "Encrypted by an unverified device": "Encrypted by an unverified device", "Encrypted messages will not be visible on clients that do not yet implement encryption": "Encrypted messages will not be visible on clients that do not yet implement encryption", "Encrypted room": "Encrypted room", + "Encryption is enabled in this room": "Encryption is enabled in this room", + "Encryption is not enabled in this room": "Encryption is not enabled in this room", "%(senderName)s ended the call.": "%(senderName)s ended the call.", "End-to-end encryption information": "End-to-end encryption information", "End-to-end encryption is in beta and may not be reliable": "End-to-end encryption is in beta and may not be reliable", @@ -354,11 +359,11 @@ "Invited": "Invited", "Invites": "Invites", "Invites user with given id to current room": "Invites user with given id to current room", - "is a": "is a", "'%(alias)s' is not a valid format for an address": "'%(alias)s' is not a valid format for an address", "'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias", "%(displayName)s is typing": "%(displayName)s is typing", "Sign in with": "Sign in with", + "Join as voice or video.": "Join as voice or video.", "Join Room": "Join Room", "joined and left": "joined and left", "joined": "joined", @@ -374,7 +379,7 @@ "left and rejoined": "left and rejoined", "left": "left", "%(targetName)s left the room.": "%(targetName)s left the room.", - "Level": "Level", + "Level:": "Level:", "List this room in %(domain)s's room directory?": "List this room in %(domain)s's room directory?", "Local addresses for this room:": "Local addresses for this room:", "Logged in as:": "Logged in as:", @@ -441,6 +446,7 @@ "Profile": "Profile", "Public Chat": "Public Chat", "Reason": "Reason", + "Reason: %(reasonText)s": "Reason: %(reasonText)s", "Revoke Moderator": "Revoke Moderator", "Refer a friend to Riot:": "Refer a friend to Riot:", "Register": "Register", @@ -448,6 +454,7 @@ "rejected": "rejected", "%(targetName)s rejected the invitation.": "%(targetName)s rejected the invitation.", "Reject invitation": "Reject invitation", + "Rejoin": "Rejoin", "Remote addresses for this room:": "Remote addresses for this room:", "Remove Contact Information?": "Remove Contact Information?", "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s removed their display name (%(oldDisplayName)s).", @@ -468,6 +475,8 @@ "Room Colour": "Room Colour", "Room contains unknown devices": "Room contains unknown devices", "Room name (optional)": "Room name (optional)", + "%(roomName)s does not exist.": "%(roomName)s does not exist.", + "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", "Rooms": "Rooms", "Save": "Save", "Saving room color settings is only available to registered users": "Saving room color settings is only available to registered users", @@ -477,6 +486,7 @@ "Search failed": "Search failed", "Searches DuckDuckGo for results": "Searches DuckDuckGo for results", "Searching known users": "Searching known users", + "Seen by %(userName)s at %(dateTime)s": "Seen by %(userName)s at %(dateTime)s", "Send a message (unencrypted)": "Send a message (unencrypted)", "Send an encrypted message": "Send an encrypted message", "Send anyway": "Send anyway", @@ -500,6 +510,7 @@ "Setting a user name will create a fresh account": "Setting a user name will create a fresh account", "Settings": "Settings", "Show panel": "Show panel", + "Show Text Formatting Toolbar": "Show Text Formatting Toolbar", "Show timestamps in 12 hour format (e.g. 2:30pm)": "Show timestamps in 12 hour format (e.g. 2:30pm)", "Signed Out": "Signed Out", "Sign in": "Sign in", @@ -522,7 +533,7 @@ "The main address for this room is": "The main address for this room is", "The phone number entered looks invalid": "The phone number entered looks invalid", "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.", - "This action cannot be performed by a guest user. Please register to be able to do this": "This action cannot be performed by a guest user. Please register to be able to do this", + "This action cannot be performed by a guest user. Please register to be able to do this.": "This action cannot be performed by a guest user. Please register to be able to do this.", "This email address is already in use": "This email address is already in use", "This email address was not found": "This email address was not found", "%(actionVerb)s this person?": "%(actionVerb)s this person?", @@ -531,6 +542,7 @@ "The file '%(fileName)s' failed to upload": "The file '%(fileName)s' failed to upload", "The remote side failed to pick up": "The remote side failed to pick up", "This Home Server does not support login using email address.": "This Home Server does not support login using email address.", + "This invitation was sent to an email address which is not associated with this account:": "This invitation was sent to an email address which is not associated with this account:", "There was a problem logging in.": "There was a problem logging in.", "This room has no local addresses": "This room has no local addresses", "This room is not recognised.": "This room is not recognised.", @@ -538,9 +550,9 @@ "These are experimental features that may break in unexpected ways": "These are experimental features that may break in unexpected ways", "The visibility of existing history will be unchanged": "The visibility of existing history will be unchanged", "This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address", - "this invitation?": "this invitation?", "This is a preview of this room. Room interactions have been disabled": "This is a preview of this room. Room interactions have been disabled", "This phone number is already in use": "This phone number is already in use", + "This room": "This room", "This room is not accessible by remote Matrix servers": "This room is not accessible by remote Matrix servers", "This room's internal ID is": "This room's internal ID is", "times": "times", @@ -550,9 +562,8 @@ "to demote": "to demote", "to favourite": "to favourite", "To invite users into the room": "To invite users into the room", - "to join the discussion": "to join the discussion", "To kick users": "To kick users", - "To link to a room it must have": "To link to a room it must have", + "To link to a room it must have an address.": "To link to a room it must have an address.", "to make a room or": "to make a room or", "To remove other users' messages": "To remove other users' messages", "To reset your password, enter the email address linked to your account": "To reset your password, enter the email address linked to your account", @@ -574,11 +585,14 @@ "Unable to verify email address.": "Unable to verify email address.", "Unban": "Unban", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s unbanned %(targetName)s.", + "Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Unable to ascertain that the address this invite was sent to matches one associated with your account.", "Unable to capture screen": "Unable to capture screen", "Unable to enable Notifications": "Unable to enable Notifications", "Unable to load device list": "Unable to load device list", + "Undecryptable": "Undecryptable", "Unencrypted room": "Unencrypted room", "unencrypted": "unencrypted", + "Unencrypted message": "Unencrypted message", "unknown caller": "unknown caller", "Unknown command": "Unknown command", "unknown device": "unknown device", @@ -587,8 +601,10 @@ "Unknown (user, device) pair:": "Unknown (user, device) pair:", "unknown": "unknown", "Unmute": "Unmute", + "Unnamed Room": "Unnamed Room", "Unrecognised command:": "Unrecognised command:", "Unrecognised room alias:": "Unrecognised room alias:", + "Unverified": "Unverified", "Uploading %(filename)s and %(count)s others": { "zero": "Uploading %(filename)s", "one": "Uploading %(filename)s and %(count)s other", @@ -605,12 +621,15 @@ "Use with caution": "Use with caution", "User ID": "User ID", "User Interface": "User Interface", + "%(user)s is a": "%(user)s is a", "User name": "User name", + "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)", "Users": "Users", "User": "User", "Verification Pending": "Verification Pending", "Verification": "Verification", "verified": "verified", + "Verified": "Verified", "Verified key": "Verified key", "Video call": "Video call", "Voice call": "Voice call", @@ -626,20 +645,23 @@ "Who would you like to add to this room?": "Who would you like to add to this room?", "Who would you like to communicate with?": "Who would you like to communicate with?", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.", - "Would you like to": "Would you like to", + "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?". "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", "You are already in a call.": "You are already in a call.", "You're not in any rooms yet! Press": "You're not in any rooms yet! Press", - "You are trying to access %(roomName)s": "You are trying to access %(roomName)s", + "You are trying to access %(roomName)s.": "You are trying to access %(roomName)s.", "You cannot place a call with yourself.": "You cannot place a call with yourself.", "You cannot place VoIP calls in this browser.": "You cannot place VoIP calls in this browser.", "You do not have permission to post to this room": "You do not have permission to post to this room", + "You have been banned from %(roomName)s by %(userName)s.": "You have been banned from %(roomName)s by %(userName)s.", "You have been invited to join this room by %(inviterName)s": "You have been invited to join this room by %(inviterName)s", + "You have been kicked from %(roomName)s by %(userName)s.": "You have been kicked from %(roomName)s by %(userName)s.", "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device", "You have disabled URL previews by default.": "You have disabled URL previews by default.", "You have enabled URL previews by default.": "You have enabled URL previews by default.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "You have entered an invalid contact. Try using their Matrix ID or email address.", "You have no visible notifications": "You have no visible notifications", + "You may wish to login with a different account, or add this email to this account.": "You may wish to login with a different account, or add this email to this account.", "you must be a": "you must be a", "You must register to use this functionality": "You must register to use this functionality", "You need to be able to invite users to do that.": "You need to be able to invite users to do that.", @@ -652,7 +674,7 @@ "You seem to be in a call, are you sure you want to quit?": "You seem to be in a call, are you sure you want to quit?", "You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?", "You should not yet trust it to secure data": "You should not yet trust it to secure data", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.", "Your home server does not support device management.": "Your home server does not support device management.", "Sun": "Sun", "Mon": "Mon", @@ -700,7 +722,10 @@ "Sent messages will be stored until your connection has returned.": "Sent messages will be stored until your connection has returned.", "Auto-complete": "Auto-complete", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Resend all or cancel all now. You can also select individual messages to resend or cancel.", - "(~%(searchCount)s results)": "(~%(searchCount)s results)", + "(~%(count)s results)": { + "one": "(~%(count)s result)", + "other": "(~%(count)s results)" + }, "Cancel": "Cancel", "or": "or", "Active call": "Active call", From 8479a8f5ffc5e3aeaa2547fe007ebcaab3916437 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 8 Jun 2017 14:11:34 +0100 Subject: [PATCH 204/275] Update .eslintignore.errorfiles --- .eslintignore.errorfiles | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.eslintignore.errorfiles b/.eslintignore.errorfiles index f1b63d7367..dedde7e07d 100644 --- a/.eslintignore.errorfiles +++ b/.eslintignore.errorfiles @@ -2,6 +2,8 @@ src/AddThreepid.js src/async-components/views/dialogs/EncryptedEventDialog.js +src/async-components/views/dialogs/ExportE2eKeysDialog.js +src/async-components/views/dialogs/ImportE2eKeysDialog.js src/autocomplete/AutocompleteProvider.js src/autocomplete/Autocompleter.js src/autocomplete/Components.js @@ -165,6 +167,7 @@ src/UserActivity.js src/utils/DecryptFile.js src/utils/DMRoomMap.js src/utils/FormattingUtils.js +src/utils/MegolmExportEncryption.js src/utils/MultiInviter.js src/utils/Receipt.js src/Velociraptor.js @@ -185,3 +188,4 @@ test/mock-clock.js test/skinned-sdk.js test/stores/RoomViewStore-test.js test/test-utils.js +test/utils/MegolmExportEncryption-test.js From 6d1fa775a04c24b37bf81524f1eb03516176e62e Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 14:14:45 +0100 Subject: [PATCH 205/275] Formatting --- src/components/structures/login/Login.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index 840f0874a7..be440febdc 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -219,8 +219,8 @@ module.exports = React.createClass({ if (err.cors === 'rejected') { if (window.location.protocol === 'https:' && (this.state.enteredHomeserverUrl.startsWith("http:") || - !this.state.enteredHomeserverUrl.startsWith("http"))) - { + !this.state.enteredHomeserverUrl.startsWith("http")) + ) { errorText = { _tJsx("Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. " + "Either use HTTPS or enable unsafe scripts.", @@ -228,8 +228,7 @@ module.exports = React.createClass({ (sub) => { return { sub }; } )} ; - } - else { + } else { errorText = { _tJsx("Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.", /(.*?)<\/a>/, From d3cf78ff5abd3297cb1f51a3017d5236db114af5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 14:17:49 +0100 Subject: [PATCH 206/275] Control currently viewied event via RoomViewStore Fix for https://github.com/vector-im/riot-web/issues/4224 Due to the way `MatrixChat` does a state update when the `view_room` dispatch fires and a second update when `RoomViewStore` sends an update, the current event ID and room ID were becoming out of sync. The solution devised was to have the event ID managed by the `RoomViewStore` itself and do any defaulting there (for when we revisit a room that we saved scroll state for previously). This required a few changes: - The addition of `update_scroll_state` in `RoomViewStore` allows the `RoomView` to save scroll state for a room before swapping to another one. Previously the caching of scroll state was done in `RoomView`. - The `view_room` dispatch now accepts an `event_id`, which dictates which event is supposed to be scrolled to in the `MessagePanel` when a new room is viewed. It also accepts `event_offset`, but currently, this isn't passed in by a dispatch in the app, but it is clobbered when loading the default position when an `event_id` isn't specified. Finally, `highlighted` was added to distinguish whether the initial event being scrolled to is also highlighted. This flag is also used by `viewRoom` in `MatrixChat` in order to decide whether to `notifyNewScreen` with the specified `event_id`. --- src/components/structures/LoggedInView.js | 2 - src/components/structures/MatrixChat.js | 19 +---- src/components/structures/RoomView.js | 93 +++++++++-------------- src/components/views/rooms/EventTile.js | 1 + src/stores/RoomViewStore.js | 72 +++++++++++++++++- 5 files changed, 109 insertions(+), 78 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index a201a0bea7..8fa35e84d7 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -223,10 +223,8 @@ export default React.createClass({ ref='roomView' autoJoin={this.props.autoJoin} onRegistered={this.props.onRegistered} - eventId={this.props.initialEventId} thirdPartyInvite={this.props.thirdPartyInvite} oobData={this.props.roomOobData} - highlightedEventId={this.props.highlightedEventId} eventPixelOffset={this.props.initialEventPixelOffset} key={this.props.currentRoomId || 'roomview'} opacity={this.props.middleOpacity} diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index efb2b38d6e..b65fa0be1c 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -618,9 +618,6 @@ module.exports = React.createClass({ this.focusComposer = true; const newState = { - initialEventId: roomInfo.event_id, - highlightedEventId: roomInfo.event_id, - initialEventPixelOffset: undefined, page_type: PageTypes.RoomView, thirdPartyInvite: roomInfo.third_party_invite, roomOobData: roomInfo.oob_data, @@ -632,18 +629,6 @@ module.exports = React.createClass({ newState.currentRoomId = roomInfo.room_id; } - // if we aren't given an explicit event id, look for one in the - // scrollStateMap. - // - // TODO: do this in RoomView rather than here - if (!roomInfo.event_id && this.refs.loggedInView) { - const scrollState = this.refs.loggedInView.getScrollStateForRoom(roomInfo.room_id); - if (scrollState) { - newState.initialEventId = scrollState.focussedEvent; - newState.initialEventPixelOffset = scrollState.pixelOffset; - } - } - // Wait for the first sync to complete so that if a room does have an alias, // it would have been retrieved. let waitFor = q(null); @@ -669,7 +654,7 @@ module.exports = React.createClass({ } } - if (roomInfo.event_id) { + if (roomInfo.event_id && roomInfo.highlighted) { presentedId += "/" + roomInfo.event_id; } this.notifyNewScreen('room/' + presentedId); @@ -1124,8 +1109,10 @@ module.exports = React.createClass({ }; const payload = { + id: '#mylovelyid', action: 'view_room', event_id: eventId, + highlighted: Boolean(eventId), third_party_invite: thirdPartyInvite, oob_data: oobData, }; diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index df21715d75..a4c589187b 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -83,36 +83,8 @@ module.exports = React.createClass({ // * invited us tovthe room oobData: React.PropTypes.object, - // id of an event to jump to. If not given, will go to the end of the - // live timeline. - eventId: React.PropTypes.string, - - // where to position the event given by eventId, in pixels from the - // bottom of the viewport. If not given, will try to put the event - // 1/3 of the way down the viewport. - eventPixelOffset: React.PropTypes.number, - - // ID of an event to highlight. If undefined, no event will be highlighted. - // Typically this will either be the same as 'eventId', or undefined. - highlightedEventId: React.PropTypes.string, - // is the RightPanel collapsed? collapsedRhs: React.PropTypes.bool, - - // a map from room id to scroll state, which will be updated on unmount. - // - // If there is no special scroll state (ie, we are following the live - // timeline), the scroll state is null. Otherwise, it is an object with - // the following properties: - // - // focussedEvent: the ID of the 'focussed' event. Typically this is - // the last event fully visible in the viewport, though if we - // have done an explicit scroll to an explicit event, it will be - // that event. - // - // pixelOffset: the number of pixels the window is scrolled down - // from the focussedEvent. - scrollStateMap: React.PropTypes.object, }, getInitialState: function() { @@ -180,13 +152,28 @@ module.exports = React.createClass({ if (this.unmounted) { return; } - this.setState({ + const newState = { roomId: RoomViewStore.getRoomId(), roomAlias: RoomViewStore.getRoomAlias(), roomLoading: RoomViewStore.isRoomLoading(), roomLoadError: RoomViewStore.getRoomLoadError(), joining: RoomViewStore.isJoining(), - }, () => { + eventId: RoomViewStore.getEventId(), + eventPixelOffset: RoomViewStore.getEventPixelOffset(), + isEventHighlighted: RoomViewStore.isEventHighlighted(), + }; + + if (this.state.eventId !== newState.eventId) { + newState.searchResults = null; + } + + // Store the scroll state for the previous room so that we can return to this + // position when viewing this room in future. + if (this.state.roomId !== newState.roomId) { + this._updateScrollMap(this.state.roomId); + } + + this.setState(newState, () => { this._onHaveRoom(); this.onRoom(MatrixClientPeg.get().getRoom(this.state.roomId)); }); @@ -287,13 +274,6 @@ module.exports = React.createClass({ } }, - componentWillReceiveProps: function(newProps) { - if (newProps.eventId != this.props.eventId) { - // when we change focussed event id, hide the search results. - this.setState({searchResults: null}); - } - }, - shouldComponentUpdate: function(nextProps, nextState) { return (!ObjectUtils.shallowEqual(this.props, nextProps) || !ObjectUtils.shallowEqual(this.state, nextState)); @@ -319,7 +299,7 @@ module.exports = React.createClass({ this.unmounted = true; // update the scroll map before we get unmounted - this._updateScrollMap(); + this._updateScrollMap(this.state.roomId); if (this.refs.roomView) { // disconnect the D&D event listeners from the room view. This @@ -598,6 +578,14 @@ module.exports = React.createClass({ }); }, + _updateScrollMap(roomId) { + dis.dispatch({ + action: 'update_scroll_state', + room_id: roomId, + scroll_state: this._getScrollState(), + }); + }, + onRoom: function(room) { if (!room || room.roomId !== this.state.roomId) { return; @@ -1240,21 +1228,6 @@ module.exports = React.createClass({ } }, - // update scrollStateMap on unmount - _updateScrollMap: function() { - if (!this.state.room) { - // we were instantiated on a room alias and haven't yet joined the room. - return; - } - if (!this.props.scrollStateMap) return; - - var roomId = this.state.room.roomId; - - var state = this._getScrollState(); - this.props.scrollStateMap[roomId] = state; - }, - - // get the current scroll position of the room, so that it can be // restored when we switch back to it. // @@ -1677,6 +1650,14 @@ module.exports = React.createClass({ hideMessagePanel = true; } + const shouldHighlight = this.state.isEventHighlighted; + let highlightedEventId = null; + if (this.state.forwardingEvent) { + highlightedEventId = this.state.forwardingEvent.getId(); + } else if (shouldHighlight) { + highlightedEventId = this.state.eventId; + } + // console.log("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview); var messagePanel = (
    diff --git a/src/async-components/views/dialogs/ImportE2eKeysDialog.js b/src/async-components/views/dialogs/ImportE2eKeysDialog.js index 61d2aeec74..91010d33b9 100644 --- a/src/async-components/views/dialogs/ImportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/ImportE2eKeysDialog.js @@ -122,13 +122,13 @@ export default React.createClass({ 'This process allows you to import encryption keys ' + 'that you had previously exported from another Matrix ' + 'client. You will then be able to decrypt any ' + - 'messages that the other client could decrypt.' + 'messages that the other client could decrypt.', ) }

    { _t( 'The export file will be protected with a passphrase. ' + - 'You should enter the passphrase here, to decrypt the file.' + 'You should enter the passphrase here, to decrypt the file.', ) }

    diff --git a/src/utils/MegolmExportEncryption.js b/src/utils/MegolmExportEncryption.js index c98c467e1c..de39ea71cc 100644 --- a/src/utils/MegolmExportEncryption.js +++ b/src/utils/MegolmExportEncryption.js @@ -32,7 +32,7 @@ const subtleCrypto = window.crypto.subtle || window.crypto.webkitSubtle; /** * Decrypt a megolm key file * - * @param {ArrayBuffer} file + * @param {ArrayBuffer} data file to decrypt * @param {String} password * @return {Promise} promise for decrypted output */ @@ -61,12 +61,12 @@ export function decryptMegolmKeyFile(data, password) { const hmac = body.subarray(-32); return deriveKeys(salt, iterations, password).then((keys) => { - const [aes_key, hmac_key] = keys; + const [aesKey, hmacKey] = keys; const toVerify = body.subarray(0, -32); return subtleCrypto.verify( {name: 'HMAC'}, - hmac_key, + hmacKey, hmac, toVerify, ).then((isValid) => { @@ -80,7 +80,7 @@ export function decryptMegolmKeyFile(data, password) { counter: iv, length: 64, }, - aes_key, + aesKey, ciphertext, ); }); @@ -102,7 +102,7 @@ export function decryptMegolmKeyFile(data, password) { */ export function encryptMegolmKeyFile(data, password, options) { options = options || {}; - const kdf_rounds = options.kdf_rounds || 500000; + const kdfRounds = options.kdf_rounds || 500000; const salt = new Uint8Array(16); window.crypto.getRandomValues(salt); @@ -115,8 +115,8 @@ export function encryptMegolmKeyFile(data, password, options) { // of a single bit of iv is a price we have to pay. iv[9] &= 0x7f; - return deriveKeys(salt, kdf_rounds, password).then((keys) => { - const [aes_key, hmac_key] = keys; + return deriveKeys(salt, kdfRounds, password).then((keys) => { + const [aesKey, hmacKey] = keys; return subtleCrypto.encrypt( { @@ -124,7 +124,7 @@ export function encryptMegolmKeyFile(data, password, options) { counter: iv, length: 64, }, - aes_key, + aesKey, new TextEncoder().encode(data), ).then((ciphertext) => { const cipherArray = new Uint8Array(ciphertext); @@ -134,17 +134,17 @@ export function encryptMegolmKeyFile(data, password, options) { resultBuffer[idx++] = 1; // version resultBuffer.set(salt, idx); idx += salt.length; resultBuffer.set(iv, idx); idx += iv.length; - resultBuffer[idx++] = kdf_rounds >> 24; - resultBuffer[idx++] = (kdf_rounds >> 16) & 0xff; - resultBuffer[idx++] = (kdf_rounds >> 8) & 0xff; - resultBuffer[idx++] = kdf_rounds & 0xff; + resultBuffer[idx++] = kdfRounds >> 24; + resultBuffer[idx++] = (kdfRounds >> 16) & 0xff; + resultBuffer[idx++] = (kdfRounds >> 8) & 0xff; + resultBuffer[idx++] = kdfRounds & 0xff; resultBuffer.set(cipherArray, idx); idx += cipherArray.length; const toSign = resultBuffer.subarray(0, idx); return subtleCrypto.sign( {name: 'HMAC'}, - hmac_key, + hmacKey, toSign, ).then((hmac) => { hmac = new Uint8Array(hmac); @@ -170,7 +170,7 @@ function deriveKeys(salt, iterations, password) { new TextEncoder().encode(password), {name: 'PBKDF2'}, false, - ['deriveBits'] + ['deriveBits'], ).then((key) => { return subtleCrypto.deriveBits( { @@ -180,33 +180,33 @@ function deriveKeys(salt, iterations, password) { hash: 'SHA-512', }, key, - 512 + 512, ); }).then((keybits) => { const now = new Date(); console.log("E2e import/export: deriveKeys took " + (now - start) + "ms"); - const aes_key = keybits.slice(0, 32); - const hmac_key = keybits.slice(32); + const aesKey = keybits.slice(0, 32); + const hmacKey = keybits.slice(32); - const aes_prom = subtleCrypto.importKey( + const aesProm = subtleCrypto.importKey( 'raw', - aes_key, + aesKey, {name: 'AES-CTR'}, false, - ['encrypt', 'decrypt'] + ['encrypt', 'decrypt'], ); - const hmac_prom = subtleCrypto.importKey( + const hmacProm = subtleCrypto.importKey( 'raw', - hmac_key, + hmacKey, { name: 'HMAC', hash: {name: 'SHA-256'}, }, false, - ['sign', 'verify'] + ['sign', 'verify'], ); - return Promise.all([aes_prom, hmac_prom]); + return Promise.all([aesProm, hmacProm]); }); } @@ -301,7 +301,7 @@ function packMegolmKeyFile(data) { function encodeBase64(uint8Array) { // Misinterpt the Uint8Array as Latin-1. // window.btoa expects a unicode string with codepoints in the range 0-255. - var latin1String = String.fromCharCode.apply(null, uint8Array); + const latin1String = String.fromCharCode.apply(null, uint8Array); // Use the builtin base64 encoder. return window.btoa(latin1String); } @@ -313,10 +313,10 @@ function encodeBase64(uint8Array) { */ function decodeBase64(base64) { // window.atob returns a unicode string with codepoints in the range 0-255. - var latin1String = window.atob(base64); + const latin1String = window.atob(base64); // Encode the string as a Uint8Array - var uint8Array = new Uint8Array(latin1String.length); - for (var i = 0; i < latin1String.length; i++) { + const uint8Array = new Uint8Array(latin1String.length); + for (let i = 0; i < latin1String.length; i++) { uint8Array[i] = latin1String.charCodeAt(i); } return uint8Array; diff --git a/test/.eslintrc.js b/test/.eslintrc.js index 4cc4659d7d..537f989b62 100644 --- a/test/.eslintrc.js +++ b/test/.eslintrc.js @@ -2,4 +2,9 @@ module.exports = { env: { mocha: true, }, -} + + // mocha defines a 'this' + rules: { + "babel/no-invalid-this": "off", + }, +}; diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js index 1c90c7a030..2637097837 100644 --- a/test/utils/MegolmExportEncryption-test.js +++ b/test/utils/MegolmExportEncryption-test.js @@ -25,23 +25,40 @@ const TEST_VECTORS=[ [ "plain", "password", - "-----BEGIN MEGOLM SESSION DATA-----\nAXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\ncissyYBxjsfsAndErh065A8=\n-----END MEGOLM SESSION DATA-----" + "-----BEGIN MEGOLM SESSION DATA-----\n" + + "AXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" + + "cissyYBxjsfsAndErh065A8=\n" + + "-----END MEGOLM SESSION DATA-----", ], [ "Hello, World", "betterpassword", - "-----BEGIN MEGOLM SESSION DATA-----\nAW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\nKYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n-----END MEGOLM SESSION DATA-----" + "-----BEGIN MEGOLM SESSION DATA-----\n" + + "AW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" + + "KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n" + + "-----END MEGOLM SESSION DATA-----", ], [ "alphanumericallyalphanumericallyalphanumericallyalphanumerically", "SWORDFISH", - "-----BEGIN MEGOLM SESSION DATA-----\nAXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\nMgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\nPgg29363BGR+/Ripq/VCLKGNbw==\n-----END MEGOLM SESSION DATA-----" + "-----BEGIN MEGOLM SESSION DATA-----\n" + + "AXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" + + "MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\n" + + "Pgg29363BGR+/Ripq/VCLKGNbw==\n" + + "-----END MEGOLM SESSION DATA-----", ], [ "alphanumericallyalphanumericallyalphanumericallyalphanumerically", - "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword", - "-----BEGIN MEGOLM SESSION DATA-----\nAf//////////////////////////////////////////AAAD6IAZJy7IQ7Y0idqSw/bmpngEEVVh\ngsH+8ptgqxw6ZVWQnohr8JsuwH9SwGtiebZuBu5smPCO+RFVWH2cQYslZijXv/BEH/txvhUrrtCd\nbWnSXS9oymiqwUIGs08sXI33ZA==\n-----END MEGOLM SESSION DATA-----" - ] + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + + "passwordpasswordpasswordpasswordpassword", + "-----BEGIN MEGOLM SESSION DATA-----\n" + + "Af//////////////////////////////////////////AAAD6IAZJy7IQ7Y0idqSw/bmpngEEVVh\n" + + "gsH+8ptgqxw6ZVWQnohr8JsuwH9SwGtiebZuBu5smPCO+RFVWH2cQYslZijXv/BEH/txvhUrrtCd\n" + + "bWnSXS9oymiqwUIGs08sXI33ZA==\n" + + "-----END MEGOLM SESSION DATA-----", + ], ] ; @@ -55,7 +72,7 @@ describe('MegolmExportEncryption', function() { if (!window.crypto.subtle && !window.crypto.webkitSubtle) { this.skip(); } - }) + }); beforeEach(function() { testUtils.beforeEach(this); @@ -64,14 +81,14 @@ describe('MegolmExportEncryption', function() { describe('decrypt', function() { it('should handle missing header', function() { const input=stringToArray(`-----`); - expect(()=>{MegolmExportEncryption.decryptMegolmKeyFile(input, '')}) + expect(()=>MegolmExportEncryption.decryptMegolmKeyFile(input, '')) .toThrow('Header line not found'); }); it('should handle missing trailer', function() { const input=stringToArray(`-----BEGIN MEGOLM SESSION DATA----- -----`); - expect(()=>{MegolmExportEncryption.decryptMegolmKeyFile(input, '')}) + expect(()=>MegolmExportEncryption.decryptMegolmKeyFile(input, '')) .toThrow('Trailer line not found'); }); @@ -81,7 +98,7 @@ AXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx cissyYBxjsfsAn -----END MEGOLM SESSION DATA----- `); - expect(()=>{MegolmExportEncryption.decryptMegolmKeyFile(input, '')}) + expect(()=>MegolmExportEncryption.decryptMegolmKeyFile(input, '')) .toThrow('Invalid file: too short'); }); @@ -94,12 +111,12 @@ cissyYBxjsfsAn const [plain, password, input] = TEST_VECTORS[i]; return MegolmExportEncryption.decryptMegolmKeyFile( - stringToArray(input), password + stringToArray(input), password, ).then((decrypted) => { expect(decrypted).toEqual(plain); return next(i+1); - }) - }; + }); + } return next(0).catch(done); }); }); @@ -115,7 +132,7 @@ cissyYBxjsfsAn input, password, {kdf_rounds: 1000}, ).then((ciphertext) => { return MegolmExportEncryption.decryptMegolmKeyFile( - ciphertext, password + ciphertext, password, ); }).then((plaintext) => { expect(plaintext).toEqual(input); From f320f7d475465f0fa1fae3e15f2c666a2d14c678 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 14:30:45 +0100 Subject: [PATCH 209/275] Remove redundant action id --- src/components/structures/MatrixChat.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b65fa0be1c..1f9d2f6bb8 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1109,7 +1109,6 @@ module.exports = React.createClass({ }; const payload = { - id: '#mylovelyid', action: 'view_room', event_id: eventId, highlighted: Boolean(eventId), From f6051f663df00e4c05a9483e6760450a67ba699d Mon Sep 17 00:00:00 2001 From: dtygel Date: Thu, 8 Jun 2017 13:32:21 +0000 Subject: [PATCH 210/275] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/pt_BR/ --- src/i18n/strings/pt_BR.json | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 99175c874e..231c6a464d 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -876,5 +876,35 @@ "You have disabled URL previews by default.": "Você desabilitou pré-visualizações de links por padrão.", "You have enabled URL previews by default.": "Você habilitou pré-visualizações de links por padrão.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Você inseriu um contato inválido. Tente usar o ID Matrix ou endereço de e-mail da pessoa que está buscando.", - "Hide removed messages": "Ocultar mensagens removidas" + "Hide removed messages": "Ocultar mensagens removidas", + "Add": "Adicionar", + "%(count)s new messages.one": "%(count)s nova mensagem", + "%(count)s new messages.other": "%(count)s novas mensagens", + "Disable markdown formatting": "Desabilitar formatação MarkDown", + "Error: Problem communicating with the given homeserver.": "Erro: problema de comunicação com o Servidor de Base fornecido.", + "Failed to fetch avatar URL": "Falha ao obter a URL da imagem de perfil", + "Home": "Início", + "The phone number entered looks invalid": "O número de telefone inserido parece ser inválido", + "Uploading %(filename)s and %(count)s others.zero": "Enviando o arquivo %(filename)s", + "Uploading %(filename)s and %(count)s others.one": "Enviando o arquivo %(filename)s e %(count)s outros arquivos", + "Uploading %(filename)s and %(count)s others.other": "Enviando o arquivo %(filename)s e %(count)s outros arquivos", + "Username invalid: %(errMessage)s": "Nome de usuária(o) inválido: %(errMessage)s", + "Searching known users": "Buscando pessoas conhecidas", + "You must register to use this functionality": "Você deve se registrar para poder usar esta funcionalidade", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Reenviar todas ou cancelar todas agora. Você também pode selecionar mensagens individuais que queira reenviar ou cancelar.", + "Create new room": "Criar nova sala", + "Welcome page": "Página de boas vindas", + "Room directory": "Lista pública de salas", + "Start chat": "Iniciar conversa pessoal", + "New Password": "Nova senha", + "Start chatting": "Iniciar a conversa", + "Start Chatting": "Iniciar a conversa", + "Click on the button below to start chatting!": "Clique no botão abaixo para começar a conversar!", + "Create a new chat or reuse an existing one": "Criar uma nova conversa ou reutilizar alguma já existente", + "You already have existing direct chats with this user:": "Você já tem conversas pessoais com esta pessoa:", + "Username available": "Nome de usuária(o) disponível", + "Username not available": "Nome de usuária(o) indisponível", + "Something went wrong!": "Algo deu errado!", + "This will be your account name on the homeserver, or you can pick a different server.": "Este será seu nome de conta no Servidor de Base , ou então você pode escolher um servidor diferente.", + "If you already have a Matrix account you can log in instead.": "Se você já tem uma conta Matrix, pode também fazer login." } From e3ac78bd2804f8d6f76c99d24175bd31dcf3735a Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Jun 2017 14:36:20 +0100 Subject: [PATCH 211/275] Self-review --- src/components/views/room_settings/ColorSettings.js | 1 - src/i18n/strings/en_EN.json | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/views/room_settings/ColorSettings.js b/src/components/views/room_settings/ColorSettings.js index 2c18cb74f9..5fc845a541 100644 --- a/src/components/views/room_settings/ColorSettings.js +++ b/src/components/views/room_settings/ColorSettings.js @@ -20,7 +20,6 @@ var sdk = require('../../../index'); var Tinter = require('../../../Tinter'); var MatrixClientPeg = require("../../../MatrixClientPeg"); var Modal = require("../../../Modal"); -import { _t } from '../../../languageHandler'; import dis from '../../../dispatcher'; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0ecbf3da55..3619424d19 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -481,7 +481,6 @@ "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", "Rooms": "Rooms", "Save": "Save", - "Saving room color settings is only available to registered users": "Saving room color settings is only available to registered users", "Scroll to bottom of page": "Scroll to bottom of page", "Scroll to unread messages": "Scroll to unread messages", "Search": "Search", @@ -648,7 +647,7 @@ "Who would you like to communicate with?": "Who would you like to communicate with?", "Searching known users": "Searching known users", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.", - "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?". + "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?", "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", "You are already in a call.": "You are already in a call.", "You're not in any rooms yet! Press": "You're not in any rooms yet! Press", From f2efdf8a4f4fbf0122dbd9aa266bde4ed713ccd5 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Jun 2017 14:45:59 +0100 Subject: [PATCH 212/275] Review comments --- src/components/views/rooms/AuxPanel.js | 4 ++-- src/components/views/rooms/RoomPreviewBar.js | 4 ++-- src/components/views/rooms/RoomSettings.js | 2 +- src/i18n/strings/en_EN.json | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index 7e7a670aea..55b68d1eb1 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -96,8 +96,8 @@ module.exports = React.createClass({ else { joinText = ( {_tJsx( - "Join as voice or video.", - [/(.*?)<\/a>/, /(.*?)<\/a>/], + "Join as voice or video.", + [/(.*?)<\/voiceText>/, /(.*?)<\/videoText>/], [ (sub) => { this.onConferenceNotificationClick(event, 'voice');}} href="#">{sub}, (sub) => { this.onConferenceNotificationClick(event, 'video');}} href="#">{sub}, diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 8aa1f353a6..34166452cb 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -138,8 +138,8 @@ module.exports = React.createClass({
    { _tJsx( - 'Would you like to accept or decline this invitation?', - [/(.*?)<\/a>/, /(.*?)<\/a>/], + 'Would you like to accept or decline this invitation?', + [/(.*?)<\/acceptText>/, /(.*?)<\/declineText>/], [ (sub) => {sub}, (sub) => {sub} diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index f31fc68afc..997c451aa0 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -754,7 +754,7 @@ module.exports = React.createClass({ if (this.state.join_rule === "public" && aliasCount == 0) { addressWarning =
    - { _tJsx( + { _tJsx( 'To link to a room it must have an address.', /(.*?)<\/a>/, (sub) => {sub} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3619424d19..d29c26aa28 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -365,7 +365,7 @@ "'%(alias)s' is not a valid format for an alias": "'%(alias)s' is not a valid format for an alias", "%(displayName)s is typing": "%(displayName)s is typing", "Sign in with": "Sign in with", - "Join as voice or video.": "Join as voice or video.", + "Join as voice or video.": "Join as voice or video.", "Join Room": "Join Room", "joined and left": "joined and left", "joined": "joined", @@ -647,7 +647,7 @@ "Who would you like to communicate with?": "Who would you like to communicate with?", "Searching known users": "Searching known users", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.", - "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?", + "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?", "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", "You are already in a call.": "You are already in a call.", "You're not in any rooms yet! Press": "You're not in any rooms yet! Press", From 71eb40585991da54b42961f9a970fc2107caee38 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 14:53:21 +0100 Subject: [PATCH 213/275] Add comments & remove redundant check --- src/HtmlUtils.js | 5 +++++ src/components/views/messages/TextualBody.js | 13 ++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 5e8cfc3755..aec32092ed 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -365,6 +365,11 @@ export function bodyToHtml(content, highlights, opts) { } function addCodeCopyButton(safeBody) { + // Adds 'copy' buttons to pre blocks + // Note that this only manipulates the markup to add the buttons: + // we need to add the event handlers once the nodes are in the DOM + // since we can't save functions in the markup. + // This is done in TextualBody const el = document.createElement("div"); el.innerHTML = safeBody; const codeBlocks = Array.from(el.getElementsByTagName("pre")); diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 45fca566b9..d5a1977cdd 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -94,14 +94,13 @@ module.exports = React.createClass({ } }, 10); } + // add event handlers to the 'copy code' buttons const buttons = ReactDOM.findDOMNode(this).getElementsByClassName("mx_EventTile_copyButton"); - if (buttons.length > 0) { - for (let i = 0; i < buttons.length; i++) { - buttons[i].onclick = (e) => { - const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; - this.copyToClipboard(copyCode.textContent); - }; - } + for (let i = 0; i < buttons.length; i++) { + buttons[i].onclick = (e) => { + const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; + this.copyToClipboard(copyCode.textContent); + }; } } }, From 9baaf5499f30c80f8018279c69a742f572483805 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Jun 2017 14:58:54 +0100 Subject: [PATCH 214/275] Linting --- src/components/views/dialogs/SessionRestoreErrorDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index 51651b4aaa..a3eb7c6962 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -47,7 +47,7 @@ export default React.createClass({

    {_tJsx( "Otherwise, click here to send a bug report.", - /(.*?)<\/a>/, (sub) => {sub} + /(.*?)<\/a>/, (sub) => {sub}, )}

    ); From 614006a256c725804fcb7d7f031e9bbc15fb1107 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 8 Jun 2017 15:09:23 +0100 Subject: [PATCH 215/275] remove duplicate keys from en_EN --- src/i18n/strings/en_EN.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index d29c26aa28..3540feddee 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -645,7 +645,6 @@ "Who can read history?": "Who can read history?", "Who would you like to add to this room?": "Who would you like to add to this room?", "Who would you like to communicate with?": "Who would you like to communicate with?", - "Searching known users": "Searching known users", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s withdrew %(targetName)s's invitation.", "Would you like to accept or decline this invitation?": "Would you like to accept or decline this invitation?", "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", @@ -817,7 +816,6 @@ "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.", "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.", "You must join the room to see its files": "You must join the room to see its files", - "Server may be unavailable, overloaded, or you hit a bug.": "Server may be unavailable, overloaded, or you hit a bug.", "Reject all %(invitedRooms)s invites": "Reject all %(invitedRooms)s invites", "Start new chat": "Start new chat", "Guest users can't invite users. Please register.": "Guest users can't invite users. Please register.", @@ -897,15 +895,9 @@ "Online": "Online", "Idle": "Idle", "Offline": "Offline", - "disabled": "disabled", - "enabled": "enabled", "Start chatting": "Start chatting", "Start Chatting": "Start Chatting", "Click on the button below to start chatting!": "Click on the button below to start chatting!", - "Create a new chat or reuse an existing one": "Create a new chat or reuse an existing one", - "You already have existing direct chats with this user:": "You already have existing direct chats with this user:", - "Start new chat": "Start new chat", - "Disable URL previews for this room (affects only you)": "Disable URL previews for this room (affects only you)", "$senderDisplayName changed the room avatar to ": "$senderDisplayName changed the room avatar to ", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removed the room avatar.", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s changed the avatar for %(roomName)s", From 74e426055699b2b0415710cc4af3661f297592f5 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 8 Jun 2017 15:14:46 +0100 Subject: [PATCH 216/275] fix fullstops --- scripts/fix-i18n.pl | 7 ++++++- src/i18n/strings/de_DE.json | 12 ++++++------ src/i18n/strings/en_US.json | 6 +++--- src/i18n/strings/fr.json | 6 +++--- src/i18n/strings/pt.json | 6 +++--- src/i18n/strings/pt_BR.json | 6 +++--- src/i18n/strings/ru.json | 10 +++++----- src/i18n/strings/th.json | 2 +- src/i18n/strings/zh_Hans.json | 2 +- src/i18n/strings/zh_Hant.json | 4 ++-- 10 files changed, 33 insertions(+), 28 deletions(-) diff --git a/scripts/fix-i18n.pl b/scripts/fix-i18n.pl index ea19d710df..def352463d 100755 --- a/scripts/fix-i18n.pl +++ b/scripts/fix-i18n.pl @@ -66,6 +66,11 @@ Some of your messages have not been sent. This room is private or inaccessible to guests. You may be able to join if you register. Tried to load a specific point in this room's timeline, but was unable to find it. Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question. +This action cannot be performed by a guest user. Please register to be able to do this. +Tried to load a specific point in this room's timeline, but was unable to find it. +Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question. +You are trying to access %(roomName)s. +You will not be able to undo this change as you are promoting the user to have the same power level as yourself. EOT )]; } @@ -89,7 +94,7 @@ if ($_ =~ m/^(\s+)"(.*?)"(: *)"(.*?)"(,?)$/) { $sub = 1; } - if ($src eq $fixup && $dst !~ /\.$/) { + if ($ARGV !~ /(zh_Hans|zh_Hant|th)\.json$/ && $src eq $fixup && $dst !~ /\.$/) { print STDERR "fixing up dst: $dst\n"; $dst .= '.'; $sub = 1; diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 4102d7be56..384e27027b 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -427,7 +427,7 @@ "You're not in any rooms yet! Press": "Du bist noch keinem Raum beigetreten! Drücke", "click to reveal": "Klicke zum anzeigen", "To remove other users' messages": "Um Nachrichten anderer Nutzer zu verbergen", - "You are trying to access %(roomName)s": "Du versuchst, auf den Raum \"%(roomName)s\" zuzugreifen", + "You are trying to access %(roomName)s.": "Du versuchst, auf den Raum \"%(roomName)s\" zuzugreifen.", "af": "Afrikaans", "ar-ae": "Arabisch (VAE)", "ar-bh": "Arabisch (Bahrain)", @@ -611,12 +611,12 @@ "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", "Submit": "Absenden", "The main address for this room is: %(canonical_alias_section)s": "Die Hauptadresse für diesen Raum ist: %(canonical_alias_section)s", - "This action cannot be performed by a guest user. Please register to be able to do this": "Diese Aktion kann nicht von einem Gast ausgeführt werden. Bitte registriere dich um dies zu tun", + "This action cannot be performed by a guest user. Please register to be able to do this.": "Diese Aktion kann nicht von einem Gast ausgeführt werden. Bitte registriere dich um dies zu tun.", "%(actionVerb)s this person?": "Diese Person %(actionVerb)s?", "This room has no local addresses": "Dieser Raum hat keine lokale Adresse", - "This room is private or inaccessible to guests. You may be able to join if you register": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden", + "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden.", "Turn Markdown off": "Markdown deaktiveren", "Turn Markdown on": "Markdown einschalten", "Unable to load device list": "Geräteliste konnte nicht geladen werden", @@ -625,7 +625,7 @@ "Usage: /markdown on|off": "Verwendung: /markdown on|off", "You seem to be in a call, are you sure you want to quit?": "Du scheinst in einem Anruf zu sein. Bist du sicher schließen zu wollen?", "You seem to be uploading files, are you sure you want to quit?": "Du scheinst Dateien hochzuladen. Bist du sicher schließen zu wollen?", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "Du wirst diese Änderung nicht rückgängig machen können, da der Nutzer dasselbe Berechtigungslevel wie du selbst erhalten wird", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Du wirst diese Änderung nicht rückgängig machen können, da der Nutzer dasselbe Berechtigungslevel wie du selbst erhalten wird.", "Make Moderator": "Zum Moderator machen", "Room": "Raum", "(~%(searchCount)s results)": "(~%(searchCount)s Ergebnisse)", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index 6736e39276..5cdfd65d27 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -489,7 +489,7 @@ "The default role for new room members is": "The default role for new room members is", "The main address for this room is": "The main address for this room is", "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.": "The signing key you provided matches the signing key you received from %(userId)s's device %(deviceId)s. Device marked as verified.", - "This action cannot be performed by a guest user. Please register to be able to do this": "This action cannot be performed by a guest user. Please register to be able to do this", + "This action cannot be performed by a guest user. Please register to be able to do this.": "This action cannot be performed by a guest user. Please register to be able to do this.", "This email address is already in use": "This email address is already in use", "This email address was not found": "This email address was not found", "%(actionVerb)s this person?": "%(actionVerb)s this person?", @@ -588,7 +588,7 @@ "Would you like to": "Would you like to", "You are already in a call.": "You are already in a call.", "You're not in any rooms yet! Press": "You're not in any rooms yet! Press", - "You are trying to access %(roomName)s": "You are trying to access %(roomName)s", + "You are trying to access %(roomName)s.": "You are trying to access %(roomName)s.", "You cannot place a call with yourself.": "You cannot place a call with yourself.", "You cannot place VoIP calls in this browser.": "You cannot place VoIP calls in this browser.", "You do not have permission to post to this room": "You do not have permission to post to this room", @@ -609,7 +609,7 @@ "You seem to be in a call, are you sure you want to quit?": "You seem to be in a call, are you sure you want to quit?", "You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?", "You should not yet trust it to secure data": "You should not yet trust it to secure data", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.", "Sun": "Sun", "Mon": "Mon", "Tue": "Tue", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ffd1ef5885..1058db4aca 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -468,7 +468,7 @@ "tag direct chat": "marquer comme conversation directe", "The default role for new room members is": "Le rôle par défaut des nouveaux membres est", "The main address for this room is": "L'adresse principale pour ce salon est", - "This action cannot be performed by a guest user. Please register to be able to do this": "Cette action ne peut être effectuée par un visiteur. Merci de vous enregistrer afin de pouvoir effectuer cette action", + "This action cannot be performed by a guest user. Please register to be able to do this.": "Cette action ne peut être effectuée par un visiteur. Merci de vous enregistrer afin de pouvoir effectuer cette action.", "This email address is already in use": "Cette adresse e-mail est déjà utilisée", "This email address was not found": "Cette adresse e-mail n’a pas été trouvée", "%(actionVerb)s this person?": "%(actionVerb)s cette personne ?", @@ -557,7 +557,7 @@ "Would you like to": "Voulez-vous", "You are already in a call.": "Vous êtes déjà dans un appel.", "You're not in any rooms yet! Press": "Vous n’êtes dans aucun salon ! Cliquez", - "You are trying to access %(roomName)s": "Vous essayez d'accéder à %(roomName)s", + "You are trying to access %(roomName)s.": "Vous essayez d'accéder à %(roomName)s.", "You cannot place a call with yourself.": "Vous ne pouvez pas passer d'appel avec vous-même.", "You cannot place VoIP calls in this browser.": "Vous ne pouvez pas passer d'appel voix dans cet explorateur.", "You do not have permission to post to this room": "Vous n’avez pas la permission de poster dans ce salon", @@ -576,7 +576,7 @@ "You seem to be uploading files, are you sure you want to quit?": "Vous semblez être en train de télécharger des fichiers, êtes-vous sûr(e) de vouloir quitter ?", "You should not yet trust it to secure data": "Vous ne pouvez pas encore lui faire confiance pour sécuriser vos données", "changing room on a RoomView is not supported": "changer de salon sur un RoomView n'est pas supporté", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "Vous ne pourrez pas défaire ce changement car vous promouvez l’utilisateur aux mêmes pouvoirs que vous", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Vous ne pourrez pas défaire ce changement car vous promouvez l’utilisateur aux mêmes pouvoirs que vous.", "Sun": "Dim", "Mon": "Lun", "Tue": "Mar", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 27d257de9e..850e95f61f 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -399,7 +399,7 @@ "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s desfez o convite a %(targetName)s.", "You are already in a call.": "Você já está em uma chamada.", "You're not in any rooms yet! Press": "Você ainda não está em nenhuma sala! Pressione", - "You are trying to access %(roomName)s": "Você está tentando acessar a sala %(roomName)s", + "You are trying to access %(roomName)s.": "Você está tentando acessar a sala %(roomName)s.", "You cannot place a call with yourself.": "Você não pode iniciar uma chamada.", "You cannot place VoIP calls in this browser.": "Você não pode fazer chamadas de voz neste navegador.", "You need to be able to invite users to do that.": "Para fazer isso, você tem que ter permissão para convidar outras pessoas.", @@ -630,7 +630,7 @@ "Some of your messages have not been sent.": "Algumas das suas mensagens não foram enviadas.", "Submit": "Enviar", "The main address for this room is": "O endereço principal desta sala é", - "This action cannot be performed by a guest user. Please register to be able to do this": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso", + "This action cannot be performed by a guest user. Please register to be able to do this.": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso.", "%(actionVerb)s this person?": "%(actionVerb)s esta pessoa?", "This room has no local addresses": "Esta sala não tem endereços locais", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão.", @@ -643,7 +643,7 @@ "You have been invited to join this room by %(inviterName)s": "Você foi convidada/o por %(inviterName)s a ingressar nesta sala", "You seem to be in a call, are you sure you want to quit?": "Parece que você está em uma chamada. Tem certeza que quer sair?", "You seem to be uploading files, are you sure you want to quit?": "Parece que você está enviando arquivos. Tem certeza que quer sair?", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "Você não poderá desfazer esta mudança, pois estará dando a este(a) usuário(a) o mesmo nível de permissões que você", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Você não poderá desfazer esta mudança, pois estará dando a este(a) usuário(a) o mesmo nível de permissões que você.", "Make Moderator": "Tornar moderador(a)", "Room": "Sala", "(~%(searchCount)s results)": "(±%(searchCount)s resultados)", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 99175c874e..9e218d5c36 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -399,7 +399,7 @@ "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s desfez o convite a %(targetName)s.", "You are already in a call.": "Você já está em uma chamada.", "You're not in any rooms yet! Press": "Você ainda não está em nenhuma sala! Pressione", - "You are trying to access %(roomName)s": "Você está tentando acessar a sala %(roomName)s", + "You are trying to access %(roomName)s.": "Você está tentando acessar a sala %(roomName)s.", "You cannot place a call with yourself.": "Você não pode iniciar uma chamada.", "You cannot place VoIP calls in this browser.": "Você não pode fazer chamadas de voz neste navegador.", "You need to be able to invite users to do that.": "Para fazer isso, você tem que ter permissão para convidar outras pessoas.", @@ -630,7 +630,7 @@ "Some of your messages have not been sent.": "Algumas das suas mensagens não foram enviadas.", "Submit": "Enviar", "The main address for this room is": "O endereço principal desta sala é", - "This action cannot be performed by a guest user. Please register to be able to do this": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso", + "This action cannot be performed by a guest user. Please register to be able to do this.": "Esta ação não pode ser realizada por um/a usuário/a visitante. Por favor, registre-se para poder fazer isso.", "%(actionVerb)s this person?": "%(actionVerb)s esta pessoa?", "This room has no local addresses": "Esta sala não tem endereços locais", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tentei carregar um ponto específico na linha do tempo desta sala, mas parece que você não tem permissões para ver a mensagem em questão.", @@ -643,7 +643,7 @@ "You have been invited to join this room by %(inviterName)s": "Você foi convidada/o por %(inviterName)s a ingressar nesta sala", "You seem to be in a call, are you sure you want to quit?": "Parece que você está em uma chamada. Tem certeza que quer sair?", "You seem to be uploading files, are you sure you want to quit?": "Parece que você está enviando arquivos. Tem certeza que quer sair?", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "Você não poderá desfazer esta mudança, pois estará dando a este(a) usuário(a) o mesmo nível de permissões que você", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Você não poderá desfazer esta mudança, pois estará dando a este(a) usuário(a) o mesmo nível de permissões que você.", "Make Moderator": "Tornar moderador(a)", "Room": "Sala", "(~%(searchCount)s results)": "(±%(searchCount)s resultados)", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 647fbfe1d5..ce3d0d973d 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -362,7 +362,7 @@ "You cannot place VoIP calls in this browser.": "Вы не можете сделать вызовы VoIP с этим браузером.", "You are already in a call.": "Вы уже находитесь в разговоре.", "You're not in any rooms yet! Press": "Вы еще не находитесь ни в каких комнатах! Нажать", - "You are trying to access %(roomName)s": "Вы пытаетесь получить доступ %(roomName)s", + "You are trying to access %(roomName)s.": "Вы пытаетесь получить доступ %(roomName)s.", "You cannot place a call with yourself.": "Вы не можете позвонить самим себе.", "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s анулировал %(targetName)s's преглашение.", "Sep": "Сен.", @@ -575,7 +575,7 @@ "tag direct chat": "отметить прямое общение", "The default role for new room members is": "Роль по умолчанию для новых участников комнаты", "The main address for this room is": "Основной адрес для этой комнаты", - "This action cannot be performed by a guest user. Please register to be able to do this": "Это действие не может быть выполнено гостем. Пожалуйста, зарегистрируйтесь для этого", + "This action cannot be performed by a guest user. Please register to be able to do this.": "Это действие не может быть выполнено гостем. Пожалуйста, зарегистрируйтесь для этого.", "This email address is already in use": "Этот адрес электронной почты уже используется", "This email address was not found": "Этот адрес электронной почты не найден", "The email address linked to your account must be entered.": "Необходимо ввести адрес электронной почты, связанный с вашей учётной записью.", @@ -752,8 +752,8 @@ "To remove other users' messages": "Удалять сообщения других пользователей", "To reset your password, enter the email address linked to your account": "Чтобы сбросить ваш пароль введите адрес email, который используется аккаунтом", "to tag as %(tagName)s": "отметить как %(tagName)s", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Вы попытались загрузить указанное сообщение в комнате, однако у вас нету разрешений для его просмотра", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Вы попытались загрузить указанное сообщение в комнате, однако сервер не смог его найти", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Вы попытались загрузить указанное сообщение в комнате, однако у вас нету разрешений для его просмотра.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Вы попытались загрузить указанное сообщение в комнате, однако сервер не смог его найти.", "Unable to load device list": "Невозможно загрузить список устройств", "Unknown (user, device) pair:": "Неизвестная пара пользователь-устройство:", "Unmute": "Разглушить", @@ -767,7 +767,7 @@ "You have entered an invalid contact. Try using their Matrix ID or email address.": "Вы ввели неправильный адрес. Попробуйте использовать Matrix ID или адрес email.", "You need to enter a user name.": "Необходимо ввести имя пользователя.", "You seem to be in a call, are you sure you want to quit?": "Вы учавствуете в звонке, вы уверены, что хотите выйти?", - "You will not be able to undo this change as you are promoting the user to have the same power level as yourself": "Вы не сможете отменить это действие так как даете пользователю такой же уровень доступа как и у вас", + "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Вы не сможете отменить это действие так как даете пользователю такой же уровень доступа как и у вас.", "Set a Display Name": "Установить отображаемое имя", "(~%(searchCount)s results)": "(~%(searchCount)s результатов)", "%(severalUsers)shad their invitations withdrawn %(repeats)s times": "%(severalUsers)s отозвали свои приглашения %(repeats)s раз", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index f97b6b8d50..7ec5b606fc 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -389,7 +389,7 @@ "Who would you like to add to this room?": "คุณต้องการเพิ่มใครเข้าห้องนี้?", "Who would you like to communicate with?": "คุณต้องการสื่อสารกับใคร?", "You're not in any rooms yet! Press": "คุณยังไม่ได้อยู่ในห้องใดเลย! กด", - "You are trying to access %(roomName)s": "คุณกำลังพยายามเข้าสู่ %(roomName)s", + "You are trying to access %(roomName)s.": "คุณกำลังพยายามเข้าสู่ %(roomName)s", "You have disabled URL previews by default.": "ค่าเริ่มต้นของคุณปิดใช้งานตัวอย่าง URL เอาไว้", "You have enabled URL previews by default.": "ค่าเริ่มต้นของคุณเปิดใช้งานตัวอย่าง URL เอาไว้", "you must be a": "คุณต้องเป็น", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index e0db2b525b..e6eb5f632b 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -147,7 +147,7 @@ "Success": "成功", "The default role for new room members is": "此聊天室新成员的默认角色是", "The main address for this room is": "此聊天室的主要地址是", - "This action cannot be performed by a guest user. Please register to be able to do this": "游客不能进行此操作。请注册", + "This action cannot be performed by a guest user. Please register to be able to do this.": "游客不能进行此操作。请注册", "This email address is already in use": "此邮箱地址已经被使用", "This email address was not found": "未找到此邮箱地址", "%(actionVerb)s this person?": "%(actionVerb)s 这个用户?", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 17901789e9..56cc8f6add 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -274,7 +274,7 @@ "Success": "成功", "The default role for new room members is": "此聊天室新成員的默認角色是", "The main address for this room is": "此聊天室的主要地址是", - "This action cannot be performed by a guest user. Please register to be able to do this": "訪客不能進行此操作。請注冊", + "This action cannot be performed by a guest user. Please register to be able to do this.": "訪客不能進行此操作。請注冊", "This email address is already in use": "此郵箱地址已經被使用", "This email address was not found": "未找到此郵箱地址", "%(actionVerb)s this person?": "%(actionVerb)s 這個用戶?", @@ -290,7 +290,7 @@ "Would you like to": "你要", "You are already in a call.": "你已在電話通話中", "You're not in any rooms yet! Press": "你尚未加入任何聊天室!請按", - "You are trying to access %(roomName)s": "你將進入 %(roomName)聊天室", + "You are trying to access %(roomName)s.": "你將進入 %(roomName)聊天室", "You cannot place a call with yourself.": "你不能打電話給自已", "You cannot place VoIP calls in this browser.": "在此瀏覽器下無法置入網路電話通話", "Sun": "星期日", From aa20ad706e0f6110801a6e30c884f21be46d76a1 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:30:43 +0100 Subject: [PATCH 217/275] Remove redundant `currentRoomAlias` --- src/components/structures/MatrixChat.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index a115e89062..0493456e0e 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -621,7 +621,6 @@ module.exports = React.createClass({ page_type: PageTypes.RoomView, thirdPartyInvite: roomInfo.third_party_invite, roomOobData: roomInfo.oob_data, - currentRoomAlias: roomInfo.room_alias, autoJoin: roomInfo.auto_join, }; From 8ddc38c9b107ddd3d143e0269f7609c2444e4bbd Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:32:31 +0100 Subject: [PATCH 218/275] Doc _viewRoom highlighted --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 0493456e0e..f34cc8b0ef 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -607,6 +607,7 @@ module.exports = React.createClass({ // @param {boolean=} roomInfo.show_settings Makes RoomView show the room settings dialog. // @param {string=} roomInfo.event_id ID of the event in this room to show: this will cause a switch to the // context of that particular event. + // @param {boolean=} roomInfo.highlighted If true, add event_id to the hash of the URL // @param {Object=} roomInfo.third_party_invite Object containing data about the third party // we received to join the room, if any. // @param {string=} roomInfo.third_party_invite.inviteSignUrl 3pid invite sign URL From 2e82bf40fb7996f909b68ab8ad4fdc94ef489c47 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:34:20 +0100 Subject: [PATCH 219/275] Explain setting of highlighted in room/$eventId showScreen handling. --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index f34cc8b0ef..5f13f53d0b 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1118,6 +1118,7 @@ module.exports = React.createClass({ const payload = { action: 'view_room', event_id: eventId, + // If an event ID is set (truthy), mark it as highlighted highlighted: Boolean(eventId), third_party_invite: thirdPartyInvite, oob_data: oobData, From dca2be632591c64914421329a3a9743232019ec6 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:37:30 +0100 Subject: [PATCH 220/275] Add RoomView initial state and docs --- src/components/structures/RoomView.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index a4c589187b..f5db36a581 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -94,6 +94,13 @@ module.exports = React.createClass({ roomLoading: true, peekLoading: false, + // The event to be scrolled to initially + eventId: null, + // The offset in pixels from the event with which to scroll vertically + eventPixelOffset: null, + // Whether to highlight the event scrolled to + isEventHighlighted: null, + forwardingEvent: null, editingRoomSettings: false, uploadingRoomSettings: false, From e58e4db628c17e54d396570f4d6cf7e216eb11d6 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:38:58 +0100 Subject: [PATCH 221/275] Explain why search results are cleared when eventId changes --- src/components/structures/RoomView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index f5db36a581..180e6ebc89 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -170,6 +170,8 @@ module.exports = React.createClass({ isEventHighlighted: RoomViewStore.isEventHighlighted(), }; + // Clear the search results when clicking a search result (which changes the + // currently scrolled to event, this.state.eventId). if (this.state.eventId !== newState.eventId) { newState.searchResults = null; } From 59e649f326aaff78253ae40cb824f78969b3b611 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:43:45 +0100 Subject: [PATCH 222/275] Add comment about roomId potentially not being resolved following an update from RoomViewStore --- src/components/structures/RoomView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 180e6ebc89..cfa4038114 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -183,6 +183,8 @@ module.exports = React.createClass({ } this.setState(newState, () => { + // At this point, this.state.roomId could be null (e.g. the alias might not + // have been resolved yet) so anything called here must handle this case. this._onHaveRoom(); this.onRoom(MatrixClientPeg.get().getRoom(this.state.roomId)); }); From 1792fa45f4732aae292f85a85903d1199be87a65 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:45:50 +0100 Subject: [PATCH 223/275] Null-guard roomId before sending a dispatch to update scroll state Otherwise we pointlessly assign the null key to something --- src/components/structures/RoomView.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index cfa4038114..06e65589d1 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -590,6 +590,10 @@ module.exports = React.createClass({ }, _updateScrollMap(roomId) { + // No point updating scroll state if the room ID hasn't been resolved yet + if (!roomId) { + return; + } dis.dispatch({ action: 'update_scroll_state', room_id: roomId, From d691c891e7353e95d309474f92bf2d1ff7cc6546 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 15:49:48 +0100 Subject: [PATCH 224/275] Move all login error string generation into view This makes all the various hits done by login report the same useful error messages and gets rid of the broken ones like printing the http status code even if it was undefined. Also add text for the case of overzealous browser extensions because lots of people get bitten by it. --- src/Login.js | 18 +-------- src/components/structures/login/Login.js | 51 ++++++++++++++++-------- src/i18n/strings/en_EN.json | 2 +- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/Login.js b/src/Login.js index 659fdb92bb..8db6e99b89 100644 --- a/src/Login.js +++ b/src/Login.js @@ -97,11 +97,6 @@ export default class Login { guest: true }; }, (error) => { - if (error.httpStatus === 403) { - error.friendlyText = _t("Guest access is disabled on this Home Server."); - } else { - error.friendlyText = _t("Failed to register as guest:") + ' ' + error.data; - } throw error; }); } @@ -157,14 +152,7 @@ export default class Login { accessToken: data.access_token }); }, function(error) { - if (error.httpStatus == 400 && loginParams.medium) { - error.friendlyText = ( - _t('This Home Server does not support login using email address.') - ); - } else if (error.httpStatus === 403) { - error.friendlyText = ( - _t('Incorrect username and/or password.') - ); + if (error.httpStatus === 403) { if (self._fallbackHsUrl) { var fbClient = Matrix.createClient({ baseUrl: self._fallbackHsUrl, @@ -184,10 +172,6 @@ export default class Login { throw error; }); } - } else { - error.friendlyText = ( - _t("There was a problem logging in.") + ' (HTTP ' + error.httpStatus + ")" - ); } throw error; }); diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index be440febdc..7d283e0e36 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -87,7 +87,24 @@ module.exports = React.createClass({ ).then((data) => { this.props.onLoggedIn(data); }, (error) => { - this._setStateFromError(error, true); + let errorText; + + // Some error strings only apply for logging in + const usingEmail = username.indexOf("@"); + if (error.httpStatus == 400 && usingEmail) { + errorText = _t('This Home Server does not support login using email address.'); + } else if (error.httpStatus == 401 || error.httpStatus === 403) { + errorText = _t('Incorrect username and/or password.'); + } else { + // other errors, not specific to doing a password login + errorText = this._errorTextFromError(error); + } + + this.setState({ + errorText: errorText, + // https://matrix.org/jira/browse/SYN-744 + loginIncorrect: error.httpStatus == 401 || error.httpStatus == 403 + }); }).finally(() => { this.setState({ busy: false @@ -110,7 +127,16 @@ module.exports = React.createClass({ this._loginLogic.loginAsGuest().then(function(data) { self.props.onLoggedIn(data); }, function(error) { - self._setStateFromError(error, true); + let errorText; + if (error.httpStatus === 403) { + errorText = _t("Guest access is disabled on this Home Server."); + } else { + errorText = self._errorTextFromError(error); + } + self.setState({ + errorText: errorText, + loginIncorrect: false, + }); }).finally(function() { self.setState({ busy: false @@ -183,31 +209,22 @@ module.exports = React.createClass({ currentFlow: self._getCurrentFlowStep(), }); }, function(err) { - self._setStateFromError(err, false); + self.setState({ + errorText: self._errorTextFromError(err), + loginIncorrect: false, + }); }).finally(function() { self.setState({ busy: false, }); - }); + }).done(); }, _getCurrentFlowStep: function() { return this._loginLogic ? this._loginLogic.getCurrentFlowStep() : null; }, - _setStateFromError: function(err, isLoginAttempt) { - this.setState({ - errorText: this._errorTextFromError(err), - // https://matrix.org/jira/browse/SYN-744 - loginIncorrect: isLoginAttempt && (err.httpStatus == 401 || err.httpStatus == 403) - }); - }, - _errorTextFromError(err) { - if (err.friendlyText) { - return err.friendlyText; - } - let errCode = err.errcode; if (!errCode && err.httpStatus) { errCode = "HTTP " + err.httpStatus; @@ -230,7 +247,7 @@ module.exports = React.createClass({ ; } else { errorText = - { _tJsx("Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.", + { _tJsx("Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted and that a browser extension is not blocking requests.", /(.*?)<\/a>/, (sub) => { return { sub }; } )} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8dbbb98423..6984d46ed4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -180,7 +180,7 @@ "Bug Report": "Bug Report", "Bulk Options": "Bulk Options", "Call Timeout": "Call Timeout", - "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.", + "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted and that a browser extension is not blocking requests.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.", "Can't load user settings": "Can't load user settings", "Change Password": "Change Password", From 000a045e3523ed7154fb3817e06d3ee5cf343439 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:47:41 +0100 Subject: [PATCH 225/275] Rename RVS state (event -> initialEvent) and redocument --- src/components/structures/RoomView.js | 18 ++++++------- src/stores/RoomViewStore.js | 38 ++++++++++++++------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 06e65589d1..942e3c8e07 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -165,14 +165,14 @@ module.exports = React.createClass({ roomLoading: RoomViewStore.isRoomLoading(), roomLoadError: RoomViewStore.getRoomLoadError(), joining: RoomViewStore.isJoining(), - eventId: RoomViewStore.getEventId(), - eventPixelOffset: RoomViewStore.getEventPixelOffset(), - isEventHighlighted: RoomViewStore.isEventHighlighted(), + initialEventId: RoomViewStore.getInitialEventId(), + initialEventPixelOffset: RoomViewStore.getInitialEventPixelOffset(), + isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(), }; // Clear the search results when clicking a search result (which changes the - // currently scrolled to event, this.state.eventId). - if (this.state.eventId !== newState.eventId) { + // currently scrolled to event, this.state.initialEventId). + if (this.state.initialEventId !== newState.initialEventId) { newState.searchResults = null; } @@ -1665,12 +1665,12 @@ module.exports = React.createClass({ hideMessagePanel = true; } - const shouldHighlight = this.state.isEventHighlighted; + const shouldHighlight = this.state.isInitialEventHighlighted; let highlightedEventId = null; if (this.state.forwardingEvent) { highlightedEventId = this.state.forwardingEvent.getId(); } else if (shouldHighlight) { - highlightedEventId = this.state.eventId; + highlightedEventId = this.state.initialEventId; } // console.log("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview); @@ -1681,8 +1681,8 @@ module.exports = React.createClass({ manageReadMarkers={true} hidden={hideMessagePanel} highlightedEventId={highlightedEventId} - eventId={this.state.eventId} - eventPixelOffset={this.state.eventPixelOffset} + eventId={this.state.initialEventId} + eventPixelOffset={this.state.initialEventPixelOffset} onScroll={ this.onMessageListScroll } onReadMarkerUpdated={ this._updateTopUnreadMessagesBar } showUrlPreview = { this.state.showUrlPreview } diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 0529824a4b..8277aeda97 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -27,12 +27,14 @@ const INITIAL_STATE = { joinError: null, // The room ID of the room roomId: null, - // The event being viewed - eventId: null, - // The offset to display the event at (see scrollStateMap) - eventPixelOffset: null, - // Whether to highlight the event - isEventHighlighted: false, + + // The event to scroll to initially + initialEventId: null, + // The offset to display the initial event at (see scrollStateMap) + initialEventPixelOffset: null, + // Whether to highlight the initial event + isInitialEventHighlighted: false, + // The room alias of the room (or null if not originally specified in view_room) roomAlias: null, // Whether the current room is loading @@ -131,9 +133,9 @@ class RoomViewStore extends Store { this._setState({ roomId: payload.room_id, - eventId: payload.event_id, - eventPixelOffset: payload.event_offset, - isEventHighlighted: payload.highlighted, + initialEventId: payload.event_id, + initialEventPixelOffset: payload.event_offset, + isInitialEventHighlighted: payload.highlighted, roomLoading: false, roomLoadError: null, }); @@ -141,9 +143,9 @@ class RoomViewStore extends Store { // Resolve the alias and then do a second dispatch with the room ID acquired this._setState({ roomId: null, - eventId: null, - eventPixelOffset: null, - isEventHighlighted: null, + initialEventId: null, + initialEventPixelOffset: null, + isInitialEventHighlighted: null, roomAlias: payload.room_alias, roomLoading: true, roomLoadError: null, @@ -229,16 +231,16 @@ class RoomViewStore extends Store { return this._state.roomId; } - getEventId() { - return this._state.eventId; + getInitialEventId() { + return this._state.initialEventId; } - getEventPixelOffset() { - return this._state.eventPixelOffset; + getInitialEventPixelOffset() { + return this._state.initialEventPixelOffset; } - isEventHighlighted() { - return this._state.isEventHighlighted; + isInitialEventHighlighted() { + return this._state.isInitialEventHighlighted; } getRoomAlias() { From 36f72cccb51d4be536509b8879321660b604d90c Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 15:54:23 +0100 Subject: [PATCH 226/275] Don't alter members of payload (when defaulting an event to scroll to), alter a copy --- src/stores/RoomViewStore.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 8277aeda97..a0c9ccc33f 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -121,24 +121,26 @@ class RoomViewStore extends Store { _viewRoom(payload) { if (payload.room_id) { - // If an event ID wasn't specified, default to the one saved for this room - // via update_scroll_state. Also assume event_offset should be set. - if (!payload.event_id) { - const roomScrollState = this._state.scrollStateMap[payload.room_id]; - if (roomScrollState) { - payload.event_id = roomScrollState.focussedEvent; - payload.event_offset = roomScrollState.pixelOffset; - } - } - - this._setState({ + const newState = { roomId: payload.room_id, initialEventId: payload.event_id, initialEventPixelOffset: payload.event_offset, isInitialEventHighlighted: payload.highlighted, roomLoading: false, roomLoadError: null, - }); + }; + + // If an event ID wasn't specified, default to the one saved for this room + // via update_scroll_state. Assume initialEventPixelOffset should be set. + if (!newState.initialEventId) { + const roomScrollState = this._state.scrollStateMap[payload.room_id]; + if (roomScrollState) { + newState.initialEventId = roomScrollState.focussedEvent; + newState.initialEventPixelOffset = roomScrollState.pixelOffset; + } + } + + this._setState(newState); } else if (payload.room_alias) { // Resolve the alias and then do a second dispatch with the room ID acquired this._setState({ From 1ff2be189605c5827dbeedc462446b29b388361b Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 16:00:12 +0100 Subject: [PATCH 227/275] Update docs for RVS --- src/stores/RoomViewStore.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index a0c9ccc33f..e2a3f574ed 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -23,9 +23,9 @@ import { _t } from '../languageHandler'; const INITIAL_STATE = { // Whether we're joining the currently viewed room joining: false, - // Any error occurred during joining + // Any error that has occurred during joining joinError: null, - // The room ID of the room + // The room ID of the room currently being viewed roomId: null, // The event to scroll to initially @@ -229,38 +229,47 @@ class RoomViewStore extends Store { this._state = Object.assign({}, INITIAL_STATE); } + // The room ID of the room currently being viewed getRoomId() { return this._state.roomId; } + // The event to scroll to initially getInitialEventId() { return this._state.initialEventId; } + // The offset to display the initial event at (see scrollStateMap) getInitialEventPixelOffset() { return this._state.initialEventPixelOffset; } + // Whether to highlight the initial event isInitialEventHighlighted() { return this._state.isInitialEventHighlighted; } + // The room alias of the room (or null if not originally specified in view_room) getRoomAlias() { return this._state.roomAlias; } + // Whether the current room is loading (true whilst resolving an alias) isRoomLoading() { return this._state.roomLoading; } + // Any error that has occurred during loading getRoomLoadError() { return this._state.roomLoadError; } + // Whether we're joining the currently viewed room isJoining() { return this._state.joining; } + // Any error that has occurred during joining getJoinError() { return this._state.joinError; } From 8dc20606c8be5ae78859178b91f2760ea37d0827 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 16:07:29 +0100 Subject: [PATCH 228/275] Use comma for list of three things --- src/components/structures/login/Login.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index 7d283e0e36..6d0e929c93 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -247,7 +247,7 @@ module.exports = React.createClass({ ; } else { errorText = - { _tJsx("Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted and that a browser extension is not blocking requests.", + { _tJsx("Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.", /(.*?)<\/a>/, (sub) => { return { sub }; } )} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6984d46ed4..c6086faf0a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -180,7 +180,7 @@ "Bug Report": "Bug Report", "Bulk Options": "Bulk Options", "Call Timeout": "Call Timeout", - "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted and that a browser extension is not blocking requests.", + "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.", "Can't load user settings": "Can't load user settings", "Change Password": "Change Password", From 9def0bb5c2947ecfc53ce1abbe8e959cc2ab23d8 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 16:08:19 +0100 Subject: [PATCH 229/275] Oops, fix email check --- src/components/structures/login/Login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index 6d0e929c93..bbfff3712e 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -90,7 +90,7 @@ module.exports = React.createClass({ let errorText; // Some error strings only apply for logging in - const usingEmail = username.indexOf("@"); + const usingEmail = username.indexOf("@") > 0; if (error.httpStatus == 400 && usingEmail) { errorText = _t('This Home Server does not support login using email address.'); } else if (error.httpStatus == 401 || error.httpStatus === 403) { From 5e55b6a6435f8d342ab84281d31407f14792b54c Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 8 Jun 2017 16:23:43 +0100 Subject: [PATCH 230/275] PR feedback --- src/components/structures/login/Login.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js index bbfff3712e..27c0c200be 100644 --- a/src/components/structures/login/Login.js +++ b/src/components/structures/login/Login.js @@ -93,7 +93,7 @@ module.exports = React.createClass({ const usingEmail = username.indexOf("@") > 0; if (error.httpStatus == 400 && usingEmail) { errorText = _t('This Home Server does not support login using email address.'); - } else if (error.httpStatus == 401 || error.httpStatus === 403) { + } else if (error.httpStatus === 401 || error.httpStatus === 403) { errorText = _t('Incorrect username and/or password.'); } else { // other errors, not specific to doing a password login @@ -102,8 +102,11 @@ module.exports = React.createClass({ this.setState({ errorText: errorText, - // https://matrix.org/jira/browse/SYN-744 - loginIncorrect: error.httpStatus == 401 || error.httpStatus == 403 + // 401 would be the sensible status code for 'incorrect password' + // but the login API gives a 403 https://matrix.org/jira/browse/SYN-744 + // mentions this (although the bug is for UI auth which is not this) + // We treat both as an incorrect password + loginIncorrect: error.httpStatus === 401 || error.httpStatus == 403, }); }).finally(() => { this.setState({ From c02dbd1cdcde8b82db68e1ef9e2ff6d285ad3789 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:26:08 +0100 Subject: [PATCH 231/275] Rename initial state variables --- src/components/structures/RoomView.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 942e3c8e07..79420e776a 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -95,11 +95,11 @@ module.exports = React.createClass({ peekLoading: false, // The event to be scrolled to initially - eventId: null, + initialEventId: null, // The offset in pixels from the event with which to scroll vertically - eventPixelOffset: null, + initialEventPixelOffset: null, // Whether to highlight the event scrolled to - isEventHighlighted: null, + isInitialEventHighlighted: null, forwardingEvent: null, editingRoomSettings: false, From df625b0d318661ba64d2b1155651204f3219f7bf Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 8 Jun 2017 17:26:40 +0100 Subject: [PATCH 232/275] hit MemberInfo with Gemini to fix vector-im/riot-web#4223 --- src/components/views/rooms/MemberInfo.js | 48 +++++++++++++----------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index ff684aeae4..6dc86f9a97 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -38,6 +38,8 @@ import Unread from '../../../Unread'; import { findReadReceiptFromUserId } from '../../../utils/Receipt'; import WithMatrixClient from '../../../wrappers/WithMatrixClient'; import AccessibleButton from '../elements/AccessibleButton'; +import GeminiScrollbar from 'react-gemini-scrollbar'; + module.exports = WithMatrixClient(React.createClass({ displayName: 'MemberInfo', @@ -727,34 +729,36 @@ module.exports = WithMatrixClient(React.createClass({ const EmojiText = sdk.getComponent('elements.EmojiText'); return (
    - -
    - -
    - - {memberName} - -
    -
    - { this.props.member.userId } + + +
    +
    -
    - { _t("Level:") } + + {memberName} + +
    +
    + { this.props.member.userId } +
    +
    + { _t("Level:") } +
    +
    + +
    -
    - -
    -
    - { adminTools } + { adminTools } - { startChat } + { startChat } - { this._renderDevices() } + { this._renderDevices() } - { spinner } + { spinner } +
    ); } From 8cfdb4ce091dc947ffe3f9b4a8a98c04b236f208 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:27:04 +0100 Subject: [PATCH 233/275] Clarify initial event --- src/stores/RoomViewStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index e2a3f574ed..ec1a86b0e4 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -28,7 +28,7 @@ const INITIAL_STATE = { // The room ID of the room currently being viewed roomId: null, - // The event to scroll to initially + // The event to scroll to when the room is first viewed initialEventId: null, // The offset to display the initial event at (see scrollStateMap) initialEventPixelOffset: null, From cd8093d953abf69784aca82bbb1b076773a6cd28 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:28:21 +0100 Subject: [PATCH 234/275] Explicit undefined initialEventPixelOffset --- src/stores/RoomViewStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index ec1a86b0e4..ec545dcfd5 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -124,7 +124,7 @@ class RoomViewStore extends Store { const newState = { roomId: payload.room_id, initialEventId: payload.event_id, - initialEventPixelOffset: payload.event_offset, + initialEventPixelOffset: undefined, isInitialEventHighlighted: payload.highlighted, roomLoading: false, roomLoadError: null, From c72edab7267dc408fbd2d4900f9deb7fefeb16d4 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:28:56 +0100 Subject: [PATCH 235/275] Update doc for getInitialEventId --- src/stores/RoomViewStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index ec545dcfd5..15a46894a1 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -234,7 +234,7 @@ class RoomViewStore extends Store { return this._state.roomId; } - // The event to scroll to initially + // The event to scroll to when the room is first viewed getInitialEventId() { return this._state.initialEventId; } From cd6786114b6b1d49d747be3750d7df763a101e04 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:40:53 +0100 Subject: [PATCH 236/275] When joining, use a roomAlias if we have it And default to the current roomId otherwise --- src/stores/RoomViewStore.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index cc8959af7a..2c5dd9e534 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -137,7 +137,9 @@ class RoomViewStore extends Store { this._setState({ joining: true, }); - MatrixClientPeg.get().joinRoom(this._state.roomId, payload.opts).done(() => { + MatrixClientPeg.get().joinRoom( + this._state.roomAlias || this._state.roomId, payload.opts, + ).done(() => { dis.dispatch({ action: 'joined_room', }); From 3218cae6e3bdce6265826df4d02f6f008240e328 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:47:48 +0100 Subject: [PATCH 237/275] Expect to join by alias if given to RVS --- test/stores/RoomViewStore-test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/stores/RoomViewStore-test.js b/test/stores/RoomViewStore-test.js index 2f545ffd74..adcae90e9b 100644 --- a/test/stores/RoomViewStore-test.js +++ b/test/stores/RoomViewStore-test.js @@ -28,8 +28,8 @@ describe('RoomViewStore', function() { }); it('can be used to view a room by ID and join', function(done) { - peg.get().joinRoom = (roomId) => { - expect(roomId).toBe("!randomcharacters:aser.ver"); + peg.get().joinRoom = (roomAddress) => { + expect(roomAddress).toBe("!randomcharacters:aser.ver"); done(); }; @@ -40,8 +40,8 @@ describe('RoomViewStore', function() { it('can be used to view a room by alias and join', function(done) { peg.get().getRoomIdForAlias.returns(q({room_id: "!randomcharacters:aser.ver"})); - peg.get().joinRoom = (roomId) => { - expect(roomId).toBe("!randomcharacters:aser.ver"); + peg.get().joinRoom = (roomAddress) => { + expect(roomAddress).toBe("#somealias2:aser.ver"); done(); }; From 9892566007f2790e2e8295b7e7093977f61672d5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:54:41 +0100 Subject: [PATCH 238/275] Highlighted means highlighted --- src/components/structures/MatrixChat.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 5f13f53d0b..b803b676f7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -608,6 +608,7 @@ module.exports = React.createClass({ // @param {string=} roomInfo.event_id ID of the event in this room to show: this will cause a switch to the // context of that particular event. // @param {boolean=} roomInfo.highlighted If true, add event_id to the hash of the URL + // and alter the EventTile to appear highlighted. // @param {Object=} roomInfo.third_party_invite Object containing data about the third party // we received to join the room, if any. // @param {string=} roomInfo.third_party_invite.inviteSignUrl 3pid invite sign URL From 5588e115eb9be9a1cf10fe4c7e33b9a3e44cbc86 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 8 Jun 2017 17:57:37 +0100 Subject: [PATCH 239/275] Clarify doc for highlighted --- src/components/structures/MatrixChat.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b803b676f7..b6e3552a95 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1119,7 +1119,9 @@ module.exports = React.createClass({ const payload = { action: 'view_room', event_id: eventId, - // If an event ID is set (truthy), mark it as highlighted + // If an event ID is given in the URL hash, notify RoomViewStore to mark + // it as highlighted, which will propagate to RoomView and highlight the + // associated EventTile. highlighted: Boolean(eventId), third_party_invite: thirdPartyInvite, oob_data: oobData, From 7dbb1c3b85bee3aa9ade8956f489d8dcaddb3553 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Thu, 8 Jun 2017 16:04:10 +0000 Subject: [PATCH 240/275] Translated using Weblate (German) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 4102d7be56..c5ee272b1f 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -885,31 +885,31 @@ "%(count)s new messages.one": "%(count)s neue Nachricht", "%(count)s new messages.other": "%(count)s neue Nachrichten", "Error: Problem communicating with the given homeserver.": "Fehler: Problem beim kommunizieren mit dem angegebenen Heimserver.", - "Failed to fetch avatar URL": "Fehler beim holen der Avatar-URL", - "The phone number entered looks invalid": "Die Telefonnummer, die eingegeben wurde, sieht ungültig aus", + "Failed to fetch avatar URL": "Abrufen der Avatar-URL fehlgeschlagen", + "The phone number entered looks invalid": "Die eingegebene Telefonnummer scheint ungültig zu sein", "This room is private or inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist privat oder für Gäste nicht betretbar. Du kannst evtl. beitreten wenn du dich registrierst.", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber du hast keine Berechtigung diese Nachricht zu sehen.", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Es wurde versucht einen spezifischen Punkt in der Chat-Historie zu laden, aber er konnte nicht gefunden werden.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Es wurde versucht, einen bestimmten Punkt im Chatverlauf dieses Raumes zu laden. Dir fehlt jedoch die Berechtigung, die betreffende Nachricht zu sehen.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Es wurde versucht, einen bestimmten Punkt im Chatverlauf dieses Raumes zu laden, der Punkt konnte jedoch nicht gefunden werden.", "Uploading %(filename)s and %(count)s others.zero": "%(filename)s wird hochgeladen", "Uploading %(filename)s and %(count)s others.one": "%(filename)s und %(count)s weitere Dateien werden hochgeladen", "Uploading %(filename)s and %(count)s others.other": "%(filename)s und %(count)s weitere Dateien werden hochgeladen", - "You must register to use this functionality": "Du musst dich registrieren um diese Funktionalität zu nutzen", - "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Sende erneut oder breche alles ab. Du kannst auch auch individuelle Nachrichten erneut senden or abbrechen.", + "You must register to use this functionality": "Du musst dich registrieren, um diese Funktionalität nutzen zu können", + "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Alle erneut senden oder alle verwerfen. Du kannst auch einzelne Nachrichten erneut senden oder verwerfen.", "Create new room": "Neuen Raum erstellen", "Welcome page": "Willkommensseite", "Room directory": "Raum-Verzeichnis", - "Start chat": "Starte Chat", + "Start chat": "Chat starten", "New Password": "Neues Passwort", "Start chatting": "Starte plaudern", "Start Chatting": "Starte Gespräche", - "Click on the button below to start chatting!": "Klicke den Button unten um das Plaudern zu beginnen!", - "Create a new chat or reuse an existing one": "Erstelle einen neuen Chat oder nutze einen existierenden", + "Click on the button below to start chatting!": "Unten auf den Button klicken, um einen Chat zu beginnen!", + "Create a new chat or reuse an existing one": "Neuen Chat erstellen oder einen vorhandenen Chat fortsetzen", "You already have existing direct chats with this user:": "Du hast bereits direkte Chats mit diesem Nutzer:", "Username available": "Nutzername verfügbar", "Username not available": "Nutzername nicht verfügbar", "Something went wrong!": "Etwas ging schief!", - "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein Konto-Name auf dem Heimserver, oder du kannst einen anderen Server auswählen.", + "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein zukünftiger Benutzername auf dem Heimserver. Alternativ kannst du auch einen anderen Server auswählen.", "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", "Home": "Start", - "Username invalid: %(errMessage)s": "Nutzername falsch: %(errMessage)s" + "Username invalid: %(errMessage)s": "Ungültiger Benutzername: %(errMessage)s" } From 80dba43b41b783c8b2809c7747d19925a5f69c43 Mon Sep 17 00:00:00 2001 From: dtygel Date: Thu, 8 Jun 2017 13:47:18 +0000 Subject: [PATCH 241/275] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/pt_BR/ --- src/i18n/strings/pt_BR.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 231c6a464d..61cc45c94f 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -81,7 +81,7 @@ "Error": "Erro", "Event information": "Informação do evento", "Export E2E room keys": "Exportar chaves ponta-a-ponta da sala", - "Failed to change password. Is your password correct?": "Não foi possível modificar a senha. A senha informada está correta?", + "Failed to change password. Is your password correct?": "Não foi possível mudar a senha. A sua senha está correta?", "Failed to forget room": "Não foi possível esquecer a sala", "Failed to leave room": "Falha ao tentar deixar a sala", "Failed to reject invitation": "Falha ao tentar rejeitar convite", From 0f062a7fe9fb1031bf14d92732c470aba694d9c2 Mon Sep 17 00:00:00 2001 From: Stanislav N Date: Thu, 8 Jun 2017 13:54:08 +0000 Subject: [PATCH 242/275] Translated using Weblate (Russian) Currently translated at 100.0% (853 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 4f1939ffcc..275d27b442 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -854,10 +854,10 @@ "Drop file here to upload": "Перетащите файл сюда для загрузки", " (unsupported)": " (не поддерживается)", "Ongoing conference call%(supportedText)s. %(joinText)s": "Идет конференц-звонок%(supportedText)s. %(joinText)s", - "for %(amount)ss": "для %(amount)s", - "for %(amount)sm": "для %(amount)s", - "for %(amount)sh": "для %(amount)s", - "for %(amount)sd": "для %(amount)s", + "for %(amount)ss": "уже %(amount)sс", + "for %(amount)sm": "уже %(amount)sм", + "for %(amount)sh": "уже %(amount)sч", + "for %(amount)sd": "уже %(amount)sд", "Online": "В сети", "Idle": "Отошел", "Offline": "Не в сети", From 449b4e87d4fd746bb110a2a82b31550de2a2459b Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Thu, 8 Jun 2017 13:54:32 +0000 Subject: [PATCH 243/275] Translated using Weblate (Thai) Currently translated at 56.1% (479 of 853 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index f97b6b8d50..635dbb256c 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -78,7 +78,7 @@ "Remove": "ลบ", "Custom Server Options": "กำหนดเซิร์ฟเวอร์เอง", "Failed to join the room": "การเข้าร่วมห้องล้มเหลว", - "Drop here %(toAction)s": "ปล่อยที่นี่ %(toAction)s", + "Drop here %(toAction)s": "ปล่อยที่นี่%(toAction)s", "Favourite": "รายการโปรด", "Failed to forget room %(errCode)s": "การลืมห้องล้มเหลว %(errCode)s", "%(targetName)s accepted an invitation.": "%(targetName)s ตอบรับคำเชิญแล้ว", @@ -120,7 +120,7 @@ "Bans user with given id": "ผู้ใช้และ id ที่ถูกแบน", "Blacklisted": "ขึ้นบัญชีดำ", "Can't load user settings": "ไม่สามารถโหลดการตั้งค่าผู้ใช้ได้", - "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s ได้เปลี่ยนชื่อที่แสดงจาก %(oldDisplayName)s ไปเป็น %(displayName)s", + "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s เปลี่ยนชื่อที่แสดงของเขาจาก %(oldDisplayName)s ไปเป็น %(displayName)s", "%(senderName)s changed their profile picture.": "%(senderName)s เปลี่ยนรูปโปรไฟล์ของเขา", "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s เปลี่ยนชื่อห้องไปเป็น %(roomName)s", "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s ลบชื่อห้อง", @@ -244,7 +244,7 @@ "New passwords don't match": "รหัสผ่านใหม่ไม่ตรงกัน", "New passwords must match each other.": "รหัสผ่านใหม่ทั้งสองช่องต้องตรงกัน", "none": "ไม่มี", - "not set": "ไม่ได้ตั้ง", + "not set": "ยังไม่ได้ตั้ง", "not specified": "ไม่ได้ระบุ", "(not supported by this browser)": "(เบราว์เซอร์นี้ไม่รองรับ)", "": "<ไม่รองรับ>", From 1d02cde5021fe8e91a3e0329dbdd547849eebe8e Mon Sep 17 00:00:00 2001 From: Dor Ben Dov Date: Thu, 8 Jun 2017 20:03:33 +0000 Subject: [PATCH 244/275] Added translation using Weblate (Hebrew) --- src/i18n/strings/he.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/i18n/strings/he.json diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/src/i18n/strings/he.json @@ -0,0 +1 @@ +{} \ No newline at end of file From f680bb5d3c29331140313c60eb2441e799c04972 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Thu, 8 Jun 2017 23:00:55 +0100 Subject: [PATCH 245/275] broken vars --- src/i18n/strings/el.json | 2 +- src/i18n/strings/th.json | 2 +- src/i18n/strings/zh_Hant.json | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index d8729202d5..725b5497a5 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -1,7 +1,7 @@ { "af": "Αφρικάνικα", "Error": "Σφάλμα", - "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου", + "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου %(errCode)s", "Failed to join the room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο", "Mute": "Σίγαση", "Notifications": "Ειδοποιήσεις", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 635dbb256c..fbc62fdb47 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -475,7 +475,7 @@ "Custom server": "เซิร์ฟเวอร์ที่กำหนดเอง", "Home server URL": "URL เซิร์ฟเวอร์บ้าน", "Identity server URL": "URL เซิร์ฟเวอร์ระบุตัวตน", - "%(severalUsers)sleft %(repeats)s times": "%(targetName)sออกจากห้อง %(repeats)s ครั้ง", + "%(severalUsers)sleft %(repeats)s times": "%(severalUsers)sออกจากห้อง %(repeats)s ครั้ง", "%(oneUser)sleft %(repeats)s times": "%(oneUser)sออกจากห้อง %(repeats)s ครั้ง", "%(severalUsers)sleft": "%(severalUsers)sออกจากห้องแล้ว", "%(oneUser)sleft": "%(oneUser)sออกจากห้องแล้ว" diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 56cc8f6add..b2e1939565 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -359,7 +359,7 @@ "Enable URL previews for this room (affects only you)": "啟用此房間的網址預覽(僅影響您)", "Drop file here to upload": "把文件放在這裡上傳", "Disable URL previews by default for participants in this room": "默認情況下,此房間的參與者禁用網址預覽", - "URL previews are %(globalDisableUrlPreview)s by default for participants in this room.": "默認情況下,這個房間的參與者的網址預覽是%(globalDisableUrlPreview)。", + "URL previews are %(globalDisableUrlPreview)s by default for participants in this room.": "默認情況下,這個房間的參與者的網址預覽是%(globalDisableUrlPreview)s。", "Removed or unknown message type": "已刪除或未知的信息類型", - "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "您即將被帶到第三方網站,以便您可以驗證您的帳戶以使用%(integrationsUrl)。你想繼續嗎?" + "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "您即將被帶到第三方網站,以便您可以驗證您的帳戶以使用%(integrationsUrl)s。你想繼續嗎?" } From 3b0906fc85ef5d6156fffb17d41174e0bb6c5701 Mon Sep 17 00:00:00 2001 From: Dor Ben Dov Date: Thu, 8 Jun 2017 20:10:15 +0000 Subject: [PATCH 246/275] Translated using Weblate (Hebrew) Currently translated at 2.1% (19 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/he/ --- src/i18n/strings/he.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index 9e26dfeeb6..2d9daecc49 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -1 +1,21 @@ -{} \ No newline at end of file +{ + "ar-ae": "ערבית (U.A.E)", + "ar-bh": "ערבית (בחריין)", + "ar-dz": "ערבית (אלג'יריה)", + "ar-eg": "ערבית (מצריים)", + "ar-iq": "ערבית (עיראק)", + "ar-jo": "ערבית (ירדן)", + "af": "אפריקאית", + "ar-kw": "ערבית (כווית)", + "ar-lb": "ערבית (לבנון)", + "ar-ly": "ערבית (לוב)", + "ar-ma": "ערבית (מרוקו)", + "ar-om": "ערבית (אומן)", + "ar-qa": "ערבית (קטאר)", + "ar-sa": "ערבית (ערב הסעודית)", + "ar-sy": "ערבית (סוריה)", + "ar-tn": "ערבית (תוניסיה)", + "ar-ye": "ערבית (תימן)", + "be": "בלארוסית", + "bg": "בולגרית" +} From c478631db4376a945f122bcdb313d28d101c779e Mon Sep 17 00:00:00 2001 From: Vladi Date: Thu, 8 Jun 2017 20:59:35 +0000 Subject: [PATCH 247/275] Translated using Weblate (Russian) Currently translated at 97.0% (874 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 121 ++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 45 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 08ed27d465..52e69c9388 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -5,7 +5,7 @@ "Account": "Аккаунт", "Add email address": "Добавить email адрес", "Add phone number": "Добавить телефонный номер", - "Admin": "Admin", + "Admin": "Админ", "Advanced": "Дополнительно", "Algorithm": "Алгоритм", "all room members": "все участники комнаты", @@ -54,7 +54,7 @@ "Deactivate my account": "Деактивировать мою учётную запись", "decline": "отказаться", "Decryption error": "Ошибка дешифрования", - "Default": "Default", + "Default": "Стандарт", "demote": "понижать", "Deops user with given id": "Deops пользователь с данным id", "Device ID": "Устройство ID", @@ -83,7 +83,7 @@ "Failed to unban": "Не удалось отменить запрет", "Failed to upload file": "Не удалось закачать файл", "Favourite": "Избранное", - "favourite": "фаворит", + "favourite": "Избранное", "Favourites": "Избранное", "Filter room members": "Фильтр участников комнаты", "Forget room": "Забыть комнату", @@ -99,7 +99,7 @@ "Import E2E room keys": "Импортировать E2E ключ комнаты", "Invalid Email Address": "Недействительный адрес электронной почты", "invited": "invited", - "Invite new room members": "Пригласить новых учасников в комнату", + "Invite new room members": "Пригласить новых участников в комнату", "Invites": "Приглашать", "Invites user with given id to current room": "Пригласить пользователя с данным id в текущую комнату", "is a": "является", @@ -108,10 +108,10 @@ "joined": "присоединенный", "joined the room": "joined the room", "Joins room with given alias": "Присоединяется к комнате с данным псевдонимом", - "Kicks user with given id": "Кик пользователя с заданным id", + "Kicks user with given id": "Выгнать пользователя с заданным id", "Labs": "Лаборатория", "Leave room": "Уйти из комнаты", - "left and rejoined": "Покинуть и переподключится", + "left and rejoined": "Покинуть и пере подключится", "left": "покинуть", "left the room": "left the room", "Logged in as": "Зарегистрированный как", @@ -119,13 +119,13 @@ "Logout": "Выход из системы", "Low priority": "Низкий приоритет", "made future room history visible to": "made future room history visible to", - "Manage Integrations": "Управление интеграциями", + "Manage Integrations": "Управление Интеграциями", "Members only": "Только участники", "Mobile phone number": "Номер мобильного телефона", "Moderator": "Ведущий", "my Matrix ID": "мой Matrix ID", "Name": "Имя", - "Never send encrypted messages to unverified devices from this device": "Никогда не отправлять зашифрованные сообщения на неверифицированные устроства с этого устройства", + "Never send encrypted messages to unverified devices from this device": "Никогда не отправлять зашифрованные сообщения на не верифицированные устройства с этого устройства", "Never send encrypted messages to unverified devices in this room from this device": "Никогда не отправляйте зашифрованные сообщения в непроверенные устройства в этой комнате из этого устройства", "New password": "Новый пароль", "New passwords must match each other.": "Новые пароли должны соответствовать друг другу.", @@ -158,8 +158,8 @@ "set a profile picture": "set a profile picture", "set their display name to": "set their display name to", "Settings": "Настройки", - "Start a chat": "Start a chat", - "Start Chat": "Start Chat", + "Start a chat": "Начать чат", + "Start Chat": "Начать чат", "tag as": "tag as", "These are experimental features that may break in unexpected ways. Use with caution": "These are experimental features that may break in unexpected ways. Use with caution", "To send events of type": "Для отправки типа событий", @@ -169,9 +169,9 @@ "Unable to remove contact information": "Невозможно удалить контактную информацию", "Unable to verify email address.": "Невозможно проверить адрес электронной почты.", "Unban": "Отменить запрет", - "Unencrypted room": "Незашифрованная комната", - "unencrypted": "незашифрованно", - "unknown device": "неизвесное устройство", + "Unencrypted room": "Не зашифрованная комната", + "unencrypted": "не зашифровано", + "unknown device": "неизвестное устройство", "unknown error code": "неизвестная ошибка", "unknown": "неизвестно", "Upload avatar": "Загрузить аватар", @@ -189,7 +189,7 @@ "Video call": "Видио вызов", "Voice call": "Голосовой вызов", "VoIP conference finished.": "VoIP конференция закончилась.", - "VoIP conference started.": "VoIP Конференция стартовала.", + "VoIP conference started.": "VoIP Конференция началась.", "(warning: cannot be disabled again!)": "(предупреждение: не может быть отключено!)", "Warning!": "Предупреждение!", "was banned": "запрещен", @@ -230,7 +230,7 @@ "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s их имя измененное с %(oldDisplayName)s на %(displayName)s.", "%(senderName)s changed their profile picture.": "%(senderName)s изменил фото профиля.", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s уровень мощности изменен на %(powerLevelDiffText)s.", - "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s имя комнаты измененно на %(roomName)s.", + "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s имя комнаты изменено на %(roomName)s.", "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s измененная тема на %(topic)s.", "Conference call failed.": "Конференц-вызов прервался.", "Conference calling is in development and may not be reliable.": "Конференц-вызов находится в процессе и может не быть надежным.", @@ -257,13 +257,13 @@ "%(senderName)s made future room history visible to": "%(senderName)s сделал видимой для всех будущую историю комнаты", "Missing room_id in request": "Отсутствует room_id в запросе", "Missing user_id in request": "Отсутствует user_id в запросе", - "Must be viewing a room": "Комната должна быть посищена", - "New Composer & Autocomplete": "Новый едитор & Автозаполнение", + "Must be viewing a room": "Посмотреть комнату", + "New Composer & Autocomplete": "Новый автор & Авто. заполнение", "(not supported by this browser)": "(не поддерживаемый этим браузером)", "af": "Африкаанс", "ar-ae": "Арабский (О.А.Е)", "ar-bh": "Арабский (Бахрейн)", - "ar-dz": "Арабский (Алжыр)", + "ar-dz": "Арабский (Алжир)", "ar-eg": "Арабский (Египет)", "ar-iq": "Арабский (Ирак)", "ar-jo": "Арабский (Иордания)", @@ -285,7 +285,7 @@ "de-ch": "Немецкий (Швейцария)", "de-li": "Немецкий (Лихтенштейн)", "de-lu": "Немецкий (Люксембург)", - "el": "Гречиский", + "el": "Греческий", "en-au": "Английский (Австралия)", "en-bz": "Английский (Белиз)", "en-ca": "Английский (Канада)", @@ -310,7 +310,7 @@ "es-pa": "Испанский (Панама)", "et": "Эстонский", "fi": "Финский", - "fr": "Французкий", + "fr": "Французский", "hr": "Хорватский", "it": "Итальянский", "ja": "Японский", @@ -320,7 +320,7 @@ "ro": "Румынский", "uk": "Украинский", "now. You can also select individual messages to resend or cancel.": "теперь. Вы можете также выбрать отдельные сообщения, чтобы снова послать или отменить.", - "Auto-complete": "Автозаполнение", + "Auto-complete": "Авто-заполнение", "Error changing language": "Ошибка изменения языка", "Riot was unable to find the correct Data for the selected Language.": "Riot был неспособен найти правельные данные для выбранного языка.", "Connectivity to the server has been lost.": "Связь с сервером была потеряна.", @@ -364,7 +364,7 @@ "You're not in any rooms yet! Press": "Вы еще не находитесь ни в каких комнатах! Нажать", "You are trying to access %(roomName)s.": "Вы пытаетесь получить доступ %(roomName)s.", "You cannot place a call with yourself.": "Вы не можете позвонить самим себе.", - "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s анулировал %(targetName)s's преглашение.", + "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s отменил %(targetName)s's приглашение.", "Sep": "Сен.", "Jan": "Янв.", "Feb": "Фев.", @@ -389,9 +389,9 @@ "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Ваш адрес электронной почты, кажется, не связан с Matrix ID на этом Homeserver.", "to start a chat with someone": "Начать чат с кем-то", "to tag direct chat": "отметить прямой чат", - "To use it, just wait for autocomplete results to load and tab through them.": "Для его использования просто подождите загрузки результатов автозаполнения и нажимайте Tab для навигации.", + "To use it, just wait for autocomplete results to load and tab through them.": "Для его использования просто подождите загрузки результатов авто-заполнения и нажимайте Tab для навигации.", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s включил сквозное шифрование (algorithm %(algorithm)s).", - "Unable to restore previous session": "Невозможно востановить предыдущий сеанс", + "Unable to restore previous session": "Невозможно восстановить предыдущий сеанс", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s запрет отменен %(targetName)s.", "Unable to capture screen": "Невозможно записать снимок экрана", "Unable to enable Notifications": "Невозможно включить уведомления", @@ -477,7 +477,7 @@ "Access Token:": "Токен:", "Always show message timestamps": "Всегда показывать время сообщения", "Authentication": "Авторизация", - "olm version:": "версия olm:", + "olm version:": "Версия olm:", "%(items)s and %(remaining)s others": "%(items)s и другие %(remaining)s", "%(items)s and one other": "%(items)s и ещё один", "%(items)s and %(lastItem)s": "%(items)s и %(lastItem)s", @@ -491,7 +491,7 @@ "Current password": "Текущий пароль", "Email": "Электронная почта", "Failed to kick": "Не удалось выгнать", - "Failed to load timeline position": "Не удалось загрузить позицию таймлайна", + "Failed to load timeline position": "Не удалось загрузить позицию графика", "Failed to mute user": "Не удалось заглушить", "Failed to reject invite": "Не удалось отклонить приглашение", "Failed to save settings": "Не удалось сохранить настройки", @@ -540,7 +540,7 @@ "%(senderName)s removed their profile picture.": "%(senderName)s убрал своё изображение.", "%(senderName)s requested a VoIP conference.": "%(senderName)s запросил голосовую конференц-связь.", "Report it": "Сообщить об этом", - "Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "На данный момент сброс пароля сбросит все ключи шифрования на всех устройствах, зашифрованная история общения будет нечитаема, если вы сперва не скачаете ваши ключи от комнаты и не загрузите их после. В будущем это будет улучшено.", + "Resetting password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "На данный момент сброс пароля сбросит все ключи шифрования на всех устройствах, зашифрованная история общения будет не читаема, если вы сперва не скачаете ваши ключи от комнаты и не загрузите их после. В будущем это будет улучшено.", "restore": "восстановить", "Return to app": "Вернуться в приложение", "Riot does not have permission to send you notifications - please check your browser settings": "Riot не имеет права для отправки вам уведомлений, пожалуйста, проверьте настройки вашего браузера", @@ -657,7 +657,7 @@ "Operation failed": "Действие не удалось", "powered by Matrix": "управляемый с Matrix", "Add a topic": "Добавить тему", - "Show timestamps in 12 hour format (e.g. 2:30pm)": "Времея отображать в 12 часовом формате (напр. 2:30pm)", + "Show timestamps in 12 hour format (e.g. 2:30pm)": "Время отображать в 12 часовом формате (напр. 2:30pm)", "Use compact timeline layout": "Компактное отображение", "Hide removed messages": "Скрыть удаленное сообщение", "No Microphones detected": "Микрофоны не обнаружены", @@ -669,17 +669,17 @@ "Analytics": "Аналитика", "Riot collects anonymous analytics to allow us to improve the application.": "Riot собирает анонимные данные, чтобы улучшить эту программу.", "Opt out of analytics": "Подтвердить отказ передачи аналитических данных", - "Logged in as:": "Зарегестрирован как:", + "Logged in as:": "Зарегистрирован как:", "Default Device": "Стандартное устройство", "No Webcams detected": "Веб-камера не обнаружена", "VoIP": "VoIP", - "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Для обеспечения безопасности выход из системы удалит все ключи шифроования из этого браузера. Если вы хотите иметь возможность расшифровать переписку в будущем - вы должны экспортирвать ключи вручную.", + "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Для обеспечения безопасности выход из системы удалит все ключи шифрования из этого браузера. Если вы хотите иметь возможность расшифровать переписку в будущем - вы должны экспортировать ключи вручную.", "Guest access is disabled on this Home Server.": "Гостевой доступ отключен на этом сервере.", "Guests can't set avatars. Please register.": "Гости не могут устанавливать аватар. Пожалуйста, зарегистрируйтесь.", "Guests can't use labs features. Please register.": "Гости не могут использовать экспериментальные возможности. Пожалуйста, зарегистрируйтесь.", "Guests cannot join this room even if explicitly invited.": "Гости не могут заходить в эту комнату если не были приглашены.", "Missing Media Permissions, click here to request.": "Отсутствуют разрешения, нажмите для запроса.", - "No media permissions": "Нет медиа разрешений", + "No media permissions": "Нет разрешённых носителей", "You may need to manually permit Riot to access your microphone/webcam": "Вам необходимо предоставить Riot доступ к микрофону или веб-камере вручную", "Anyone": "Все", "Are you sure you want to leave the room '%(roomName)s'?": "Вы уверены, что хотите покинуть '%(roomName)s'?", @@ -694,7 +694,7 @@ "disabled": "отключено", "Disable markdown formatting": "Отключить форматирование Markdown", "Email address": "Адрес email", - "Email address (optional)": "Адрем email (не обязательно)", + "Email address (optional)": "Адрес email (не обязательно)", "enabled": "включено", "Error decrypting attachment": "Ошибка расшифровки файла", "Export": "Экспорт", @@ -712,7 +712,7 @@ "Password:": "Пароль:", "Privacy warning": "Предупреждение приватности", "Privileged Users": "Привилегированные пользователи", - "Revoke Moderator": "Снять модераторские права", + "Revoke Moderator": "Снять права Модератора", "Refer a friend to Riot:": "Расскажите другу о Riot:", "Register": "Регистрация", "Remote addresses for this room:": "Удаленные адреса для этой комнаты:", @@ -724,7 +724,7 @@ "Server may be unavailable or overloaded": "Сервер может быть недоступен или перегружен", "Server may be unavailable, overloaded, or search timed out :(": "Сервер может быть недоступен, перегружен или поиск прекращен по тайм-ауту :(", "Server may be unavailable, overloaded, or the file too big": "Сервер может быть недоступен, перегружен или размер файла слишком большой", - "Server may be unavailable, overloaded, or you hit a bug.": "Сервер может быть недоступен, перегружен или вы нашли баг.", + "Server may be unavailable, overloaded, or you hit a bug.": "Сервер может быть недоступен, перегружен или вы нашли ошибку.", "Server unavailable, overloaded, or something else went wrong.": "Сервер может быть недоступен, перегружен или произошло что-то страшное.", "Session ID": "ID сессии", "%(senderName)s set a profile picture.": "%(senderName)s установил картинку профиля.", @@ -743,7 +743,7 @@ "This room is not accessible by remote Matrix servers": "Это комната закрыта для других серверов Matrix", "To ban users": "Забанить пользователей", "to browse the directory": "просматривать директорию", - "To configure the room": "Конфигурировать комнату", + "To configure the room": "Настроить комнату", "To invite users into the room": "Приглашать пользователей в комнату", "to join the discussion": "присоединиться к дискуссии", "To kick users": "Выгонять пользователей", @@ -752,21 +752,21 @@ "To remove other users' messages": "Удалять сообщения других пользователей", "To reset your password, enter the email address linked to your account": "Чтобы сбросить ваш пароль введите адрес email, который используется аккаунтом", "to tag as %(tagName)s": "отметить как %(tagName)s", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Вы попытались загрузить указанное сообщение в комнате, однако у вас нету разрешений для его просмотра.", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Вы попытались загрузить указанное сообщение в комнате, однако сервер не смог его найти.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Ошибка загрузки истории комнаты: недостаточно прав.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Ошибка загрузки истории комнаты: запрошенный элемент не найден.", "Unable to load device list": "Невозможно загрузить список устройств", "Unknown (user, device) pair:": "Неизвестная пара пользователь-устройство:", - "Unmute": "Разглушить", + "Unmute": "Вкл. звук", "Unrecognised command:": "Неизвестная команда:", "Unrecognised room alias:": "Неизвестный псевдоним комнаты:", "Verified key": "Верифицированный ключ", "WARNING: Device already verified, but keys do NOT MATCH!": "ВНИМАНИЕ: устройство уже было верифицировано, однако ключи НЕ СОВПАДАЮТ!", "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "ВНИМАНИЕ: ОШИБКА ВЕРИФИКАЦИИ КЛЮЧЕЙ! Ключ для подписки устройства %(deviceId)s пользователя %(userId)s: \"%(fprint)s\", однако он не совпадает с предоставленным ключем \"%(fingerprint)s\". Это может означать перехват вашего канала коммуникации!", - "You have disabled URL previews by default.": "Предпросмотр ссылок отключен по-умолчанию.", + "You have disabled URL previews by default.": "Пред. просмотр ссылок отключен по-умолчанию.", "You have enabled URL previews by default.": "Предпросмотр ссылок включен по-умолчанию.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Вы ввели неправильный адрес. Попробуйте использовать Matrix ID или адрес email.", "You need to enter a user name.": "Необходимо ввести имя пользователя.", - "You seem to be in a call, are you sure you want to quit?": "Вы учавствуете в звонке, вы уверены, что хотите выйти?", + "You seem to be in a call, are you sure you want to quit?": "Вы участвуете в звонке, вы уверены, что хотите выйти?", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Вы не сможете отменить это действие так как даете пользователю такой же уровень доступа как и у вас.", "Set a Display Name": "Установить отображаемое имя", "(~%(searchCount)s results)": "(~%(searchCount)s результатов)", @@ -784,7 +784,7 @@ "Import room keys": "Импортировать ключи", "File to import": "Файл для импорта", "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Этот процесс позволяет вам экспортировать ключи для сообщений, которые вы получили в комнатах с шифрованием, в локальный файл. Вы сможете импортировать эти ключи в другой клиент Matrix чтобы расшифровать эти сообщения.", - "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "Экспортированный файл позволит любому пользователю расшифровать и зашифровать сообщения, которые вы видите, поэтому вы должны быть крайне осторожны и держать файл в надежном месте. Чтобы поспособствовать этому вы должны ввести пароль, который будет использоваться для шифрования ключей. Вы сможете импоортировать ключи только зная этот пароль.", + "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "Экспортированный файл позволит любому пользователю расшифровать и зашифровать сообщения, которые вы видите, поэтому вы должны быть крайне осторожны и держать файл в надежном месте. Чтобы поспособствовать этому вы должны ввести пароль, который будет использоваться для шифрования ключей. Вы сможете импортировать ключи только зная этот пароль.", "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "Этот процесс позволяем вам импортировать ключи шифрования, которые вы экспортировали ранее из клиента Matrix. После импорта вы сможете читать зашифрованную переписку и отправлять шифрованные сообщения.", "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Экспортированный файл защищен паролем. Вы должны ввести этот пароль для расшифровки.", "You must join the room to see its files": "Вы должны зайти в комнату для просмотра файлов", @@ -865,7 +865,7 @@ "$senderDisplayName changed the room avatar to ": "$senderDisplayName сменил аватар комнаты на ", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s удалил аватар комнаты.", "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s сменил аватар для %(roomName)s", - "Create new room": "Создать комнату", + "Create new room": "Создать новую комнату", "Room directory": "Каталог комнат", "Start chat": "Начать чат", "Welcome page": "Домашняя страница", @@ -875,8 +875,6 @@ "Error: Problem communicating with the given homeserver.": "Ошибка: проблема коммуникаций с указанным Home Server'ом.", "Failed to fetch avatar URL": "Ошибка получения аватара", "The phone number entered looks invalid": "Введенный номер телефона выглядит неправильным", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Ошибка загрузки истории комнаты: недостаточно прав.", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Ошибка загрузки истории комнаты: запрошенный элемент не найден.", "Uploading %(filename)s and %(count)s others.zero": "Загрузка %(filename)s", "Uploading %(filename)s and %(count)s others.one": "Загрузка %(filename)s и %(count)s другой файл", "Uploading %(filename)s and %(count)s others.other": "Загрузка %(filename)s и %(count)s других файлов", @@ -895,5 +893,38 @@ "Something went wrong!": "Что-то пошло не так!", "This will be your account name on the homeserver, or you can pick a different server.": "Это будет ваше имя пользователя на , или вы можете выбрать другой сервер.", "If you already have a Matrix account you can log in instead.": "Если вы уже имеете учетную запись Matrix, то вы можете войти.", - "Home": "Старт" + "Home": "Старт", + "a room": "комната", + "Accept": "Принять", + "Active call (%(roomName)s)": "Активный вызов (%(roomName)s)", + "Admin tools": "Админ утилита", + "And %(count)s more...": "И %(count)s больше...", + "Alias (optional)": "Псевдоним (опционально)", + "Click here to join the discussion!": " Нажми здесь чтоб присоединиться к обсуждению!", + "Close": "Закрыть", + "Disable Notifications": "Отключить оповещение", + "Drop File Here": "Вставить сюда файл", + "Enable Notifications": "Включить оповещение", + "Encrypted by a verified device": "Шифрование с помощью проверенных устройств", + "Encrypted by an unverified device": "Шифрование с помощью не проверенных устройств", + "Encryption is enabled in this room": "Шифрование в этой комнате включено", + "Encryption is not enabled in this room": "Шифрование в этой комнате не включено", + "Failed to upload profile picture!": "Не удалось загрузить фото профиля!", + "Incoming call from %(name)s": "Входящий вызов от %(name)s", + "Incoming video call from %(name)s": "Входящий видио вызов от %(name)s", + "Incoming voice call from %(name)s": "Входящий голосовой вызов от %(name)s", + "Join as voice or video.": "Присоединен как голос или видио .", + "Last seen": "В последний раз видели", + "Level:": "Уровень:", + "No display name": "Нет отображаемое имя", + "Otherwise, click here to send a bug report.": "Иначе , нажать 2 чтоб отослать отчет о ошибке.", + "Private Chat": "Частный чат", + "Public Chat": "Общественный чат", + "Reason: %(reasonText)s": "Причина: %(reasonText)s", + "Rejoin": "Пере-соединиться", + "Set": "Вводить", + "Start authentication": "Начать идентификацию", + "This room": "Эта комната", + "(~%(count)s results).other": "(~%(count)s results)", + "Device Name": "Имя устройства" } From 5c21216e95cc99b5fb2e9b300371655a6a9166bf Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk Date: Fri, 9 Jun 2017 04:18:05 +0000 Subject: [PATCH 248/275] Translated using Weblate (Thai) Currently translated at 66.0% (595 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/th/ --- src/i18n/strings/th.json | 126 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 125 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 635dbb256c..e63d0de9a3 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -478,5 +478,129 @@ "%(severalUsers)sleft %(repeats)s times": "%(targetName)sออกจากห้อง %(repeats)s ครั้ง", "%(oneUser)sleft %(repeats)s times": "%(oneUser)sออกจากห้อง %(repeats)s ครั้ง", "%(severalUsers)sleft": "%(severalUsers)sออกจากห้องแล้ว", - "%(oneUser)sleft": "%(oneUser)sออกจากห้องแล้ว" + "%(oneUser)sleft": "%(oneUser)sออกจากห้องแล้ว", + "el": "กรีก", + "en-au": "อังกฤษ (ออสเตรเลีย)", + "en-bz": "อังกฤษ (เบลีซ)", + "en-gb": "อังกฤษ (สหราชอาณาจักร)", + "en-nz": "อังกฤษ (นิวซีแลนด์)", + "en-jm": "อังกฤษ (จาเมกา)", + "en-ie": "อังกฤษ (ไอร์แลนด์)", + "en-tt": "อังกฤษ (ตรินิแดด)", + "af": "แอฟริกาใต้", + "ar-ae": "อาหรับ (สหรัฐอาหรับเอมิเรตส์)", + "ar-bh": "อาหรับ (บาห์เรน)", + "ar-dz": "อาหรับ (แอลจีเรีย)", + "ar-eg": "อาหรับ (อียิปต์)", + "ar-iq": "อาหรับ (อิรัก)", + "ar-jo": "อาหรับ (จอร์แดน)", + "ar-kw": "อาหรับ (คูเวต)", + "ar-lb": "อาหรับ (เลบานอน)", + "ar-ly": "อาหรับ (ลิเบีย)", + "ar-ma": "อาหรับ (โมร็อกโก)", + "ar-om": "อาหรับ (โอมาน)", + "ar-qa": "อาหรับ (กาตาร์)", + "ar-sa": "อาหรับ (ซาอุดีอาระเบีย)", + "ar-sy": "อาหรับ (ซีเรีย)", + "ar-tn": "อาหรับ (ตูนิเซีย)", + "ar-ye": "อาหรับ (เยเมน)", + "be": "เบลารุส", + "bg": "บัลแกเรีย", + "ca": "คาตาลัน", + "cs": "สาธารณรัฐเช็ก", + "da": "เดนมาร์ก", + "de-at": "เยอรมัน (ออสเตรีย)", + "de-ch": "เยอรมัน (สวิสเซอร์แลนด์)", + "de-lu": "เยอรมัน (ลักเซมเบิร์ก)", + "en-za": "อังกฤษ (แอฟริกาใต้)", + "es-ar": "สเปน (อาร์เจนตินา)", + "es-bo": "สเปน (โบลิเวีย)", + "es-cl": "สเปน (ชิลี)", + "es-co": "สเปน (โคลัมเบีย)", + "es-cr": "สเปน (คอสตาริกา)", + "es-do": "สเปน (สาธารณรัฐโดมินิกัน)", + "zu": "สูลู", + "zh-tw": "จีน (ไต้หวัน)", + "zh-sg": "จีน (สิงคโปร์)", + "zh-hk": "จีน (ฮ่องกง)", + "xh": "โซซา", + "ve": "เวนดา", + "ur": "อูรดู", + "uk": "ยูเครน", + "ts": "ซองก้า", + "tr": "ตุรกี", + "tn": "ซวานา", + "sv": "สวีเดน", + "sv-fi": "สวีเดน (ฟินแลนด์)", + "sr": "เซอร์เบีย", + "sq": "แอลเบเนีย", + "sl": "สโลเวเนีย", + "sk": "สโลวาเกีย", + "sb": "ซอร์เบีย", + "ru": "รัสเซีย", + "ru-mo": "รัสเซีย (สาธารณรัฐมอลโดวา)", + "ro": "โรมาเนีย", + "ro-mo": "โรมาเนีย (สาธารณรัฐมอลโดวา)", + "pt": "โปรตุเกส", + "pt-br": "โปรตุเกส (บราซิล)", + "pl": "โปแลนด์", + "no": "นอร์เวย์", + "nl": "ดัตช์", + "nl-be": "ดัตช์ (เบลเยียม)", + "mt": "มอลตา", + "ms": "มาเลเซีย", + "lv": "ลัตเวีย", + "lt": "ลิธัวเนีย", + "ji": "ยิดดิช", + "it": "อิตาลี", + "it-ch": "อิตาลี (สวิสเซอร์แลนด์)", + "is": "ไอซ์แลนด์", + "id": "อินโดนีเซีย", + "hu": "ฮังการี", + "hr": "โครเอเชีย", + "hi": "ฮินดู", + "he": "อิสราเอล", + "gd": "เกลิค (สกอตแลนด์)", + "fr-lu": "ฝรั่งเศส (ลักเซมเบิร์ก)", + "fr-ca": "ฝรั่งเศส (แคนาดา)", + "fr-ch": "ฝรั่งเศส (สวิสเซอร์แลนด์)", + "fr-be": "ฝรั่งเศส (เบลเยี่ยม)", + "fo": "แฟโร", + "fi": "ฟินแลนด์", + "fa": "ฟาร์ซิ", + "et": "เอสโตเนีย", + "es-ve": "สเปน (เวเนซุเอลา)", + "es-uy": "สเปน (อุรุกวัย)", + "es-sv": "สเปน (เอลซัลวาดอร์)", + "es": "สเปน (สเปน)", + "es-py": "สเปน (ปารากวัย)", + "es-pr": "สเปน (เปอร์โตริโก)", + "es-pe": "สเปน (เปรู)", + "es-pa": "สเปน (ปานามา)", + "es-ni": "สเปน (นิการากัว)", + "es-mx": "สเปน (เม็กซิโก)", + "es-hn": "สเปน (ฮอนดูรัส)", + "es-gt": "สเปน (กัวเตมาลา)", + "es-ec": "สเปน (เอกวาดอร์)", + "Add": "เพิ่ม", + "de-li": "เยอรมัน (ลิกเตนสไตน์)", + "eu": "บาสก์ (บาสก์)", + "ga": "ไอร์แลนด์", + "zh-cn": "จีน (สาธารณรัฐประชาชนจีน)", + "mk": "มาซิโดเนีย (อดีตสาธารณรัฐยูโกสลาฟมาซิโดเนีย)", + "a room": "ห้อง", + "Accept": "ยอมรับ", + "VoIP": "VoIP", + "Close": "ปิด", + "Custom": "กำหนดเอง", + "Decline": "ปฏิเสธ", + "Home": "เมนูหลัก", + "Last seen": "เห็นครั้งสุดท้าย", + "Rejoin": "กลับเข้าร่วม", + "Set": "ตั้ง", + "This room": "ห้องนี้", + "Unnamed Room": "ห้องที่ยังไม่ได้ตั้งชื่อ", + "%(user)s is a": "%(user)s เป็น", + "(~%(count)s results).one": "(~%(count)s ผลลัพท์)", + "(~%(count)s results).other": "(~%(count)s ผลลัพท์)" } From 2a293ac57171c52ab40cb9a9caa1fc77cd60519c Mon Sep 17 00:00:00 2001 From: Jean GB Date: Fri, 9 Jun 2017 08:10:27 +0000 Subject: [PATCH 249/275] Translated using Weblate (French) Currently translated at 93.0% (838 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 1058db4aca..e1cd7316de 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -294,7 +294,7 @@ "Found a bug?": "Trouvé un problème ?", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s de %(fromPowerLevel)s à %(toPowerLevel)s", "Guest users can't create new rooms. Please register to create room and start a chat.": "Les visiteurs ne peuvent créer de nouveaux salons. Merci de vous enregistrer pour commencer une discussion.", - "Guest users can't upload files. Please register to upload.": "Les visiteurs ne peuvent telécharger de fichiers. Merci de vous enregistrer pour télécharger.", + "Guest users can't upload files. Please register to upload.": "Les visiteurs ne peuvent pas télécharger de fichier. Veuillez vous enregistrer pour télécharger.", "had": "avait", "Hangup": "Raccrocher", "Hide read receipts": "Cacher les accusés de réception", @@ -499,15 +499,15 @@ "to make a room or": "pour créer un salon ou", "To remove other users' messages": "Pour supprimer les messages des autres utilisateurs", "To reset your password, enter the email address linked to your account": "Pour réinitialiser votre mot de passe, merci d’entrer l’adresse email liée à votre compte", - "to restore": "restaurer", + "to restore": "pour restaurer", "To send events of type": "Pour envoyer des évènements du type", "To send messages": "Pour envoyer des messages", "to start a chat with someone": "pour démarrer une conversation avec quelqu’un", "to tag as %(tagName)s": "pour marquer comme %(tagName)s", "to tag direct chat": "pour marquer comme conversation directe", "To use it, just wait for autocomplete results to load and tab through them.": "Pour l’utiliser, attendez simplement que les résultats de l’auto-complétion s’affichent et défilez avec la touche Tab.", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Une tentative de chargement d’un point donné dans la chronologie de ce salon a été effectuée, mais vous n’avez pas la permission de voir le message en question.", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Une tentative de chargement d’un point donné dans la chronologie de ce salon a été effectuée, mais il n’a pas été trouvé.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Un instant donné de la chronologie n’a pu être chargé car vous n’avez pas la permission de le visualiser.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Un instant donné de la chronologie n’a pu être chargé car il n’a pas pu être trouvé.", "Turn Markdown off": "Désactiver le formatage ’Markdown’", "Turn Markdown on": "Activer le formatage ’Markdown’", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s a activé l’encryption bout-en-bout (algorithme %(algorithm)s).", @@ -619,7 +619,7 @@ "There are no visible files in this room": "Il n'y a pas de fichier visible dans ce salon", "Room": "Salon", "Connectivity to the server has been lost.": "La connectivité au serveur a été perdue.", - "Sent messages will be stored until your connection has returned.": "Les messages envoyé seront stockés jusqu’à ce que votre connection revienne.", + "Sent messages will be stored until your connection has returned.": "Les messages envoyés seront stockés jusqu’à ce que votre connection revienne.", "Auto-complete": "Auto-complétion", "Resend all": "Tout renvoyer", "(~%(searchCount)s results)": "(~%(searchCount)s résultats)", @@ -834,11 +834,7 @@ "Error: Problem communicating with the given homeserver.": "Erreur: Problème de communication avec le homeserveur.", "Failed to fetch avatar URL": "Échec lors de la récupération de l’URL de l’avatar", "The phone number entered looks invalid": "Le numéro de téléphone entré semble être invalide", - "Guest users can't upload files. Please register to upload.": "Les visiteurs ne peuvent pas télécharger de fichier. Veuillez vous enregistrer pour télécharger.", - "Some of your messages have not been sent.": "Certains de vos messages n’ont pas été envoyés.", "This room is private or inaccessible to guests. You may be able to join if you register.": "Ce salon est privé ou interdits aux visiteurs. Vous pourrez peut-être le joindre si vous vous enregistrez.", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Un instant donné de la chronologie n’a pu être chargé car vous n’avez pas la permission de le visualiser.", - "Tried to load a specific point in this room's timeline, but was unable to find it.": "Un instant donné de la chronologie n’a pu être chargé car il n’a pas pu être trouvé.", "Uploading %(filename)s and %(count)s others.zero": "Téléchargement de %(filename)s", "Uploading %(filename)s and %(count)s others.one": "Téléchargement de %(filename)s et %(count)s autre", "Uploading %(filename)s and %(count)s others.other": "Téléchargement de %(filename)s et %(count)s autres", From a21b6e61a693ccfef18134bd5148ff479fc97101 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 9 Jun 2017 10:08:26 +0100 Subject: [PATCH 250/275] Default to home page when settings is closed If the current room isn't set. --- src/components/structures/MatrixChat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b6e3552a95..61b1dd4a38 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1307,7 +1307,7 @@ module.exports = React.createClass({ }); } else { dis.dispatch({ - action: 'view_room_directory', + action: 'view_home_page', }); } }, From c7229967a663ad6b6ae3a04700288a8dcf8478c5 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 9 Jun 2017 10:28:45 +0100 Subject: [PATCH 251/275] Goto /home when forgetting the last room --- src/components/structures/MatrixChat.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b6e3552a95..9e59e8ea5c 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -570,6 +570,12 @@ module.exports = React.createClass({ const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); + if (allRooms.length === 0) { + dis.dispatch({ + action: 'view_home_page', + }); + return; + } let roomIndex = -1; for (let i = 0; i < allRooms.length; ++i) { if (allRooms[i].roomId == this.state.currentRoomId) { From 19bb879fbf3858d40c4e28d08af53479a9989199 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 9 Jun 2017 10:54:42 +0100 Subject: [PATCH 252/275] Handle only 1 room in the list --- src/components/structures/MatrixChat.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 9e59e8ea5c..fae2b831d5 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -570,7 +570,10 @@ module.exports = React.createClass({ const allRooms = RoomListSorter.mostRecentActivityFirst( MatrixClientPeg.get().getRooms(), ); - if (allRooms.length === 0) { + // If there are 0 rooms or 1 room, view the home page because otherwise + // if there are 0, we end up trying to index into an empty array, and + // if there is 1, we end up viewing the same room. + if (allRooms.length < 2) { dis.dispatch({ action: 'view_home_page', }); From 81a8c566362f1c716452c24ad868c7d71cff4662 Mon Sep 17 00:00:00 2001 From: Jean GB Date: Fri, 9 Jun 2017 08:19:29 +0000 Subject: [PATCH 253/275] Translated using Weblate (French) Currently translated at 93.0% (838 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index e1cd7316de..712ccb2a63 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -386,7 +386,7 @@ "Email address": "Adresse e-mail", "Error decrypting attachment": "Erreur lors du déchiffrement de la pièce jointe", "Failed to set avatar.": "Erreur lors de la définition de la photo de profil.", - "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Par sécurité une deconnexion supprimera toutes les clés d’encryption de cet explorateur. Si vous voulez être capable de décrypter l’historique de votre conversation lors de sessions futures de Riot, merci d’exporter les clés pour le salon.", + "For security, logging out will delete any end-to-end encryption keys from this browser. If you want to be able to decrypt your conversation history from future Riot sessions, please export your room keys for safe-keeping.": "Par sécurité une déconnexion supprimera toutes les clés d’encryption de ce navigateur. Si vous voulez être capable de décrypter l’historique de votre conversation lors de sessions futures de Riot, merci d’exporter les clés pour le salon.", "Guests can't set avatars. Please register.": "Les visiteurs ne peuvent définir de photo de profil. Merci de vous enregistrer.", "Guests can't use labs features. Please register.": "Les visiteurs ne peuvent utiliser les fonctionalités du laboratoire. Merci de vous enregistrer.", "Guests cannot join this room even if explicitly invited.": "Les visiteurs ne peuvent rejoindre ce salon, même si explicitement invités.", From 65e4b70efe46967e86a4efde49fd8d313a3dba9f Mon Sep 17 00:00:00 2001 From: Bamstam Date: Thu, 8 Jun 2017 16:04:10 +0000 Subject: [PATCH 254/275] Translated using Weblate (German) Currently translated at 93.5% (843 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index bed8034bdf..57c4f1bed7 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -911,5 +911,6 @@ "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein zukünftiger Benutzername auf dem Heimserver. Alternativ kannst du auch einen anderen Server auswählen.", "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", "Home": "Start", - "Username invalid: %(errMessage)s": "Ungültiger Benutzername: %(errMessage)s" + "Username invalid: %(errMessage)s": "Ungültiger Benutzername: %(errMessage)s", + "a room": "einen Raum" } From b88c46a509c4c4c86fb6b17ad841150106fce8e9 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Thu, 8 Jun 2017 16:04:10 +0000 Subject: [PATCH 255/275] Translated using Weblate (German) Currently translated at 93.5% (843 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 57c4f1bed7..11d58a355e 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -912,5 +912,6 @@ "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", "Home": "Start", "Username invalid: %(errMessage)s": "Ungültiger Benutzername: %(errMessage)s", - "a room": "einen Raum" + "a room": "einen Raum", + "Accept": "Akzeptieren" } From 7f4368e2d1396278085722537827861934dc721b Mon Sep 17 00:00:00 2001 From: Bamstam Date: Thu, 8 Jun 2017 16:04:10 +0000 Subject: [PATCH 256/275] Translated using Weblate (German) Currently translated at 93.7% (845 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 11d58a355e..1db20bf77e 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -913,5 +913,6 @@ "Home": "Start", "Username invalid: %(errMessage)s": "Ungültiger Benutzername: %(errMessage)s", "a room": "einen Raum", - "Accept": "Akzeptieren" + "Accept": "Akzeptieren", + "Active call (%(roomName)s)": "Aktiver Anruf (%(roomName)s)" } From 0df1e9b9d8f1e04d81e2f469cd6a93e03493a1f1 Mon Sep 17 00:00:00 2001 From: Bamstam Date: Thu, 8 Jun 2017 16:04:10 +0000 Subject: [PATCH 257/275] Translated using Weblate (German) Currently translated at 93.8% (846 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 1db20bf77e..4ed5275b92 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -914,5 +914,6 @@ "Username invalid: %(errMessage)s": "Ungültiger Benutzername: %(errMessage)s", "a room": "einen Raum", "Accept": "Akzeptieren", - "Active call (%(roomName)s)": "Aktiver Anruf (%(roomName)s)" + "Active call (%(roomName)s)": "Aktiver Anruf (%(roomName)s)", + "Admin tools": "Admin-Werkzeuge" } From 0dc8e3adbd2cadeff090a84115f9a5d4d887de5d Mon Sep 17 00:00:00 2001 From: Krombel Date: Fri, 9 Jun 2017 11:41:41 +0000 Subject: [PATCH 258/275] Translated using Weblate (German) Currently translated at 100.0% (901 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 57 ++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 4ed5275b92..15189a1372 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -915,5 +915,60 @@ "a room": "einen Raum", "Accept": "Akzeptieren", "Active call (%(roomName)s)": "Aktiver Anruf (%(roomName)s)", - "Admin tools": "Admin-Werkzeuge" + "Admin tools": "Admin-Werkzeuge", + "And %(count)s more...": "Und %(count)s weitere...", + "Alias (optional)": "Alias (optional)", + "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Verbindung zum Heimserver fehlgeschlagen - bitte prüfe deine Verbindung, stelle sicher, dass dem SSL-Zertifikat deines Heimservers vertraut wird und keine Browser-Erweiterung Anfragen blockiert.", + "Click here to join the discussion!": "Klicke hier um der Diskussion beizuwohnen!", + "Close": "Schließen", + "Custom": "Erweitert", + "Decline": "Ablehnen", + "Disable Notifications": "Benachrichtigungen deaktivieren", + "Drop File Here": "Lasse Datei hier los", + "Enable Notifications": "Benachrichtigungen aktivieren", + "Encrypted by a verified device": "Von einem vertrauten Gerät verschlüsselt", + "Encrypted by an unverified device": "Von einem nicht vertrauten Gerät verschlüsselt", + "Failed to upload profile picture!": "Hochladen des Profilbild's fehlgeschlagen!", + "Incoming call from %(name)s": "Eingehender Anruf von %(name)s", + "Incoming video call from %(name)s": "Eingehender Video-Anruf von %(name)s", + "Incoming voice call from %(name)s": "Eingehender Sprach-Anruf von %(name)s", + "Join as voice or video.": "Mit Sprache oder Video beitreten.", + "Last seen": "Zuletzt gesehen", + "Level:": "Level:", + "No display name": "Kein Anzeigename", + "Otherwise, click here to send a bug report.": "Ansonsten klicke hier um einen Fehlerbericht zu senden.", + "Private Chat": "Privater Chat", + "Public Chat": "Öffentlicher Chat", + "Reason: %(reasonText)s": "Grund: %(reasonText)s", + "Rejoin": "Erneut beitreten", + "Room contains unknown devices": "Raum enthält unbekannte Geräte", + "%(roomName)s does not exist.": "%(roomName)s existert nicht.", + "%(roomName)s is not accessible at this time.": "%(roomName)s ist aktuell nicht zugreifbar.", + "Searching known users": "Suche nach bekannten Nutzern", + "Seen by %(userName)s at %(dateTime)s": "Gesehen von %(userName)s um %(dateTime)s", + "Send anyway": "Trotzdem senden", + "Set": "Setze", + "Start authentication": "Starte Authentifizierung", + "Show Text Formatting Toolbar": "Zeige text-formatierende Werkzeugleiste", + "This invitation was sent to an email address which is not associated with this account:": "Diese Einledung wurde an eine E-Mail-Adresse gesendet, die nicht mit diesem Konto verknüpft ist:", + "This room": "Dieser Raum", + "To link to a room it must have an address.": "Um einen Raum zu verlinken, muss er eine Adresse haben.", + "Undecryptable": "Nicht entschlüsselbar", + "Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Kann nicht feststellen, ob die Adresse an die diese Einladung gesendet wurde mit einer übereinstimmt, die zu deinem Konto gehört.", + "Unencrypted message": "Nicht verschlüsselbare Nachricht", + "unknown caller": "Unbekannter Anrufer", + "Unnamed Room": "Unbenannter Raum", + "Unverified": "Nicht verifiziert", + "Upload new:": "Neue(s) hochladen:", + "%(user)s is a": "%(user)s ist ein", + "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (Berechtigungslevel %(powerLevelNumber)s)", + "Verified": "Verifiziert", + "Would you like to accept or decline this invitation?": "Möchtest du diese Einladung akzeptieren oder ablehnen?", + "You have been banned from %(roomName)s by %(userName)s.": "Du wurdest von %(userName)s aus dem Raum %(roomName)s verbannt.", + "You have been kicked from %(roomName)s by %(userName)s.": "Du wurdest von %(userName)s aus dem Raum %(roomName)s gekickt.", + "You may wish to login with a different account, or add this email to this account.": "Du möchtest dich evtl. mit einem anderen Konto anmelden oder diese E-Mail-Adresse diesem Konto hinzufügen.", + "Your home server does not support device management.": "Dein Heimserver unterstützt kein Geräte-Management.", + "(~%(count)s results).one": "(~%(count)s Ergebnis)", + "(~%(count)s results).other": "(~%(count)s Ergebnis)", + "Device Name": "Geräte-Name" } From ecc8abbfc96158ca7f0f5d43c5ab38f38ad2a8f2 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 9 Jun 2017 13:46:45 +0100 Subject: [PATCH 259/275] When ChatCreateOrReuseDialog is cancelled by a guest, go home --- src/components/structures/MatrixChat.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 9c166cf04a..0444368298 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -466,7 +466,7 @@ module.exports = React.createClass({ this.notifyNewScreen('home'); break; case 'view_set_mxid': - this._setMxId(); + this._setMxId(payload); break; case 'view_start_chat_or_reuse': this._chatCreateOrReuse(payload.user_id); @@ -680,7 +680,7 @@ module.exports = React.createClass({ }); }, - _setMxId: function() { + _setMxId: function(payload) { const SetMxIdDialog = sdk.getComponent('views.dialogs.SetMxIdDialog'); const close = Modal.createDialog(SetMxIdDialog, { homeserverUrl: MatrixClientPeg.get().getHomeserverUrl(), @@ -689,6 +689,11 @@ module.exports = React.createClass({ dis.dispatch({ action: 'cancel_after_sync_prepared', }); + if (payload.go_home_on_cancel) { + dis.dispatch({ + action: 'view_home_page', + }); + } return; } this.onRegistered(credentials); @@ -769,6 +774,11 @@ module.exports = React.createClass({ } dis.dispatch({ action: 'view_set_mxid', + // If the set_mxid dialog is cancelled, view /home because if the browser + // was pointing at /user/@someone:domain?action=chat, the URL needs to be + // reset so that they can revisit /user/.. // (and trigger + // `_chatCreateOrReuse` again) + go_home_on_cancel: true, }); return; } From d6da5c649410ff6814e77d8c312c1b4abc9bde98 Mon Sep 17 00:00:00 2001 From: dtygel Date: Fri, 9 Jun 2017 13:33:02 +0000 Subject: [PATCH 260/275] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (901 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/pt_BR/ --- src/i18n/strings/pt_BR.json | 60 ++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 3b4b94cab2..75d7a115b2 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -906,5 +906,63 @@ "Username not available": "Nome de usuária(o) indisponível", "Something went wrong!": "Algo deu errado!", "This will be your account name on the homeserver, or you can pick a different server.": "Este será seu nome de conta no Servidor de Base , ou então você pode escolher um servidor diferente.", - "If you already have a Matrix account you can log in instead.": "Se você já tem uma conta Matrix, pode também fazer login." + "If you already have a Matrix account you can log in instead.": "Se você já tem uma conta Matrix, pode também fazer login.", + "a room": "uma sala", + "Accept": "Aceitar", + "Active call (%(roomName)s)": "Chamada ativa (%(roomName)s)", + "Admin tools": "Ferramentas de administração", + "And %(count)s more...": "E mais %(count)s...", + "Alias (optional)": "Apelido (opcional)", + "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Não foi possível conectar ao Servidor de Base. Por favor, confira sua conectividade à internet, garanta que o certificado SSL do Servidor de Base é confiável, e que uma extensão do navegador não esteja bloqueando as requisições de rede.", + "Click here to join the discussion!": "Clique aqui para participar da conversa!", + "Close": "Fechar", + "Custom": "Personalizado", + "Decline": "Recusar", + "Disable Notifications": "Desabilitar notificações", + "Drop File Here": "Arraste o arquivo aqui", + "Enable Notifications": "Habilitar notificações", + "Encrypted by a verified device": "Criptografado por um dispositivo verificado", + "Encrypted by an unverified device": "Criptografado por um dispositivo não verificado", + "Failed to upload profile picture!": "Falha ao enviar a imagem de perfil!", + "Incoming call from %(name)s": "Chamada de %(name)s recebida", + "Incoming video call from %(name)s": "Chamada de vídeo de %(name)s recebida", + "Incoming voice call from %(name)s": "Chamada de voz de %(name)s recebida", + "Join as voice or video.": "Participar por voz ou por vídeo.", + "Last seen": "Último uso", + "Level:": "Nível:", + "No display name": "Sem nome público de usuária(o)", + "Otherwise, click here to send a bug report.": "Caso contrário, clique aqui para enviar um relatório de erros.", + "Private Chat": "Conversa privada", + "Public Chat": "Conversa pública", + "Reason: %(reasonText)s": "Justificativa: %(reasonText)s", + "Rejoin": "Voltar a participar da sala", + "Room contains unknown devices": "Esta sala contém dispositivos desconhecidos", + "%(roomName)s does not exist.": "%(roomName)s não existe.", + "%(roomName)s is not accessible at this time.": "%(roomName)s não está acessível neste momento.", + "Seen by %(userName)s at %(dateTime)s": "Visto por %(userName)s em %(dateTime)s", + "Send anyway": "Enviar de qualquer maneira", + "Set": "Definir", + "Show Text Formatting Toolbar": "Exibir barra de formatação de texto", + "Start authentication": "Iniciar autenticação", + "This invitation was sent to an email address which is not associated with this account:": "Este convite foi enviado para um endereço de e-mail que não é associado a esta conta:", + "This room": "Esta sala", + "To link to a room it must have an address.": "Para produzir um link para uma sala, ela necessita ter um endereço.", + "Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Não foi possível garantir que o endereço para o qual este convite foi enviado bate com alqum que está associado com sua conta.", + "Undecryptable": "Não é possível descriptografar", + "Unencrypted message": "Mensagem não criptografada", + "unknown caller": "a pessoa que está chamando é desconhecida", + "Unnamed Room": "Sala sem nome", + "Unverified": "Não verificado", + "Upload new:": "Enviar novo:", + "%(user)s is a": "%(user)s é um(a)", + "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (nível de permissão %(powerLevelNumber)s)", + "Verified": "Verificado", + "Would you like to accept or decline this invitation?": "Você gostaria de aceitar ou recusar este convite?", + "You have been banned from %(roomName)s by %(userName)s.": "Você foi expulso(a) da sala %(roomName)s por %(userName)s.", + "You have been kicked from %(roomName)s by %(userName)s.": "Você foi removido(a) da sala %(roomName)s por %(userName)s.", + "You may wish to login with a different account, or add this email to this account.": "Você pode querer fazer login com uma conta diferente, ou adicionar este e-mail a esta conta.", + "Your home server does not support device management.": "O seu Servidor de Base não suporta o gerenciamento de dispositivos.", + "(~%(count)s results).one": "(~%(count)s resultado)", + "(~%(count)s results).other": "(~%(count)s resultados)", + "Device Name": "Nome do dispositivo" } From 6126cce96779fc21ce9b06972f5ee8d7ca05cdda Mon Sep 17 00:00:00 2001 From: Szimszon Date: Fri, 9 Jun 2017 12:55:52 +0000 Subject: [PATCH 261/275] Translated using Weblate (Hungarian) Currently translated at 19.4% (175 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/hu/ --- src/i18n/strings/hu.json | 151 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 748810f76e..458d461b90 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -24,5 +24,154 @@ "Wednesday": "Szerda", "Thursday": "Csütörtök", "Friday": "Péntek", - "Saturday": "Szombat" + "Saturday": "Szombat", + "af": "Afrikaans", + "ar-ae": "Arabic (U.A.E.)", + "ar-bh": "Arabic (Bahrain)", + "ar-dz": "Arabic (Algeria)", + "ar-eg": "Arabic (Egypt)", + "ar-iq": "Arabic (Iraq)", + "ar-jo": "Arabic (Jordan)", + "ar-kw": "Arabic (Kuwait)", + "ar-lb": "Arabic (Lebanon)", + "ar-ly": "Arabic (Libya)", + "ar-ma": "Arabic (Morocco)", + "ar-om": "Arabic (Oman)", + "ar-qa": "Arabic (Qatar)", + "ar-sa": "Arabic (Saudi Arabia)", + "ar-sy": "Arabic (Syria)", + "ar-tn": "Arabic (Tunisia)", + "ar-ye": "Arabic (Yemen)", + "be": "Belorusz", + "bg": "Bolgár", + "ca": "Katalán", + "cs": "Cseh", + "da": "Dán", + "de-at": "Német (Osztrák)", + "de-ch": "Német (Svájci)", + "de": "Német", + "de-li": "Német (Lichtenstein)", + "de-lu": "Német (Luxemburg)", + "el": "Görög", + "en-au": "Angol (Ausztrál)", + "en-bz": "Angol (Belize)", + "en-ca": "Angol (Kanada)", + "en": "Angol", + "en-gb": "Angol (Egyesült Királyság)", + "en-ie": "Angol (Ír)", + "en-jm": "Angol (Jamaika)", + "en-nz": "Angol (Új-Zéland)", + "en-tt": "Angol (Trinidad)", + "en-us": "Angol (Egyesült Államok)", + "en-za": "Angol (Dél-Afrika)", + "es-ar": "Spanyol (Argentína)", + "es-bo": "Spanyol (Bolívia)", + "es-cl": "Spanyol (Chile)", + "es-co": "Spanyol (Kolumbia)", + "es-cr": "Spanyol (Costa Rica)", + "es-do": "Spanyol (Dominikai Köztársaság)", + "es-ec": "Spanyol (Ecuador)", + "es-gt": "Spanyol (Guatemala)", + "es-hn": "Spanyol (Honduras)", + "es-mx": "Spanyol (Mexikó)", + "es-ni": "Spanyol (Nicaragua)", + "es-pa": "Spanyol (Panama)", + "es-pe": "Spanyol (Peru)", + "es-pr": "Spanyol (Puerto Rico)", + "es-py": "Spanyol (Paraguay)", + "es": "Spanyol (Spanyol)", + "es-sv": "Spanyol (El Salvador)", + "es-uy": "Spanyol (Uruguay)", + "es-ve": "Spanyol (Venezuela)", + "et": "Észt", + "eu": "Baszk (Baszk)", + "fa": "Perzsa", + "fi": "Finn", + "fo": "Feröer", + "fr-be": "Francia (Belgium)", + "fr-ca": "Francia (Kanada)", + "fr-ch": "Francia (Svájc)", + "fr": "Francia", + "fr-lu": "Francia (Luxemburg)", + "ga": "Ír", + "gd": "Gall (Skót)", + "he": "Héber", + "hi": "Hindu", + "hr": "Horvát", + "hu": "Magyar", + "id": "Indonéz", + "is": "Izland", + "it-ch": "Olasz (Svájc)", + "it": "Olasz", + "ja": "Japán", + "ji": "Jiddis", + "ko": "Korea", + "lt": "Litván", + "lv": "Lett", + "mk": "Macedónia (FYROM)", + "ms": "Maláj", + "mt": "Málta", + "nl-be": "Holland (Belgium)", + "nl": "Holland", + "no": "Norvég", + "pl": "Lengyel", + "pt-br": "Portugál (Brazil)", + "pt": "Portugál", + "ro-mo": "Román (Moldova)", + "ro": "Román", + "ru-mo": "Orosz (Moldova)", + "ru": "Orosz", + "sk": "Szlovák", + "sl": "Szlovén", + "sq": "Albán", + "sr": "Szerb", + "sv-fi": "Svéd (Finn)", + "sv": "Svéd", + "sx": "Sutu", + "sz": "Sami (Lapp)", + "th": "Thai", + "tr": "Török", + "ts": "Tsonga", + "uk": "Ukrán", + "ur": "Urdu", + "ve": "Venda", + "vi": "Vietnám", + "xh": "Xhosa", + "zh-cn": "Kína (PRC)", + "zh-hk": "Kína (Hong Kong SAR)", + "zh-sg": "Kína (Szingapúr)", + "zh-tw": "Kína (Tajvan)", + "zu": "Zulu", + "A registered account is required for this action": "Regisztrált fiókra van szükség ehhez a művelethez", + "a room": "egy szoba", + "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Elküldtük a szöveges üzenetet ide: +%(msisdn)s. Kérlek add meg az ellenőrző kódot ami benne van", + "Accept": "Elfogad", + "%(targetName)s accepted an invitation.": "%(targetName)s elfogadta a meghívást.", + "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s elfogadta a meghívást ide: %(displayName)s.", + "Account": "Fiók", + "Access Token:": "Elérési kulcs:", + "Active call (%(roomName)s)": "Hívás folyamatban (%(roomName)s)", + "Add": "Hozzáad", + "Add a topic": "Téma megadása", + "Add email address": "E-mail cím megadása", + "Add phone number": "Telefonszám megadása", + "Admin": "Adminisztrátor", + "Admin tools": "Admin. eszközök", + "And %(count)s more...": "És még %(count)s...", + "VoIP": "VoIP", + "Missing Media Permissions, click here to request.": "Hiányzó Média jogosultság, kattintson ide az igényléshez.", + "No Microphones detected": "Nem található mikrofon", + "No Webcams detected": "Nem található webkamera", + "No media permissions": "Nincs media jogosultság", + "You may need to manually permit Riot to access your microphone/webcam": "Lehet hogy manuálisan kell engedélyeznie a Riot-nak a hozzáférést a mikrofonhoz ás webkamerához", + "Default Device": "Alapértelmezett eszköz", + "Microphone": "Mikrofon", + "Camera": "Kamera", + "Advanced": "Haladó", + "Algorithm": "Algoritmus", + "Hide removed messages": "Törölt üzenetek elrejtése", + "Always show message timestamps": "Üzenet időbélyeg folyamatos megjelenítése", + "Authentication": "Azonosítás", + "Alias (optional)": "Becenév (opcionális)", + "all room members": "minden szoba tagság" } From 0b76b94063dec0a356addd5af1745d9f637c575d Mon Sep 17 00:00:00 2001 From: Vladi Date: Fri, 9 Jun 2017 13:04:08 +0000 Subject: [PATCH 262/275] Translated using Weblate (Russian) Currently translated at 99.4% (896 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.nordgedanken.de/projects/riot-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 52e69c9388..07ab24e824 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -169,8 +169,8 @@ "Unable to remove contact information": "Невозможно удалить контактную информацию", "Unable to verify email address.": "Невозможно проверить адрес электронной почты.", "Unban": "Отменить запрет", - "Unencrypted room": "Не зашифрованная комната", - "unencrypted": "не зашифровано", + "Unencrypted room": "Незашифрованная комната", + "unencrypted": "незашифровано", "unknown device": "неизвестное устройство", "unknown error code": "неизвестная ошибка", "unknown": "неизвестно", @@ -926,5 +926,27 @@ "Start authentication": "Начать идентификацию", "This room": "Эта комната", "(~%(count)s results).other": "(~%(count)s results)", - "Device Name": "Имя устройства" + "Device Name": "Имя устройства", + "Custom": "Пользователь", + "Decline": "Отклонить", + "Room contains unknown devices": "Комната содержит неизвестное устройство", + "%(roomName)s does not exist.": "%(roomName)s не существует.", + "%(roomName)s is not accessible at this time.": "%(roomName)s в данный момент не доступна.", + "Seen by %(userName)s at %(dateTime)s": "Отослать от %(userName)s в %(dateTime)s", + "Send anyway": "Отправить в любом случае", + "Show Text Formatting Toolbar": "Показать панель инструментов форматирования текста", + "This invitation was sent to an email address which is not associated with this account:": "Это приглашение было отправлено на адрес электронной почты, который не связан с этой учетной записью:", + "To link to a room it must have an address.": "Для ссылки на комнату. Она должна иметь адрес.", + "Unable to ascertain that the address this invite was sent to matches one associated with your account.": "Не удалось установить, что адрес на который было отправлено это приглашение соответствует вашей учетной записи.", + "Undecryptable": "Невозможно расшифровать", + "Unencrypted message": "Незашифрованое послание", + "unknown caller": "Звонящий неизвестен", + "Unnamed Room": "Комната без имени", + "Unverified": "Непроверенно", + "Upload new:": "Загрузить новый:", + "%(user)s is a": "%(user)s является", + "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (уровень доступа %(powerLevelNumber)s)", + "Verified": "Подтверждён", + "Would you like to accept or decline this invitation?": "Хотели бы вы это приглашение подтвердить или отклонить?", + "(~%(count)s results).one": "(~%(count)s Результат)" } From 0879d796ebce94d2a335d3a0adb1d33900b7f31f Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 20:26:41 +0100 Subject: [PATCH 263/275] released js-sdk --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15a903c25a..dd7ff9c11e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.3", "lodash": "^4.13.1", - "matrix-js-sdk": "0.7.10", + "matrix-js-sdk": "0.7.11-rc.1", "optimist": "^0.6.1", "prop-types": "^15.5.8", "q": "^1.4.1", From 345661ee2ddf1a0e524bca1cb815df8c3b4f7247 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 20:28:08 +0100 Subject: [PATCH 264/275] Prepare changelog for v0.9.3-rc.1 --- CHANGELOG.md | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66e4627afd..b217d7a0db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,154 @@ +Changes in [0.9.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.3-rc.1) (2017-06-09) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.2...v0.9.3-rc.1) + + * When ChatCreateOrReuseDialog is cancelled by a guest, go home + [\#1069](https://github.com/matrix-org/matrix-react-sdk/pull/1069) + * Update from Weblate. + [\#1065](https://github.com/matrix-org/matrix-react-sdk/pull/1065) + * Goto /home when forgetting the last room + [\#1067](https://github.com/matrix-org/matrix-react-sdk/pull/1067) + * Default to home page when settings is closed + [\#1066](https://github.com/matrix-org/matrix-react-sdk/pull/1066) + * Update from Weblate. + [\#1063](https://github.com/matrix-org/matrix-react-sdk/pull/1063) + * When joining, use a roomAlias if we have it + [\#1062](https://github.com/matrix-org/matrix-react-sdk/pull/1062) + * Control currently viewed event via RoomViewStore + [\#1058](https://github.com/matrix-org/matrix-react-sdk/pull/1058) + * Better error messages for login + [\#1060](https://github.com/matrix-org/matrix-react-sdk/pull/1060) + * Add remaining translations + [\#1056](https://github.com/matrix-org/matrix-react-sdk/pull/1056) + * Added button that copies code to clipboard + [\#1040](https://github.com/matrix-org/matrix-react-sdk/pull/1040) + * de-lint MegolmExportEncryption + test + [\#1059](https://github.com/matrix-org/matrix-react-sdk/pull/1059) + * Better RTL support + [\#1021](https://github.com/matrix-org/matrix-react-sdk/pull/1021) + * make mels emoji capable + [\#1057](https://github.com/matrix-org/matrix-react-sdk/pull/1057) + * Make travis check for lint on files which are clean to start with + [\#1055](https://github.com/matrix-org/matrix-react-sdk/pull/1055) + * Update from Weblate. + [\#1053](https://github.com/matrix-org/matrix-react-sdk/pull/1053) + * Add some logging around switching rooms + [\#1054](https://github.com/matrix-org/matrix-react-sdk/pull/1054) + * Update from Weblate. + [\#1052](https://github.com/matrix-org/matrix-react-sdk/pull/1052) + * Use user_directory endpoint to populate ChatInviteDialog + [\#1050](https://github.com/matrix-org/matrix-react-sdk/pull/1050) + * Various Analytics changes/fixes/improvements + [\#1046](https://github.com/matrix-org/matrix-react-sdk/pull/1046) + * Use an arrow function to allow `this` + [\#1051](https://github.com/matrix-org/matrix-react-sdk/pull/1051) + * New guest access + [\#937](https://github.com/matrix-org/matrix-react-sdk/pull/937) + * Translate src/components/structures + [\#1048](https://github.com/matrix-org/matrix-react-sdk/pull/1048) + * Cancel 'join room' action if 'log in' is clicked + [\#1049](https://github.com/matrix-org/matrix-react-sdk/pull/1049) + * fix copy and paste derp and rip out unused imports + [\#1015](https://github.com/matrix-org/matrix-react-sdk/pull/1015) + * Update from Weblate. + [\#1042](https://github.com/matrix-org/matrix-react-sdk/pull/1042) + * Reset 'first sync' flag / promise on log in + [\#1041](https://github.com/matrix-org/matrix-react-sdk/pull/1041) + * Remove DM-guessing code (again) + [\#1036](https://github.com/matrix-org/matrix-react-sdk/pull/1036) + * Cancel deferred actions + [\#1039](https://github.com/matrix-org/matrix-react-sdk/pull/1039) + * Merge develop, add i18n for SetMxIdDialog + [\#1034](https://github.com/matrix-org/matrix-react-sdk/pull/1034) + * Defer an intention for creating a room + [\#1038](https://github.com/matrix-org/matrix-react-sdk/pull/1038) + * Fix 'create room' button + [\#1037](https://github.com/matrix-org/matrix-react-sdk/pull/1037) + * Always show the spinner during the first sync + [\#1033](https://github.com/matrix-org/matrix-react-sdk/pull/1033) + * Only view welcome user if we are not looking at a room + [\#1032](https://github.com/matrix-org/matrix-react-sdk/pull/1032) + * Update from Weblate. + [\#1030](https://github.com/matrix-org/matrix-react-sdk/pull/1030) + * Keep deferred actions for view_user_settings and view_create_chat + [\#1031](https://github.com/matrix-org/matrix-react-sdk/pull/1031) + * Don't do a deferred start chat if user is welcome user + [\#1029](https://github.com/matrix-org/matrix-react-sdk/pull/1029) + * Introduce state `peekLoading` to avoid collision with `roomLoading` + [\#1028](https://github.com/matrix-org/matrix-react-sdk/pull/1028) + * Update from Weblate. + [\#1016](https://github.com/matrix-org/matrix-react-sdk/pull/1016) + * Fix accepting a 3pid invite + [\#1013](https://github.com/matrix-org/matrix-react-sdk/pull/1013) + * Propagate room join errors to the UI + [\#1007](https://github.com/matrix-org/matrix-react-sdk/pull/1007) + * Implement /user/@userid:domain?action=chat + [\#1006](https://github.com/matrix-org/matrix-react-sdk/pull/1006) + * Show People/Rooms emptySubListTip even when total rooms !== 0 + [\#967](https://github.com/matrix-org/matrix-react-sdk/pull/967) + * Fix to show the correct room + [\#995](https://github.com/matrix-org/matrix-react-sdk/pull/995) + * Remove cachedPassword from localStorage on_logged_out + [\#977](https://github.com/matrix-org/matrix-react-sdk/pull/977) + * Add /start to show the setMxId above HomePage + [\#964](https://github.com/matrix-org/matrix-react-sdk/pull/964) + * Allow pressing Enter to submit setMxId + [\#961](https://github.com/matrix-org/matrix-react-sdk/pull/961) + * add login link to SetMxIdDialog + [\#954](https://github.com/matrix-org/matrix-react-sdk/pull/954) + * Block user settings with view_set_mxid + [\#936](https://github.com/matrix-org/matrix-react-sdk/pull/936) + * Show "Something went wrong!" when errcode undefined + [\#935](https://github.com/matrix-org/matrix-react-sdk/pull/935) + * Reset store state when logging out + [\#930](https://github.com/matrix-org/matrix-react-sdk/pull/930) + * Set the displayname to the mxid once PWLU + [\#933](https://github.com/matrix-org/matrix-react-sdk/pull/933) + * Fix view_next_room, view_previous_room and view_indexed_room + [\#929](https://github.com/matrix-org/matrix-react-sdk/pull/929) + * Use RVS to indicate "joining" when setting a mxid + [\#928](https://github.com/matrix-org/matrix-react-sdk/pull/928) + * Don't show notif nag bar if guest + [\#932](https://github.com/matrix-org/matrix-react-sdk/pull/932) + * Show "Password" instead of "New Password" + [\#927](https://github.com/matrix-org/matrix-react-sdk/pull/927) + * Remove warm-fuzzy after setting mxid + [\#926](https://github.com/matrix-org/matrix-react-sdk/pull/926) + * Allow teamServerConfig to be missing + [\#925](https://github.com/matrix-org/matrix-react-sdk/pull/925) + * Remove GuestWarningBar + [\#923](https://github.com/matrix-org/matrix-react-sdk/pull/923) + * Make left panel better for new users (mk III) + [\#924](https://github.com/matrix-org/matrix-react-sdk/pull/924) + * Implement default welcome page and allow custom URL /w config + [\#922](https://github.com/matrix-org/matrix-react-sdk/pull/922) + * Implement a store for RoomView + [\#921](https://github.com/matrix-org/matrix-react-sdk/pull/921) + * Add prop to toggle whether new password input is autoFocused + [\#915](https://github.com/matrix-org/matrix-react-sdk/pull/915) + * Implement warm-fuzzy success dialog for SetMxIdDialog + [\#905](https://github.com/matrix-org/matrix-react-sdk/pull/905) + * Write some tests for the RTS UI + [\#893](https://github.com/matrix-org/matrix-react-sdk/pull/893) + * Make confirmation optional on ChangePassword + [\#890](https://github.com/matrix-org/matrix-react-sdk/pull/890) + * Remove "Current Password" input if mx_pass exists + [\#881](https://github.com/matrix-org/matrix-react-sdk/pull/881) + * Replace NeedToRegisterDialog /w SetMxIdDialog + [\#889](https://github.com/matrix-org/matrix-react-sdk/pull/889) + * Invite the welcome user after registration if configured + [\#882](https://github.com/matrix-org/matrix-react-sdk/pull/882) + * Prevent ROUs from creating new chats/new rooms + [\#879](https://github.com/matrix-org/matrix-react-sdk/pull/879) + * Redesign mxID chooser, add availability checking + [\#877](https://github.com/matrix-org/matrix-react-sdk/pull/877) + * Show password nag bar when user is PWLU + [\#864](https://github.com/matrix-org/matrix-react-sdk/pull/864) + * fix typo + [\#858](https://github.com/matrix-org/matrix-react-sdk/pull/858) + * Initial implementation: SetDisplayName -> SetMxIdDialog + [\#849](https://github.com/matrix-org/matrix-react-sdk/pull/849) + Changes in [0.9.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.2) (2017-06-06) =================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.1...v0.9.2) From 27592728f50dce51b1edebcc6fea38bb10f84788 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 20:28:09 +0100 Subject: [PATCH 265/275] v0.9.3-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dd7ff9c11e..557ffe8aa4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.9.2", + "version": "0.9.3-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From c61942ed5db51b77e67aea1232acb0d484443b14 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 21:42:34 +0100 Subject: [PATCH 266/275] We now require flux 2.1 because we use utils --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 557ffe8aa4..595bedd374 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "emojione": "2.2.3", "file-saver": "^1.3.3", "filesize": "3.5.6", - "flux": "^2.0.3", + "flux": "2.1.1", "fuse.js": "^2.2.0", "glob": "^5.0.14", "highlight.js": "^8.9.1", From d6b85c9d4dc768527c1312d18759f4f8ff0b86b5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 22:06:43 +0100 Subject: [PATCH 267/275] Fix translations on conf call banner * You can't substitute react elements into a text string * Substituting in undefined gives the string 'undefined', so initialise it to the empty string. --- src/components/views/rooms/AuxPanel.js | 11 ++++++++--- src/i18n/strings/de_DE.json | 2 +- src/i18n/strings/en_EN.json | 2 +- src/i18n/strings/en_US.json | 2 +- src/i18n/strings/fr.json | 2 +- src/i18n/strings/pt.json | 2 +- src/i18n/strings/pt_BR.json | 2 +- src/i18n/strings/ru.json | 2 +- src/i18n/strings/zh_Hant.json | 2 +- 9 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js index 55b68d1eb1..acb9c76aa0 100644 --- a/src/components/views/rooms/AuxPanel.js +++ b/src/components/views/rooms/AuxPanel.js @@ -89,12 +89,13 @@ module.exports = React.createClass({ var conferenceCallNotification = null; if (this.props.displayConfCallNotification) { - var supportedText, joinText; + let supportedText = ''; + let joinNode; if (!MatrixClientPeg.get().supportsVoip()) { supportedText = _t(" (unsupported)"); } else { - joinText = ( + joinNode = ( {_tJsx( "Join as voice or video.", [/(.*?)<\/voiceText>/, /(.*?)<\/videoText>/], @@ -106,9 +107,13 @@ module.exports = React.createClass({ ); } + // XXX: the translation here isn't great: appending ' (unsupported)' is likely to not make sense in many languages, + // but there are translations for this in the languages we do have so I'm leaving it for now. conferenceCallNotification = (
    - {_t("Ongoing conference call%(supportedText)s. %(joinText)s", {supportedText: supportedText, joinText: joinText})} + {_t("Ongoing conference call%(supportedText)s.", {supportedText: supportedText})} +   + {joinNode}
    ); } diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 15189a1372..699914d7ea 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -814,7 +814,7 @@ "Drop file here to upload": "Datei hier loslassen zum hochladen", "Idle": "Untätig", "We recommend you go through the verification process for each device to confirm they belong to their legitimate owner, but you can resend the message without verifying if you prefer.": "Wir empfehlen dir für jedes Gerät durch den Verifizierungsprozess zu gehen um zu bestätigen, dass sie ihrem legitimierten Besitzer gehören, aber du kannst die Nachrichten ohne Verifizierung erneut senden, wenn du es vorziehst.", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Laufendes Konferenzgespräch%(supportedText)s. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Laufendes Konferenzgespräch%(supportedText)s.", "You are about to be taken to a third-party site so you can authenticate your account for use with %(integrationsUrl)s. Do you wish to continue?": "Du wirst jetzt auf die Website eines Drittanbieters weitergeleitet, damit du dein Konto für die Verwendung von %(integrationsUrl)s authentifizieren kannst. Möchtest du fortfahren?", "Disable URL previews for this room (affects only you)": "URL-Vorschau für diesen Raum deaktivieren (betrifft nur dich)", "Start automatically after system login": "Starte automatisch nach System-Login", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c7c6cd6ef3..c2fab535b0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -887,7 +887,7 @@ "Enable URL previews for this room (affects only you)": "Enable URL previews for this room (affects only you)", "Drop file here to upload": "Drop file here to upload", " (unsupported)": " (unsupported)", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Ongoing conference call%(supportedText)s. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Ongoing conference call%(supportedText)s.", "for %(amount)ss": "for %(amount)ss", "for %(amount)sm": "for %(amount)sm", "for %(amount)sh": "for %(amount)sh", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index 5cdfd65d27..20041ef231 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -813,7 +813,7 @@ "Enable URL previews for this room (affects only you)": "Enable URL previews for this room (affects only you)", "Drop file here to upload": "Drop file here to upload", " (unsupported)": " (unsupported)", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Ongoing conference call%(supportedText)s. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Ongoing conference call%(supportedText)s.", "for %(amount)ss": "for %(amount)ss", "for %(amount)sm": "for %(amount)sm", "for %(amount)sh": "for %(amount)sh", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 712ccb2a63..4b074b63ea 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -759,7 +759,7 @@ "Enable URL previews for this room (affects only you)": "Activer les aperçus d'URL pour ce salon (n'affecte que vous)", "Drop file here to upload": "Déposer le fichier ici pour le télécharger", " (unsupported)": " (non supporté)", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Appel conférence en cours%(supportedText)s. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Appel conférence en cours%(supportedText)s.", "Online": "En ligne", "Offline": "Déconnecté", "Disable URL previews for this room (affects only you)": "Désactiver les aperçus d'URL pour ce salon (n'affecte que vous)", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 850e95f61f..d366fb7e66 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -808,7 +808,7 @@ "Enable URL previews for this room (affects only you)": "Habilitar pré-visualizações de links para esta sala (afeta somente a você)", "Drop file here to upload": "Arraste um arquivo aqui para enviar", " (unsupported)": " (não suportado)", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Conferência%(supportedText)s em andamento. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Conferência%(supportedText)s em andamento.", "Online": "Online", "Idle": "Ocioso", "Offline": "Offline", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 75d7a115b2..118c2445a6 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -808,7 +808,7 @@ "Enable URL previews for this room (affects only you)": "Habilitar pré-visualizações de links para esta sala (afeta somente a você)", "Drop file here to upload": "Arraste um arquivo aqui para enviar", " (unsupported)": " (não suportado)", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Conferência%(supportedText)s em andamento. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Conferência%(supportedText)s em andamento.", "Online": "Online", "Idle": "Ocioso", "Offline": "Offline", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 07ab24e824..6bcfa680c6 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -853,7 +853,7 @@ "Enable URL previews for this room (affects only you)": "Включить предпросмотр URL в этой комнате (только для вас)", "Drop file here to upload": "Перетащите файл сюда для загрузки", " (unsupported)": " (не поддерживается)", - "Ongoing conference call%(supportedText)s. %(joinText)s": "Идет конференц-звонок%(supportedText)s. %(joinText)s", + "Ongoing conference call%(supportedText)s.": "Идет конференц-звонок%(supportedText)s.", "for %(amount)ss": "уже %(amount)sс", "for %(amount)sm": "уже %(amount)sм", "for %(amount)sh": "уже %(amount)sч", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index b2e1939565..140e7a7b2d 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -353,7 +353,7 @@ "This image cannot be displayed.": "這張圖片無法顯示", "Error decrypting video": "解密影片出錯", "Add an Integration": "新增整合器", - "Ongoing conference call%(supportedText)s. %(joinText)s": "%(supportedText)s. %(joinText)s 正在進行電話會議", + "Ongoing conference call%(supportedText)s.": "%(supportedText)s. 正在進行電話會議", " (unsupported)": " (不支持)", "URL Previews": "網址預覽", "Enable URL previews for this room (affects only you)": "啟用此房間的網址預覽(僅影響您)", From 8bb26073bec724e93f75dff82efd6a97aea66e5f Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 22:13:53 +0100 Subject: [PATCH 268/275] Prepare changelog for v0.9.3-rc.2 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b217d7a0db..651303d3b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [0.9.3-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.3-rc.2) (2017-06-09) +============================================================================================================= +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.3-rc.1...v0.9.3-rc.2) + + * Fix flux dependency + * Fix translations on conference call bar + Changes in [0.9.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.3-rc.1) (2017-06-09) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.2...v0.9.3-rc.1) From 336b10daf11ce819afeee473e927c94ee1a5b425 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 9 Jun 2017 22:13:54 +0100 Subject: [PATCH 269/275] v0.9.3-rc.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 595bedd374..7e2ad6d064 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.9.3-rc.1", + "version": "0.9.3-rc.2", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 29355a610f000b44a1937e4824bd0a9f6362ebd3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 12 Jun 2017 15:19:52 +0100 Subject: [PATCH 270/275] js-sdk 0.7.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7e2ad6d064..1b57cc6890 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "isomorphic-fetch": "^2.2.1", "linkifyjs": "^2.1.3", "lodash": "^4.13.1", - "matrix-js-sdk": "0.7.11-rc.1", + "matrix-js-sdk": "0.7.11", "optimist": "^0.6.1", "prop-types": "^15.5.8", "q": "^1.4.1", From 613318658319160d7db2b4dfbd0d3ac3cdde1660 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 9 Jun 2017 22:19:14 +0100 Subject: [PATCH 271/275] fullstop fails --- .../views/elements/MemberEventListSummary.js | 28 +++++++++---------- src/i18n/strings/de_DE.json | 4 +-- src/i18n/strings/th.json | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js index f2f6da83e5..842b44b793 100644 --- a/src/components/views/elements/MemberEventListSummary.js +++ b/src/components/views/elements/MemberEventListSummary.js @@ -227,8 +227,7 @@ module.exports = React.createClass({ ? _t("%(severalUsers)sjoined", { severalUsers: "" }) : _t("%(oneUser)sjoined", { oneUser: "" }); } - - break; + break; case "left": if (repeats > 1) { res = (plural) @@ -238,7 +237,8 @@ module.exports = React.createClass({ res = (plural) ? _t("%(severalUsers)sleft", { severalUsers: "" }) : _t("%(oneUser)sleft", { oneUser: "" }); - } break; + } + break; case "joined_and_left": if (repeats > 1) { res = (plural) @@ -249,7 +249,7 @@ module.exports = React.createClass({ ? _t("%(severalUsers)sjoined and left", { severalUsers: "" }) : _t("%(oneUser)sjoined and left", { oneUser: "" }); } - break; + break; case "left_and_joined": if (repeats > 1) { res = (plural) @@ -259,8 +259,8 @@ module.exports = React.createClass({ res = (plural) ? _t("%(severalUsers)sleft and rejoined", { severalUsers: "" }) : _t("%(oneUser)sleft and rejoined", { oneUser: "" }); - } break; - break; + } + break; case "invite_reject": if (repeats > 1) { res = (plural) @@ -271,7 +271,7 @@ module.exports = React.createClass({ ? _t("%(severalUsers)srejected their invitations", { severalUsers: "" }) : _t("%(oneUser)srejected their invitation", { oneUser: "" }); } - break; + break; case "invite_withdrawal": if (repeats > 1) { res = (plural) @@ -282,7 +282,7 @@ module.exports = React.createClass({ ? _t("%(severalUsers)shad their invitations withdrawn", { severalUsers: "" }) : _t("%(oneUser)shad their invitation withdrawn", { oneUser: "" }); } - break; + break; case "invited": if (repeats > 1) { res = (plural) @@ -293,7 +293,7 @@ module.exports = React.createClass({ ? _t("were invited") : _t("was invited"); } - break; + break; case "banned": if (repeats > 1) { res = (plural) @@ -304,7 +304,7 @@ module.exports = React.createClass({ ? _t("were banned") : _t("was banned"); } - break; + break; case "unbanned": if (repeats > 1) { res = (plural) @@ -315,7 +315,7 @@ module.exports = React.createClass({ ? _t("were unbanned") : _t("was unbanned"); } - break; + break; case "kicked": if (repeats > 1) { res = (plural) @@ -326,7 +326,7 @@ module.exports = React.createClass({ ? _t("were kicked") : _t("was kicked"); } - break; + break; case "changed_name": if (repeats > 1) { res = (plural) @@ -337,7 +337,7 @@ module.exports = React.createClass({ ? _t("%(severalUsers)schanged their name", { severalUsers: "" }) : _t("%(oneUser)schanged their name", { oneUser: "" }); } - break; + break; case "changed_avatar": if (repeats > 1) { res = (plural) @@ -348,7 +348,7 @@ module.exports = React.createClass({ ? _t("%(severalUsers)schanged their avatar", { severalUsers: "" }) : _t("%(oneUser)schanged their avatar", { oneUser: "" }); } - break; + break; } return res; diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 699914d7ea..fbd49a6800 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -615,8 +615,8 @@ "%(actionVerb)s this person?": "Diese Person %(actionVerb)s?", "This room has no local addresses": "Dieser Raum hat keine lokale Adresse", "This room is private or inaccessible to guests. You may be able to join if you register": "Dieser Raum ist privat oder für Gäste nicht zugänglich. Du kannst jedoch eventuell beitreten, wenn du dich registrierst", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen", - "Tried to load a specific point in this room's timeline, but was unable to find it": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Versuchte einen spezifischen Punkt in der Raum-Chronik zu laden, aber du hast keine Berechtigung die angeforderte Nachricht anzuzeigen.", + "Tried to load a specific point in this room's timeline, but was unable to find it.": "Der Versuch, einen spezifischen Punkt im Chatverlauf zu laden, ist fehlgeschlagen. Der Punkt konnte nicht gefunden werden.", "Turn Markdown off": "Markdown deaktiveren", "Turn Markdown on": "Markdown einschalten", "Unable to load device list": "Geräteliste konnte nicht geladen werden", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 05116953f7..a54f7fee42 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -389,7 +389,7 @@ "Who would you like to add to this room?": "คุณต้องการเพิ่มใครเข้าห้องนี้?", "Who would you like to communicate with?": "คุณต้องการสื่อสารกับใคร?", "You're not in any rooms yet! Press": "คุณยังไม่ได้อยู่ในห้องใดเลย! กด", - "You are trying to access %(roomName)s": "คุณกำลังพยายามเข้าสู่ %(roomName)s", + "You are trying to access %(roomName)s.": "คุณกำลังพยายามเข้าสู่ %(roomName)s", "You have disabled URL previews by default.": "ค่าเริ่มต้นของคุณปิดใช้งานตัวอย่าง URL เอาไว้", "You have enabled URL previews by default.": "ค่าเริ่มต้นของคุณเปิดใช้งานตัวอย่าง URL เอาไว้", "you must be a": "คุณต้องเป็น", From 6afd8952911fb8ac3dddd2d49ad93ecfe5969398 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 9 Jun 2017 22:20:09 +0100 Subject: [PATCH 272/275] broken var --- src/i18n/strings/zh_Hant.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 140e7a7b2d..2d0ac27363 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -290,7 +290,7 @@ "Would you like to": "你要", "You are already in a call.": "你已在電話通話中", "You're not in any rooms yet! Press": "你尚未加入任何聊天室!請按", - "You are trying to access %(roomName)s.": "你將進入 %(roomName)聊天室", + "You are trying to access %(roomName)s.": "你將進入 %(roomName)s聊天室", "You cannot place a call with yourself.": "你不能打電話給自已", "You cannot place VoIP calls in this browser.": "在此瀏覽器下無法置入網路電話通話", "Sun": "星期日", From f98c491fddb60c8f64b71c0e287bcdcfa41dd97c Mon Sep 17 00:00:00 2001 From: Riot Translate Bot Date: Sun, 11 Jun 2017 20:40:20 +0100 Subject: [PATCH 273/275] Update from Weblate. (#1073) * Translated using Weblate (German) Currently translated at 93.4% (842 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Russian) Currently translated at 100.0% (901 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/ru/ * Added translation using Weblate (Arabic) * Translated using Weblate (Greek) Currently translated at 42.2% (381 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/el/ * Translated using Weblate (English (United States)) Currently translated at 91.8% (828 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/en_US/ * Translated using Weblate (Russian) Currently translated at 100.0% (901 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/ru/ * Translated using Weblate (German) Currently translated at 100.0% (901 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/de/ * Translated using Weblate (Hungarian) Currently translated at 20.0% (181 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/hu/ * Translated using Weblate (Chinese (Simplified)) Currently translated at 38.9% (351 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/zh_Hans/ * Translated using Weblate (Arabic) Currently translated at 0.5% (5 of 901 strings) Translation: Riot Web/matrix-react-sdk Translate-URL: https://translate.riot.im/projects/riot-web/matrix-react-sdk/ar/ * remote entirely spurious translation progress stats :/ --- src/i18n/strings/ar.json | 7 ++ src/i18n/strings/de_DE.json | 42 ++++----- src/i18n/strings/el.json | 23 +++-- src/i18n/strings/en_US.json | 19 +++- src/i18n/strings/hu.json | 8 +- src/i18n/strings/ru.json | 31 ++++--- src/i18n/strings/zh_Hans.json | 157 ++++++++++++++++++++++++++++++++-- 7 files changed, 237 insertions(+), 50 deletions(-) create mode 100644 src/i18n/strings/ar.json diff --git a/src/i18n/strings/ar.json b/src/i18n/strings/ar.json new file mode 100644 index 0000000000..30f0730a98 --- /dev/null +++ b/src/i18n/strings/ar.json @@ -0,0 +1,7 @@ +{ + "ar-iq": "العربية", + "Continue": "استمر", + "Username available": "اسم المستخدم متاح", + "Username not available": "الإسم المستخدم غير موجود", + "Something went wrong!": "هناك خطأ ما!" +} diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index fbd49a6800..bfdaf62399 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1,5 +1,5 @@ { - "Filter room members": "Raum-Benutzer filtern", + "Filter room members": "Raum-Mitglieder filtern", "You have no visible notifications": "Du hast keine sichtbaren Benachrichtigungen", "Invites": "Einladungen", "Favourites": "Favoriten", @@ -88,7 +88,7 @@ "Display name": "Anzeigename", "Email Address": "E-Mail-Adresse", "Email, name or matrix ID": "E-Mail, Name oder Matrix-ID", - "Encrypted messages will not be visible on clients that do not yet implement encryption": "Verschlüsselte Nachrichten werden an Clients nicht sichtbar sein, die Verschlüsselung noch nicht implementiert haben", + "Encrypted messages will not be visible on clients that do not yet implement encryption": "Verschlüsselte Nachrichten werden nicht in Matrix-Clients sichtbar sein, die die Verschlüsselung noch nicht implementiert haben", "Encrypted room": "Verschlüsselter Raum", "Encryption is enabled in this room": "Verschlüsselung ist in diesem Raum aktiviert", "Encryption is not enabled in this room": "Verschlüsselung ist in diesem Raum nicht aktiviert", @@ -193,7 +193,7 @@ "Room name (optional)": "Raumname (optional)", "Scroll to unread messages": "Zu den ungelesenen Nachrichten scrollen", "Send Invites": "Einladungen senden", - "Send Reset Email": "E-Mail für das Zurücksetzen senden", + "Send Reset Email": "E-Mail zum Zurücksetzen senden", "sent an image": "hat ein Bild gesendet", "sent an invitation to": "sandte eine Einladung an", "sent a video": "hat ein Video gesendet", @@ -270,7 +270,7 @@ "Who would you like to add to this room?": "Wen möchtest du zu diesem Raum hinzufügen?", "Who would you like to communicate with?": "Mit wem möchtest du kommunizieren?", "Would you like to": "Möchtest du", - "You do not have permission to post to this room": "Du hast keine Berechtigung an diesen Raum etwas zu senden", + "You do not have permission to post to this room": "Du hast keine Berechtigung, in diesem Raum etwas zu senden", "You have been invited to join this room by %(inviterName)s": "%(inviterName)s hat dich in diesen Raum eingeladen", "You have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, sign in again on each device": "Du wurdest auf allen Geräten abgemeldet und wirst keine Push-Benachrichtigungen mehr erhalten. Um die Benachrichtigungen zu reaktivieren, musst du dich auf jedem Gerät neu anmelden", "you must be a": "nötige Rolle", @@ -392,7 +392,7 @@ "%(senderName)s unbanned %(targetName)s.": "%(senderName)s zog Bann für %(targetName)s zurück.", "Usage": "Verwendung", "Use with caution": "Mit Vorsicht zu verwenden", - "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s zog die Einladung für %(targetName)s zurück.", + "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s hat die Einladung für %(targetName)s zurückgezogen.", "You need to be able to invite users to do that.": "Du musst die Berechtigung haben, Nutzer einzuladen, um diese Aktion ausführen zu können.", "You need to be logged in.": "Du musst angemeldet sein.", "There are no visible files in this room": "Es gibt keine sichtbaren Dateien in diesem Raum", @@ -564,7 +564,7 @@ "Click to mute audio": "Klicke um den Ton stumm zu stellen", "Click to mute video": "Klicken, um das Video stummzuschalten", "Command error": "Befehlsfehler", - "Decrypt %(text)s": "Entschlüssele %(text)s", + "Decrypt %(text)s": "%(text)s entschlüsseln", "Delete": "Löschen", "Devices": "Geräte", "Direct chats": "Direkte Chats", @@ -586,7 +586,7 @@ "Invalid alias format": "Ungültiges Alias-Format", "Invalid address format": "Ungültiges Adressformat", "'%(alias)s' is not a valid format for an address": "'%(alias)s' ist kein gültiges Adressformat", - "'%(alias)s' is not a valid format for an alias": "'%(alias)s' hat kein valides Aliasformat", + "'%(alias)s' is not a valid format for an alias": "'%(alias)s' ist kein gültiges Alias-Format", "Join Room": "Dem Raum beitreten", "Kick": "Kicke", "Level": "Berechtigungslevel", @@ -607,7 +607,7 @@ "Server error": "Server-Fehler", "Server may be unavailable, overloaded, or search timed out :(": "Der Server ist entweder nicht verfügbar, überlastet oder die Suche wurde wegen Zeitüberschreitung abgebrochen :(", "Server may be unavailable, overloaded, or the file too big": "Server ist entweder nicht verfügbar, überlastet oder die Datei ist zu groß", - "Server unavailable, overloaded, or something else went wrong.": "Server nicht verfügbar, überlastet oder etwas anderes lief falsch.", + "Server unavailable, overloaded, or something else went wrong.": "Server ist nicht verfügbar, überlastet oder ein anderer Fehler ist aufgetreten.", "Some of your messages have not been sent.": "Einige deiner Nachrichten wurden nicht gesendet.", "Submit": "Absenden", "The main address for this room is: %(canonical_alias_section)s": "Die Hauptadresse für diesen Raum ist: %(canonical_alias_section)s", @@ -626,7 +626,7 @@ "You seem to be in a call, are you sure you want to quit?": "Du scheinst in einem Anruf zu sein. Bist du sicher schließen zu wollen?", "You seem to be uploading files, are you sure you want to quit?": "Du scheinst Dateien hochzuladen. Bist du sicher schließen zu wollen?", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Du wirst diese Änderung nicht rückgängig machen können, da der Nutzer dasselbe Berechtigungslevel wie du selbst erhalten wird.", - "Make Moderator": "Zum Moderator machen", + "Make Moderator": "Zum Moderator ernennen", "Room": "Raum", "(~%(searchCount)s results)": "(~%(searchCount)s Ergebnisse)", "Cancel": "Abbrechen", @@ -655,7 +655,7 @@ "%(oneUser)sjoined %(repeats)s times": "%(oneUser)shat den Raum %(repeats)s mal betreten", "%(severalUsers)sjoined": "%(severalUsers)shaben den Raum betreten", "%(oneUser)sjoined": "%(oneUser)shat den Raum betreten", - "%(severalUsers)sleft %(repeats)s times": "%(severalUsers)sverließen %(repeats)s mal den Raum", + "%(severalUsers)sleft %(repeats)s times": "%(severalUsers)shaben %(repeats)s mal den Raum verlassen", "%(oneUser)sleft %(repeats)s times": "%(oneUser)sging %(repeats)s mal", "%(severalUsers)sleft": "%(severalUsers)shaben den Raum verlassen", "%(oneUser)sleft": "%(oneUser)sging", @@ -674,7 +674,7 @@ "%(severalUsers)shad their invitations withdrawn %(repeats)s times": "%(severalUsers)szogen ihre Einladungen %(repeats)s mal zurück", "%(oneUser)shad their invitation withdrawn %(repeats)s times": "%(oneUser)szog seine/ihre Einladung %(repeats)s mal zurück", "%(severalUsers)shad their invitations withdrawn": "%(severalUsers)szogen ihre Einladungen zurück", - "%(oneUser)shad their invitation withdrawn": "%(oneUser)szog seine/ihre Einladung zurück", + "%(oneUser)shad their invitation withdrawn": "%(oneUser)swurde die ursprüngliche Einladung wieder entzogen", "were invited %(repeats)s times": "wurden %(repeats)s mal eingeladen", "was invited %(repeats)s times": "wurde %(repeats)s mal eingeladen", "were invited": "wurden eingeladen", @@ -751,8 +751,8 @@ "Verify device": "Gerät verifizieren", "I verify that the keys match": "Ich bestätige, dass die Schlüssel passen", "Unable to restore session": "Sitzungswiederherstellung fehlgeschlagen", - "Continue anyway": "Fahre trotzdem fort", - "Your display name is how you'll appear to others when you speak in rooms. What would you like it to be?": "Dein Anzeigename ist der Name, der anderen Nutzern angezeigt wird, wenn du in Räumen sprichst. Welchen Anzeigenamen möchtest du wählen?", + "Continue anyway": "Trotzdem fortfahren", + "Your display name is how you'll appear to others when you speak in rooms. What would you like it to be?": "Dein Anzeigename ist der Name, der anderen Nutzern angezeigt wird, wenn du in Räumen kommunizierst. Welchen Anzeigenamen möchtest du wählen?", "You are currently blacklisting unverified devices; to send messages to these devices you must verify them.": "Do blockst aktuell unverifizierte Geräte. Um Nachrichten an diese Geräte zu senden musst du sie verifizieren.", "\"%(RoomName)s\" contains devices that you haven't seen before.": "\"%(RoomName)s\" enthält Geräte, die du bislang noch nicht gesehen hast.", "Unknown devices": "Unbekannte Geräte", @@ -809,7 +809,7 @@ "If you have previously used a more recent version of Riot, your session may be incompatible with this version. Close this window and return to the more recent version.": "Wenn du zuvor eine aktuellere Version von Riot verwendet hast, ist deine Sitzung eventuell inkompatibel mit dieser Version. Bitte schließe dieses Fenster und kehre zur aktuelleren Version zurück.", "Blacklist": "Blockieren", "Unblacklist": "Entblockieren", - "Unverify": "Entverifizieren", + "Unverify": "Verifizierung widerrufen", "This Home Server would like to make sure you are not a robot": "Dieser Heimserver möchte sicherstellen, dass du kein Roboter bist", "Drop file here to upload": "Datei hier loslassen zum hochladen", "Idle": "Untätig", @@ -841,7 +841,7 @@ "Camera": "Kamera", "Device already verified!": "Gerät bereits verifiziert!", "Export": "Export", - "Failed to register as guest:": "Registrieren als Gast schlug fehl:", + "Failed to register as guest:": "Die Registrierung als Gast ist fehlgeschlagen:", "Guest access is disabled on this Home Server.": "Gastzugang ist auf diesem Heimserver deaktivert.", "Import": "Import", "Incorrect username and/or password.": "Inkorrekter Nutzername und/oder Passwort.", @@ -862,7 +862,7 @@ "Register": "Registrieren", "Save": "Speichern", "Setting a user name will create a fresh account": "Die Eingabe eines Benutzernamens wird ein neues Konto erzeugen", - "Tagged as: ": "Getaggt als: ", + "Tagged as: ": "Markiert als: ", "This Home Server does not support login using email address.": "Dieser Heimserver unterstützt den Login mittels E-Mail-Adresse nicht.", "There was a problem logging in.": "Es gab ein Problem beim anmelden.", "Unknown (user, device) pair:": "Unbekanntes (Nutzer-/Gerät-)Paar:", @@ -880,7 +880,7 @@ "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s hat das Raum-Bild für %(roomName)s geändert", "Hide removed messages": "Gelöschte Nachrichten verbergen", "Start new chat": "Neuen Chat starten", - "Disable markdown formatting": "Deaktiviere Markdown-Formatierung", + "Disable markdown formatting": "Markdown-Formatierung deaktivieren", "Add": "Hinzufügen", "%(count)s new messages.one": "%(count)s neue Nachricht", "%(count)s new messages.other": "%(count)s neue Nachrichten", @@ -900,13 +900,13 @@ "Room directory": "Raum-Verzeichnis", "Start chat": "Chat starten", "New Password": "Neues Passwort", - "Start chatting": "Starte plaudern", + "Start chatting": "Chat beginnen", "Start Chatting": "Starte Gespräche", "Click on the button below to start chatting!": "Unten auf den Button klicken, um einen Chat zu beginnen!", "Create a new chat or reuse an existing one": "Neuen Chat erstellen oder einen vorhandenen Chat fortsetzen", "You already have existing direct chats with this user:": "Du hast bereits direkte Chats mit diesem Nutzer:", - "Username available": "Nutzername verfügbar", - "Username not available": "Nutzername nicht verfügbar", + "Username available": "Benutzername ist verfügbar", + "Username not available": "Benutzername ist nicht verfügbar", "Something went wrong!": "Etwas ging schief!", "This will be your account name on the homeserver, or you can pick a different server.": "Dies wird dein zukünftiger Benutzername auf dem Heimserver. Alternativ kannst du auch einen anderen Server auswählen.", "If you already have a Matrix account you can log in instead.": "Wenn du bereits ein Matrix-Benutzerkonto hast, kannst du dich stattdessen auch direkt anmelden.", @@ -964,7 +964,7 @@ "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (Berechtigungslevel %(powerLevelNumber)s)", "Verified": "Verifiziert", "Would you like to accept or decline this invitation?": "Möchtest du diese Einladung akzeptieren oder ablehnen?", - "You have been banned from %(roomName)s by %(userName)s.": "Du wurdest von %(userName)s aus dem Raum %(roomName)s verbannt.", + "You have been banned from %(roomName)s by %(userName)s.": "Du wurdest von %(userName)s aus dem Raum %(roomName)s ausgeschlossen.", "You have been kicked from %(roomName)s by %(userName)s.": "Du wurdest von %(userName)s aus dem Raum %(roomName)s gekickt.", "You may wish to login with a different account, or add this email to this account.": "Du möchtest dich evtl. mit einem anderen Konto anmelden oder diese E-Mail-Adresse diesem Konto hinzufügen.", "Your home server does not support device management.": "Dein Heimserver unterstützt kein Geräte-Management.", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 725b5497a5..a38dddb35b 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -1,13 +1,13 @@ { "af": "Αφρικάνικα", "Error": "Σφάλμα", - "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου %(errCode)s", + "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου (%(errCode)s)", "Failed to join the room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο", "Mute": "Σίγαση", "Notifications": "Ειδοποιήσεις", "Operation failed": "Η λειτουργία απέτυχε", - "Please Register": "Παρακαλώ εγγραφείτε", - "Remove": "Αφαίρεσε", + "Please Register": "Παρακαλούμε εγγραφείτε", + "Remove": "Αφαίρεση", "Search": "Αναζήτηση", "Settings": "Ρυθμίσεις", "unknown error code": "άγνωστος κωδικός σφάλματος", @@ -195,7 +195,7 @@ "%(senderDisplayName)s removed the room name.": "Ο χρήστης %(senderDisplayName)s διέγραψε το όνομα του δωματίου.", "Changes your display nickname": "Αλλάζει το όνομα χρήστη", "Click here": "Κάνε κλικ εδώ", - "Drop here %(toAction)s": "Σύρε εδώ %(toAction)s", + "Drop here %(toAction)s": "Απόθεση εδώ %(toAction)s", "Conference call failed.": "Η κλήση συνδιάσκεψης απέτυχε.", "powered by Matrix": "βασισμένο στο πρωτόκολλο Matrix", "Confirm password": "Επιβεβαίωση κωδικού", @@ -222,7 +222,7 @@ "device id: ": "id συσκευής: ", "Device key:": "Κλειδί Συσκευής:", "Devices": "Συσκευές", - "Direct Chat": "Απευθείας Συνομιλία", + "Direct Chat": "Απευθείας συνομιλία", "Direct chats": "Απευθείας συνομιλίες", "disabled": "ανενεργό", "Disinvite": "Ανακάλεσε πρόσκληση", @@ -244,7 +244,7 @@ "Existing Call": "Υπάρχουσα Κλήση", "Export": "Εξαγωγή", "Export E2E room keys": "Εξαγωγή κλειδιών κρυπτογραφίας για το δωμάτιο", - "Failed to change password. Is your password correct?": "Δεν ήταν δυνατή η αλλαγή του κωδικού. Είναι ο κωδικός σωστός;", + "Failed to change password. Is your password correct?": "Δεν ήταν δυνατή η αλλαγή του κωδικού πρόσβασης. Είναι σωστός ο κωδικός πρόσβασης;", "Failed to delete device": "Δεν ήταν δυνατή η διαγραφή της συσκευής", "Failed to join room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο", "Failed to leave room": "Δεν ήταν δυνατή η αποχώρηση από το δωμάτιο", @@ -330,7 +330,7 @@ "": "<δεν υποστηρίζεται>", "No more results": "Δεν υπάρχουν άλλα αποτελέσματα", "No results": "Κανένα αποτέλεσμα", - "OK": "ΟΚ", + "OK": "Εντάξει", "olm version:": "έκδοση olm:", "Password": "Κωδικός", "Password:": "Κωδικός:", @@ -364,7 +364,7 @@ "cancel all": "ακύρωση όλων", "or": "ή", "Custom Server Options": "Προσαρμοσμένες ρυθμίσεις διακομιστή", - "Dismiss": "Αγνόησε", + "Dismiss": "Απόρριψη", "Monday": "Δευτέρα", "Tuesday": "Τρίτη", "Wednesday": "Τετάρτη", @@ -382,5 +382,10 @@ "%(severalUsers)sjoined and left %(repeats)s times": "%(severalUsers)s συνδέθηκαν και έφυγαν %(repeats)s φορές", "%(oneUser)sjoined and left %(repeats)s times": "%(oneUser)s συνδέθηκε και έφυγε %(repeats)s φορές", "%(severalUsers)sjoined and left": "%(severalUsers)s συνδέθηκαν και έφυγαν", - "%(oneUser)sjoined and left": "%(oneUser)s συνδέθηκε και έφυγε" + "%(oneUser)sjoined and left": "%(oneUser)s συνδέθηκε και έφυγε", + "Close": "Κλείσιμο", + "Create new room": "Δημιουργία νέου δωματίου", + "Room directory": "Ευρετήριο", + "Start chat": "Έναρξη συνομιλίας", + "Welcome page": "Αρχική σελίδα" } diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index 20041ef231..d857ff06cb 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -824,5 +824,22 @@ "Disable URL previews for this room (affects only you)": "Disable URL previews for this room (affects only you)", "$senderDisplayName changed the room avatar to ": "$senderDisplayName changed the room avatar to ", "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s removed the room avatar.", - "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s changed the avatar for %(roomName)s" + "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s changed the avatar for %(roomName)s", + "Active call (%(roomName)s)": "Active call (%(roomName)s)", + "Accept": "Accept", + "a room": "a room", + "Add": "Add", + "Admin tools": "Admin tools", + "And %(count)s more...": "And %(count)s more...", + "Alias (optional)": "Alias (optional)", + "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.", + "Click here to join the discussion!": "Click here to join the discussion!", + "Close": "Close", + "%(count)s new messages.one": "%(count)s new message", + "%(count)s new messages.other": "%(count)s new messages", + "Custom": "Custom", + "Decline": "Decline", + "Disable markdown formatting": "Disable markdown formatting", + "Disable Notifications": "Disable Notifications", + "Enable Notifications": "Enable Notifications" } diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 458d461b90..c6a86347f5 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -173,5 +173,11 @@ "Always show message timestamps": "Üzenet időbélyeg folyamatos megjelenítése", "Authentication": "Azonosítás", "Alias (optional)": "Becenév (opcionális)", - "all room members": "minden szoba tagság" + "all room members": "minden szoba tagság", + "Failed to change password. Is your password correct?": "Nem sikerült megváltoztatni a jelszót. Helyesen írtad be a jelszavadat?", + "Continue": "Folytatás", + "Create new room": "Új szoba létrehozása", + "sb": "Szorb", + "rm": "Rétoromán", + "tn": "Tswana" } diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 6bcfa680c6..f2d88bcc44 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -59,7 +59,7 @@ "Deops user with given id": "Deops пользователь с данным id", "Device ID": "Устройство ID", "Devices will not yet be able to decrypt history from before they joined the room": "Устройство еще не будет в состоянии дешифровать историю, до присоединения к комнате", - "Direct Chat": "Персональное сообщение", + "Direct Chat": "Приватный чат", "Disable inline URL previews by default": "Отключить встроенные предварительные просмотры URL по умолчанию", "Display name": "Отображаемое имя", "Displays action": "Отображение действий", @@ -75,7 +75,7 @@ "Error": "Ошибка", "Event information": "Event information", "Export E2E room keys": "Экспорт E2E ключей комнаты", - "Failed to change password. Is your password correct?": "Не удалось изменить пароль. Ваш пароль правильный?", + "Failed to change password. Is your password correct?": "Не удалось сменить пароль. Вы правильно ввели текущий пароль?", "Failed to forget room": "Не удалось забыть комнату", "Failed to leave room": "Не удалось выйти из комнаты", "Failed to reject invitation": "Не удалось отклонить приглашение", @@ -246,7 +246,7 @@ "Failed to set up conference call": "Не удалось установить конференц-вызов", "Failed to verify email address: make sure you clicked the link in the email": "Не удалось подтвердить email-адрес: убедитесь что вы щелкнули по ссылке электронной почты", "Failure to create room": "Не удалось создать комнату", - "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s из %(fromPowerLevel)s до %(toPowerLevel)s", + "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId) изменил %(fromPowerLevel) на %(toPowerLevel)", "Guest users can't create new rooms. Please register to create room and start a chat.": "Гостевые пользователи не могут создавать новые комнаты. Зарегистрируйтесь для создания комнаты и чата.", "click to reveal": "нажать для открытия", "%(senderName)s invited %(targetName)s.": "%(senderName)s приглашает %(targetName)s.", @@ -258,7 +258,7 @@ "Missing room_id in request": "Отсутствует room_id в запросе", "Missing user_id in request": "Отсутствует user_id в запросе", "Must be viewing a room": "Посмотреть комнату", - "New Composer & Autocomplete": "Новый автор & Авто. заполнение", + "New Composer & Autocomplete": "Новый автор & Автозаполнение", "(not supported by this browser)": "(не поддерживаемый этим браузером)", "af": "Африкаанс", "ar-ae": "Арабский (О.А.Е)", @@ -355,12 +355,12 @@ "Friday": "Пятница", "Saturday": "Суббота", "Sunday": "Воскресенье", - "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", + "%(weekDayName)s %(time)s": "%(weekDayName) %(time)", "Upload an avatar:": "Загрузите аватар:", "You need to be logged in.": "Вы должны быть зарегистрированы.", "You need to be able to invite users to do that.": "Вам необходимо пригласить пользователей чтобы сделать это.", "You cannot place VoIP calls in this browser.": "Вы не можете сделать вызовы VoIP с этим браузером.", - "You are already in a call.": "Вы уже находитесь в разговоре.", + "You are already in a call.": "Связь уже установлена.", "You're not in any rooms yet! Press": "Вы еще не находитесь ни в каких комнатах! Нажать", "You are trying to access %(roomName)s.": "Вы пытаетесь получить доступ %(roomName)s.", "You cannot place a call with yourself.": "Вы не можете позвонить самим себе.", @@ -725,7 +725,7 @@ "Server may be unavailable, overloaded, or search timed out :(": "Сервер может быть недоступен, перегружен или поиск прекращен по тайм-ауту :(", "Server may be unavailable, overloaded, or the file too big": "Сервер может быть недоступен, перегружен или размер файла слишком большой", "Server may be unavailable, overloaded, or you hit a bug.": "Сервер может быть недоступен, перегружен или вы нашли ошибку.", - "Server unavailable, overloaded, or something else went wrong.": "Сервер может быть недоступен, перегружен или произошло что-то страшное.", + "Server unavailable, overloaded, or something else went wrong.": "Сервер может быть недоступен, перегружен или что-то пошло не так.", "Session ID": "ID сессии", "%(senderName)s set a profile picture.": "%(senderName)s установил картинку профиля.", "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s установил отображаемое имя %(displayName)s.", @@ -766,7 +766,7 @@ "You have enabled URL previews by default.": "Предпросмотр ссылок включен по-умолчанию.", "You have entered an invalid contact. Try using their Matrix ID or email address.": "Вы ввели неправильный адрес. Попробуйте использовать Matrix ID или адрес email.", "You need to enter a user name.": "Необходимо ввести имя пользователя.", - "You seem to be in a call, are you sure you want to quit?": "Вы участвуете в звонке, вы уверены, что хотите выйти?", + "You seem to be in a call, are you sure you want to quit?": "Звонок не завершен, вы уверены, что хотите выйти?", "You will not be able to undo this change as you are promoting the user to have the same power level as yourself.": "Вы не сможете отменить это действие так как даете пользователю такой же уровень доступа как и у вас.", "Set a Display Name": "Установить отображаемое имя", "(~%(searchCount)s results)": "(~%(searchCount)s результатов)", @@ -818,7 +818,7 @@ "\"%(RoomName)s\" contains devices that you haven't seen before.": "\"%(RoomName)s\" содержит неизвестные прежде устройства.", "Unknown Address": "Неизвестный адрес", "Unblacklist": "Удалить из черного списка", - "Blacklist": "Добавить в черный список", + "Blacklist": "Черный список", "Unverify": "Убрать верификацию", "Verify...": "Верифицировать...", "ex. @bob:example.com": "например @bob:example.com", @@ -872,7 +872,7 @@ "Add": "Добавить", "%(count)s new messages.one": "%(count)s новое сообщение", "%(count)s new messages.other": "%(count)s новых сообщений", - "Error: Problem communicating with the given homeserver.": "Ошибка: проблема коммуникаций с указанным Home Server'ом.", + "Error: Problem communicating with the given homeserver.": "Ошибка: проблема связи с указанным сервером.", "Failed to fetch avatar URL": "Ошибка получения аватара", "The phone number entered looks invalid": "Введенный номер телефона выглядит неправильным", "Uploading %(filename)s and %(count)s others.zero": "Загрузка %(filename)s", @@ -925,7 +925,7 @@ "Set": "Вводить", "Start authentication": "Начать идентификацию", "This room": "Эта комната", - "(~%(count)s results).other": "(~%(count)s results)", + "(~%(count)s results).other": "(~%(count) найдено)", "Device Name": "Имя устройства", "Custom": "Пользователь", "Decline": "Отклонить", @@ -947,6 +947,11 @@ "%(user)s is a": "%(user)s является", "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (уровень доступа %(powerLevelNumber)s)", "Verified": "Подтверждён", - "Would you like to accept or decline this invitation?": "Хотели бы вы это приглашение подтвердить или отклонить?", - "(~%(count)s results).one": "(~%(count)s Результат)" + "Would you like to accept or decline this invitation?": "Хотели бы вы подтвердить это приглашение или отклонить?", + "(~%(count)s results).one": "(~%(count)s Результат)", + "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Не удается подключиться к домашнему серверу - проверьте подключение, убедитесь, что ваш сертификат SSL homeserver's SSL certificate действителен, и расширение браузера не блокирует запросы.", + "You have been banned from %(roomName)s by %(userName)s.": "%(userName) забанил Вас в % (roomName).", + "You have been kicked from %(roomName)s by %(userName)s.": "%(userName) выгнал Вас из %(roomName).", + "You may wish to login with a different account, or add this email to this account.": "Вы можете войти в систему с другой учетной записью или добавить этот адрес email в эту учетную запись.", + "Your home server does not support device management.": "Ваш домашний сервер не поддерживает управление устройствами." } diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index e6eb5f632b..ad37ce9430 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -162,9 +162,9 @@ "de-at": "德语(奥地利)", "de-ch": "德语(瑞士)", "de": "德语", - "de-lu": "德语(卢森堡)", + "de-lu": "德语 (卢森堡)", "el": "希腊语", - "en-au": "英语(澳大利亚)", + "en-au": "英语 (澳大利亚)", "en": "英语", "zh-cn": "中文(中国)", "zh-hk": "中文(香港)", @@ -199,11 +199,158 @@ "Ed25519 fingerprint": "Ed25519指纹", "Invite new room members": "邀请新的聊天室成员", "Join Room": "加入聊天室", - "joined": "加入了", - "%(targetName)s joined the room.": "%(targetName)s 加入了聊天室。.", + "joined": "已加入", + "%(targetName)s joined the room.": "%(targetName)s 已加入聊天室。", "Jump to first unread message.": "跳到第一条未读消息。", "%(senderName)s kicked %(targetName)s.": "%(senderName)s 把 %(targetName)s 踢出了聊天室。.", "Leave room": "离开聊天室", "Login as guest": "以游客的身份登录", - "New password": "新密码" + "New password": "新密码", + "ar-ae": "阿拉伯语 (阿联酋)", + "ar-bh": "阿拉伯语 (巴林)", + "ar-dz": "阿拉伯语 (阿尔及利亚)", + "ar-eg": "阿拉伯语 (埃及)", + "ar-iq": "阿拉伯语 (伊拉克)", + "ar-jo": "阿拉伯语 (约旦)", + "ar-kw": "阿拉伯语 (科威特)", + "ar-lb": "阿拉伯语 (黎巴嫩)", + "ar-ly": "阿拉伯语 (利比亚)", + "ar-ma": "阿拉伯语 (摩洛哥)", + "ar-ye": "阿拉伯语 (也门)", + "en-ca": "英语 (加拿大)", + "en-gb": "英语 (英国)", + "en-ie": "英语 (爱尔兰)", + "en-nz": "英语 (新西兰)", + "Add a topic": "新话题", + "Admin": "管理员", + "Admin tools": "管理工具", + "VoIP": "IP 电话", + "Missing Media Permissions, click here to request.": "没有媒体存储权限,点此获取。", + "No Microphones detected": "未检测到麦克风", + "No Webcams detected": "未检测到摄像头", + "No media permissions": "没有媒体存取权限", + "You may need to manually permit Riot to access your microphone/webcam": "你可能需要手动授权 Riot 使用你的麦克风或摄像头", + "Default Device": "默认设备", + "Microphone": "麦克风", + "Camera": "摄像头", + "Hide removed messages": "隐藏被删除的消息", + "Authentication": "认证", + "Alias (optional)": "别名 (可选)", + "%(items)s and %(remaining)s others": "%(items)s 和其它 %(remaining)s 个", + "%(items)s and one other": "%(items)s 和其它一个", + "%(items)s and %(lastItem)s": "%(items)s 和 %(lastItem)s", + "and %(overflowCount)s others...": "和其它 %(overflowCount)s 个...", + "and one other...": "和其它一个...", + "%(names)s and one other are typing": "%(names)s 和另一个人正在打字", + "anyone": "任何人", + "Anyone": "任何人", + "Anyone who knows the room's link, apart from guests": "任何知道聊天室链接的人,游客除外", + "Anyone who knows the room's link, including guests": "任何知道聊天室链接的人,包括游客", + "Are you sure?": "你确定吗?", + "Are you sure you want to leave the room '%(roomName)s'?": "你确定要离开聊天室 “%(roomName)s” 吗?", + "Are you sure you want to reject the invitation?": "你确定要拒绝邀请吗?", + "Are you sure you want to upload the following files?": "你确定要上传这些文件吗?", + "Bans user with given id": "封禁指定 ID 的用户", + "Blacklisted": "已列入黑名单", + "Bug Report": "反馈漏洞", + "Bulk Options": "批量操作", + "Call Timeout": "通话超时", + "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "无法连接主服务器 - 请检查网络连接,确保你的主服务器 SSL 证书被信任,且没有浏览器插件拦截请求。", + "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "当浏览器地址栏里有 HTTPS 的 URL 时,不能使用 HTTP 连接主服务器。请使用 HTTPS 或者允许不安全的脚本。", + "Can't load user settings": "无法加载用户设置", + "Change Password": "修改密码", + "%(senderName)s changed their display name from %(oldDisplayName)s to %(displayName)s.": "%(senderName)s 将昵称从 %(oldDisplayName)s 改为了 %(displayName)s。", + "%(senderName)s changed their profile picture.": "%(senderName)s 修改了头像。", + "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s 将聊天室名称改为 %(roomName)s。", + "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s 移除了聊天室名称。", + "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s 把话题修改为 “%(topic)s”。", + "Changes to who can read history will only apply to future messages in this room": "修改阅读历史的权限仅对此聊天室以后的消息有效", + "Changes your display nickname": "修改昵称", + "Changing password will currently reset any end-to-end encryption keys on all devices, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "目前,修改密码会导致所有设备上的端对端密钥被重置,使得加密的聊天记录不再可读。除非你事先导出聊天室密钥,修改密码后再导入。这个问题未来会改善。", + "Clear Cache and Reload": "清除缓存并刷新", + "Clear Cache": "清除缓存", + "Click here to join the discussion!": "点此 加入讨论!", + "Click to mute audio": "点此静音", + "Click to mute video": "点此静音", + "click to reveal": "点击展开", + "Click to unmute video": "点此打开声音", + "Click to unmute audio": "点此打开声音", + "Close": "关闭", + "Command error": "命令错误", + "Commands": "命令", + "Conference call failed.": "视频会议失败。", + "Conference calling is in development and may not be reliable.": "视频会议功能还在开发状态,可能不稳定。", + "Conference calls are not supported in encrypted rooms": "加密聊天室不支持视频会议", + "Conference calls are not supported in this client": "此客户端不支持视频会议", + "%(count)s new messages.one": "%(count)s 条新消息", + "%(count)s new messages.other": "%(count)s 新消息", + "Create a new chat or reuse an existing one": "创建新聊天或使用已有的聊天", + "Custom": "自定义", + "Custom level": "自定义级别", + "Decline": "拒绝", + "Device already verified!": "设备已经验证!", + "Device ID:": "设备 ID:", + "device id: ": "设备 ID: ", + "Device key:": "设备密钥 :", + "Disable Notifications": "关闭消息通知", + "disabled": "已禁用", + "Disable markdown formatting": "禁用 Markdown 格式", + "Drop File Here": "把文件拖拽到这里", + "Email address (optional)": "电子邮件地址 (可选)", + "Enable Notifications": "启用消息通知", + "enabled": "已启用", + "Encrypted by a verified device": "由一个已验证的设备加密", + "Encrypted by an unverified device": "由一个未经验证的设备加密", + "Encryption is enabled in this room": "此聊天室启用了加密", + "Encryption is not enabled in this room": "此聊天室未启用加密", + "Enter passphrase": "输入密码", + "Error: Problem communicating with the given homeserver.": "错误: 与指定的主服务器通信时出错。", + "Export": "导出", + "Failed to fetch avatar URL": "获取 Avatar URL 失败", + "Failed to register as guest:": "无法注册为游客:", + "Failed to upload profile picture!": "无法上传头像!", + "Guest access is disabled on this Home Server.": "此服务器禁用了游客访问。", + "Home": "主页面", + "Import": "导入", + "Incoming call from %(name)s": "来自 %(name)s 的通话", + "Incoming video call from %(name)s": "来自 %(name)s 的视频通话", + "Incoming voice call from %(name)s": "来自 %(name)s 的视频通话", + "Incorrect username and/or password.": "用户名或密码错误。", + "%(senderName)s invited %(targetName)s.": "%(senderName)s 邀请了 %(targetName)s。", + "Invited": "已邀请", + "Invites": "邀请", + "Invites user with given id to current room": "邀请指定 ID 的用户加入当前聊天室", + "'%(alias)s' is not a valid format for an address": "'%(alias)s' 不是一个合法的电子邮件地址格式", + "'%(alias)s' is not a valid format for an alias": "'%(alias)s' 不是一个合法的昵称格式", + "%(displayName)s is typing": "%(displayName)s 正在输入", + "Sign in with": "第三方登录", + "Message not sent due to unknown devices being present": "消息未发送,因为有未知的设备存在", + "Missing room_id in request": "请求中没有 room_id", + "Missing user_id in request": "请求中没有 user_id", + "Mobile phone number": "手机号码", + "Mobile phone number (optional)": "手机号码 (可选)", + "Moderator": "管理员", + "Mute": "静音", + "my Matrix ID": "我的 Matrix ID", + "Name": "姓名", + "Never send encrypted messages to unverified devices from this device": "不要从此设备向未验证的设备发送消息", + "Never send encrypted messages to unverified devices in this room": "不要在此聊天室里向未验证的设备发送消息", + "New passwords don't match": "两次输入的新密码不符", + "none": "无", + "not set": "未设置", + "not specified": "未指定", + "Notifications": "通知", + "(not supported by this browser)": "(此浏览器不支持)", + "": "<不支持>", + "NOT verified": "未验证", + "No display name": "无昵称", + "No results": "没有更多结果", + "OK": "确定", + "Once encryption is enabled for a room it cannot be turned off again (for now)": "(目前) 一旦聊天室开启加密,就不能再关闭", + "Operation failed": "操作失败", + "Password": "密码", + "Password:": "密码:", + "Passwords can't be empty": "密码不能为空", + "Permissions": "权限", + "Phone": "电话" } From a389d5a3c487f72d4bc018f3f5da638a28be6057 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 12 Jun 2017 15:50:36 +0100 Subject: [PATCH 274/275] Prepare changelog for v0.9.3 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 651303d3b9..16eeca8fa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in [0.9.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.3) (2017-06-12) +=================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.3-rc.2...v0.9.3) + + * Add more translations & fix some existing ones + Changes in [0.9.3-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.9.3-rc.2) (2017-06-09) ============================================================================================================= [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.9.3-rc.1...v0.9.3-rc.2) From aef0a8025ca2c94c2a52c823d9bc7d4825b52e15 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 12 Jun 2017 15:50:37 +0100 Subject: [PATCH 275/275] v0.9.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b57cc6890..12a17900be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.9.3-rc.2", + "version": "0.9.3", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": {