From d516906b368fdc23154567526417825dd910bae2 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 30 Aug 2017 13:52:46 +0100 Subject: [PATCH 01/43] Implement sticky date separators Use `react-sticky` to implement sticky date separators. This will pin a date separator to the top of the timeline panel when the separator scrolls out of the top of the view. A known issue of this is that the spinner, which is in line with event tiles in the timeline, will appear to push the stuck date separator down. In reality the first date separator after the spinner is in line with event tiles and is not stuck because the spinner forces the timeline to be scrolled slightly further down than it would be otherwise. But also, date separators in the timeline (not "stuck") have a greater height. Ideally the date separator would be suppressed whilst back paginating, but this will cause the stuck separator to flicker on and off. This is why the suppression has been removed. --- package.json | 1 + src/DateUtils.js | 44 ++++ src/components/structures/MessagePanel.js | 9 +- src/components/structures/ScrollPanel.js | 274 +++++++++++---------- src/components/structures/TimelinePanel.js | 1 - 5 files changed, 189 insertions(+), 140 deletions(-) diff --git a/package.json b/package.json index 661db4b6bc..c323e67ecf 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "react-addons-css-transition-group": "15.3.2", "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", + "react-sticky": "^6.0.1", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", diff --git a/src/DateUtils.js b/src/DateUtils.js index 78eef57eae..e7be394c17 100644 --- a/src/DateUtils.js +++ b/src/DateUtils.js @@ -30,6 +30,18 @@ function getDaysArray() { ]; } +function getLongDaysArray() { + return [ + _t('Sunday'), + _t('Monday'), + _t('Tuesday'), + _t('Wednesday'), + _t('Thursday'), + _t('Friday'), + _t('Saturday'), + ]; +} + function getMonthsArray() { return [ _t('Jan'), @@ -96,6 +108,38 @@ module.exports = { }); }, + formatDateSeparator: function(date) { + const days = getDaysArray(); + const longDays = getLongDaysArray(); + const months = getMonthsArray(); + + const today = new Date(); + const yesterday = new Date(); + yesterday.setDate(today.getDate() - 1); + + if (date.toDateString() === today.toDateString()) { + return _t('Today'); + } else if (date.toDateString() === yesterday.toDateString()) { + return _t('Yesterday'); + } else if (today.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) { + return longDays[date.getDay()]; + } else if (today.getTime() - date.getTime() < 365 * 24 * 60 * 60 * 1000) { + return _t('%(weekDayName)s, %(monthName)s %(day)s', { + weekDayName: days[date.getDay()], + monthName: months[date.getMonth()], + day: date.getDate(), + fullYear: date.getFullYear(), + }); + } else { + return _t('%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s', { + weekDayName: days[date.getDay()], + monthName: months[date.getMonth()], + day: date.getDate(), + fullYear: date.getFullYear(), + }); + } + }, + formatTime: function(date, showTwelveHour=false) { if (showTwelveHour) { return twelveHourTime(date); diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 460ed43e82..6d999c9619 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -61,9 +61,6 @@ module.exports = React.createClass({ // for pending messages. ourUserId: React.PropTypes.string, - // true to suppress the date at the start of the timeline - suppressFirstDateSeparator: React.PropTypes.bool, - // whether to show read receipts manageReadReceipts: React.PropTypes.bool, @@ -517,10 +514,10 @@ module.exports = React.createClass({ _wantsDateSeparator: function(prevEvent, nextEventDate) { if (prevEvent == null) { - // first event in the panel: depends if we could back-paginate from - // here. - return !this.props.suppressFirstDateSeparator; + // First event in the panel always wants a DateSeparator + return true; } + const prevEventDate = prevEvent.getDate(); if (!nextEventDate || !prevEventDate) { return false; diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index a8a2ec181b..cbd2954918 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -17,6 +17,7 @@ limitations under the License. var React = require("react"); var ReactDOM = require("react-dom"); var GeminiScrollbar = require('react-gemini-scrollbar'); +import { StickyContainer } from 'react-sticky'; import Promise from 'bluebird'; var KeyCode = require('../../KeyCode'); @@ -77,111 +78,48 @@ if (DEBUG_SCROLL) { * scroll down further. If stickyBottom is disabled, we just save the scroll * offset as normal. */ -module.exports = React.createClass({ - displayName: 'ScrollPanel', +export default class ScrollPanel extends StickyContainer { - propTypes: { - /* stickyBottom: if set to true, then once the user hits the bottom of - * the list, any new children added to the list will cause the list to - * scroll down to show the new element, rather than preserving the - * existing view. - */ - stickyBottom: React.PropTypes.bool, + constructor() { + super(); + this.onResize = this.onResize.bind(this); + this.onScroll = this.onScroll.bind(this); + } - /* startAtBottom: if set to true, the view is assumed to start - * scrolled to the bottom. - * XXX: It's likley this is unecessary and can be derived from - * stickyBottom, but I'm adding an extra parameter to ensure - * behaviour stays the same for other uses of ScrollPanel. - * If so, let's remove this parameter down the line. - */ - startAtBottom: React.PropTypes.bool, - - /* onFillRequest(backwards): a callback which is called on scroll when - * the user nears the start (backwards = true) or end (backwards = - * false) of the list. - * - * This should return a promise; no more calls will be made until the - * promise completes. - * - * The promise should resolve to true if there is more data to be - * retrieved in this direction (in which case onFillRequest may be - * called again immediately), or false if there is no more data in this - * directon (at this time) - which will stop the pagination cycle until - * the user scrolls again. - */ - onFillRequest: React.PropTypes.func, - - /* onUnfillRequest(backwards): a callback which is called on scroll when - * there are children elements that are far out of view and could be removed - * without causing pagination to occur. - * - * This function should accept a boolean, which is true to indicate the back/top - * of the panel and false otherwise, and a scroll token, which refers to the - * first element to remove if removing from the front/bottom, and last element - * to remove if removing from the back/top. - */ - onUnfillRequest: React.PropTypes.func, - - /* onScroll: a callback which is called whenever any scroll happens. - */ - onScroll: React.PropTypes.func, - - /* onResize: a callback which is called whenever the Gemini scroll - * panel is resized - */ - onResize: React.PropTypes.func, - - /* className: classnames to add to the top-level div - */ - className: React.PropTypes.string, - - /* style: styles to add to the top-level div - */ - style: React.PropTypes.object, - }, - - getDefaultProps: function() { - return { - stickyBottom: true, - startAtBottom: true, - onFillRequest: function(backwards) { return Promise.resolve(false); }, - onUnfillRequest: function(backwards, scrollToken) {}, - onScroll: function() {}, - }; - }, - - componentWillMount: function() { + componentWillMount() { this._pendingFillRequests = {b: null, f: null}; this.resetScrollState(); - }, + } - componentDidMount: function() { + componentDidMount() { this.checkFillState(); - }, + } - componentDidUpdate: function() { + componentDidUpdate() { // after adding event tiles, we may need to tweak the scroll (either to // keep at the bottom of the timeline, or to maintain the view after // adding events to the top). // // This will also re-check the fill state, in case the paginate was inadequate this.checkScroll(); - }, + } - componentWillUnmount: function() { + componentWillUnmount() { // set a boolean to say we've been unmounted, which any pending // promises can use to throw away their results. // // (We could use isMounted(), but facebook have deprecated that.) this.unmounted = true; - }, + } - onScroll: function(ev) { + onScroll(ev) { var sn = this._getScrollNode(); debuglog("Scroll event: offset now:", sn.scrollTop, "_lastSetScroll:", this._lastSetScroll); + this.node = sn; + this.notifySubscribers(ev); + // Sometimes we see attempts to write to scrollTop essentially being // ignored. (Or rather, it is successfully written, but on the next // scroll event, it's been reset again). @@ -217,27 +155,27 @@ module.exports = React.createClass({ this.props.onScroll(ev); this.checkFillState(); - }, + } - onResize: function() { + onResize() { this.props.onResize(); this.checkScroll(); this.refs.geminiPanel.forceUpdate(); - }, + } // after an update to the contents of the panel, check that the scroll is // where it ought to be, and set off pagination requests if necessary. - checkScroll: function() { + checkScroll() { this._restoreSavedScrollState(); this.checkFillState(); - }, + } // return true if the content is fully scrolled down right now; else false. // // note that this is independent of the 'stuckAtBottom' state - it is simply // about whether the the content is scrolled down right now, irrespective of // whether it will stay that way when the children update. - isAtBottom: function() { + isAtBottom() { var sn = this._getScrollNode(); // there seems to be some bug with flexbox/gemini/chrome/richvdh's @@ -247,7 +185,7 @@ module.exports = React.createClass({ // that we're at the bottom when we're still a few pixels off. return sn.scrollHeight - Math.ceil(sn.scrollTop) <= sn.clientHeight + 3; - }, + } // returns the vertical height in the given direction that can be removed from // the content box (which has a height of scrollHeight, see checkFillState) without @@ -280,17 +218,17 @@ module.exports = React.createClass({ // |#########| - | // |#########| | // `---------' - - _getExcessHeight: function(backwards) { + _getExcessHeight(backwards) { var sn = this._getScrollNode(); if (backwards) { return sn.scrollTop - sn.clientHeight - UNPAGINATION_PADDING; } else { return sn.scrollHeight - (sn.scrollTop + 2*sn.clientHeight) - UNPAGINATION_PADDING; } - }, + } // check the scroll state and send out backfill requests if necessary. - checkFillState: function() { + checkFillState() { if (this.unmounted) { return; } @@ -329,10 +267,10 @@ module.exports = React.createClass({ // need to forward-fill this._maybeFill(false); } - }, + } // check if unfilling is possible and send an unfill request if necessary - _checkUnfillState: function(backwards) { + _checkUnfillState(backwards) { let excessHeight = this._getExcessHeight(backwards); if (excessHeight <= 0) { return; @@ -373,10 +311,10 @@ module.exports = React.createClass({ this.props.onUnfillRequest(backwards, markerScrollToken); }, UNFILL_REQUEST_DEBOUNCE_MS); } - }, + } // check if there is already a pending fill request. If not, set one off. - _maybeFill: function(backwards) { + _maybeFill(backwards) { var dir = backwards ? 'b' : 'f'; if (this._pendingFillRequests[dir]) { debuglog("ScrollPanel: Already a "+dir+" fill in progress - not starting another"); @@ -408,7 +346,7 @@ module.exports = React.createClass({ this.checkFillState(); } }).done(); - }, + } /* get the current scroll state. This returns an object with the following * properties: @@ -424,9 +362,9 @@ module.exports = React.createClass({ * the number of pixels the bottom of the tracked child is above the * bottom of the scroll panel. */ - getScrollState: function() { + getScrollState() { return this.scrollState; - }, + } /* reset the saved scroll state. * @@ -440,46 +378,46 @@ module.exports = React.createClass({ * no use if no children exist yet, or if you are about to replace the * child list.) */ - resetScrollState: function() { + resetScrollState() { this.scrollState = {stuckAtBottom: this.props.startAtBottom}; - }, + } /** * jump to the top of the content. */ - scrollToTop: function() { + scrollToTop() { this._setScrollTop(0); this._saveScrollState(); - }, + } /** * jump to the bottom of the content. */ - scrollToBottom: function() { + scrollToBottom() { // the easiest way to make sure that the scroll state is correctly // saved is to do the scroll, then save the updated state. (Calculating // it ourselves is hard, and we can't rely on an onScroll callback // happening, since there may be no user-visible change here). this._setScrollTop(Number.MAX_VALUE); this._saveScrollState(); - }, + } /** * Page up/down. * * mult: -1 to page up, +1 to page down */ - scrollRelative: function(mult) { + scrollRelative(mult) { var scrollNode = this._getScrollNode(); var delta = mult * scrollNode.clientHeight * 0.5; this._setScrollTop(scrollNode.scrollTop + delta); this._saveScrollState(); - }, + } /** * Scroll up/down in response to a scroll key */ - handleScrollKey: function(ev) { + handleScrollKey(ev) { switch (ev.keyCode) { case KeyCode.PAGE_UP: if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { @@ -505,7 +443,7 @@ module.exports = React.createClass({ } break; } - }, + } /* Scroll the panel to bring the DOM node with the scroll token * `scrollToken` into view. @@ -518,7 +456,7 @@ module.exports = React.createClass({ * node (specifically, the bottom of it) will be positioned. If omitted, it * defaults to 0. */ - scrollToToken: function(scrollToken, pixelOffset, offsetBase) { + scrollToToken(scrollToken, pixelOffset, offsetBase) { pixelOffset = pixelOffset || 0; offsetBase = offsetBase || 0; @@ -540,11 +478,11 @@ module.exports = React.createClass({ // ... then make it so. this._restoreSavedScrollState(); - }, + } // set the scrollTop attribute appropriately to position the given child at the // given offset in the window. A helper for _restoreSavedScrollState. - _scrollToToken: function(scrollToken, pixelOffset) { + _scrollToToken(scrollToken, pixelOffset) { /* find the dom node with the right scrolltoken */ var node; var messages = this.refs.itemlist.children; @@ -576,9 +514,9 @@ module.exports = React.createClass({ this._setScrollTop(scrollNode.scrollTop + scrollDelta); } - }, + } - _saveScrollState: function() { + _saveScrollState() { if (this.props.stickyBottom && this.isAtBottom()) { this.scrollState = { stuckAtBottom: true }; debuglog("ScrollPanel: Saved scroll state", this.scrollState); @@ -616,9 +554,9 @@ module.exports = React.createClass({ } else { debuglog("ScrollPanel: unable to save scroll state: found no children in the viewport"); } - }, + } - _restoreSavedScrollState: function() { + _restoreSavedScrollState() { var scrollState = this.scrollState; var scrollNode = this._getScrollNode(); @@ -628,9 +566,9 @@ module.exports = React.createClass({ this._scrollToToken(scrollState.trackedScrollToken, scrollState.pixelOffset); } - }, + } - _setScrollTop: function(scrollTop) { + _setScrollTop(scrollTop) { var scrollNode = this._getScrollNode(); var prevScroll = scrollNode.scrollTop; @@ -652,12 +590,12 @@ module.exports = React.createClass({ debuglog("ScrollPanel: set scrollTop:", scrollNode.scrollTop, "requested:", scrollTop, "_lastSetScroll:", this._lastSetScroll); - }, + } /* get the DOM node which has the scrollTop property we care about for our * message panel. */ - _getScrollNode: function() { + _getScrollNode() { if (this.unmounted) { // this shouldn't happen, but when it does, turn the NPE into // something more meaningful. @@ -665,21 +603,91 @@ module.exports = React.createClass({ } return this.refs.geminiPanel.scrollbar.getViewElement(); - }, + } - render: function() { + render() { // TODO: the classnames on the div and ol could do with being updated to // reflect the fact that we don't necessarily contain a list of messages. // it's not obvious why we have a separate div and ol anyway. - return ( -
-
    - {this.props.children} -
-
-
- ); - }, -}); + return ( + +
+
    + {this.props.children} +
+
+
+ ); + } +} + +ScrollPanel.propTypes = { + /* stickyBottom: if set to true, then once the user hits the bottom of + * the list, any new children added to the list will cause the list to + * scroll down to show the new element, rather than preserving the + * existing view. + */ + stickyBottom: React.PropTypes.bool, + + /* startAtBottom: if set to true, the view is assumed to start + * scrolled to the bottom. + * XXX: It's likley this is unecessary and can be derived from + * stickyBottom, but I'm adding an extra parameter to ensure + * behaviour stays the same for other uses of ScrollPanel. + * If so, let's remove this parameter down the line. + */ + startAtBottom: React.PropTypes.bool, + + /* onFillRequest(backwards): a callback which is called on scroll when + * the user nears the start (backwards = true) or end (backwards = + * false) of the list. + * + * This should return a promise; no more calls will be made until the + * promise completes. + * + * The promise should resolve to true if there is more data to be + * retrieved in this direction (in which case onFillRequest may be + * called again immediately), or false if there is no more data in this + * directon (at this time) - which will stop the pagination cycle until + * the user scrolls again. + */ + onFillRequest: React.PropTypes.func, + + /* onUnfillRequest(backwards): a callback which is called on scroll when + * there are children elements that are far out of view and could be removed + * without causing pagination to occur. + * + * This function should accept a boolean, which is true to indicate the back/top + * of the panel and false otherwise, and a scroll token, which refers to the + * first element to remove if removing from the front/bottom, and last element + * to remove if removing from the back/top. + */ + onUnfillRequest: React.PropTypes.func, + + /* onScroll: a callback which is called whenever any scroll happens. + */ + onScroll: React.PropTypes.func, + + /* onResize: a callback which is called whenever the Gemini scroll + * panel is resized + */ + onResize: React.PropTypes.func, + + /* className: classnames to add to the top-level div + */ + className: React.PropTypes.string, + + /* style: styles to add to the top-level div + */ + style: React.PropTypes.object, +}; + +ScrollPanel.defaultProps = { + stickyBottom: true, + startAtBottom: true, + onFillRequest: function(backwards) { return Promise.resolve(false); }, + onUnfillRequest: function(backwards, scrollToken) {}, + onScroll: function() {}, +}; diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 6be31361dd..6c7073fd63 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -1125,7 +1125,6 @@ var TimelinePanel = React.createClass({ highlightedEventId={ this.props.highlightedEventId } readMarkerEventId={ this.state.readMarkerEventId } readMarkerVisible={ this.state.readMarkerVisible } - suppressFirstDateSeparator={ this.state.canBackPaginate } showUrlPreview = { this.props.showUrlPreview } manageReadReceipts = { this.props.manageReadReceipts } ourUserId={ MatrixClientPeg.get().credentials.userId } From 69bce6aee51e6300fc1d1ed6e916c66a0e1f1d24 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Wed, 30 Aug 2017 17:35:26 +0100 Subject: [PATCH 02/43] Update tests to reflect not supressing first date separator --- test/components/structures/TimelinePanel-test.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/components/structures/TimelinePanel-test.js b/test/components/structures/TimelinePanel-test.js index 98ec65b8e8..c13d149ed0 100644 --- a/test/components/structures/TimelinePanel-test.js +++ b/test/components/structures/TimelinePanel-test.js @@ -234,7 +234,6 @@ describe('TimelinePanel', function() { // 5 times, and we should have given up paginating expect(client.paginateEventTimeline.callCount).toEqual(5); expect(messagePanel.props.backPaginating).toBe(false); - expect(messagePanel.props.suppressFirstDateSeparator).toBe(false); // now, if we update the events, there shouldn't be any // more requests. @@ -339,7 +338,6 @@ describe('TimelinePanel', function() { awaitScroll().then(() => { // we should now have loaded the first few events expect(messagePanel.props.backPaginating).toBe(false); - expect(messagePanel.props.suppressFirstDateSeparator).toBe(true); // back-paginate until we hit the start return backPaginate(); @@ -347,7 +345,6 @@ describe('TimelinePanel', function() { // hopefully, we got to the start of the timeline expect(messagePanel.props.backPaginating).toBe(false); - expect(messagePanel.props.suppressFirstDateSeparator).toBe(false); var events = scryEventTiles(panel); expect(events[0].props.mxEvent).toBe(timeline.getEvents()[0]); From cdb28f956e5cab941cf66e94238ca7e5be23c1a0 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 31 Aug 2017 16:29:31 +0100 Subject: [PATCH 03/43] Add comment for StickyContainer extension --- src/components/structures/ScrollPanel.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index cbd2954918..abb9ddff49 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -117,7 +117,11 @@ export default class ScrollPanel extends StickyContainer { debuglog("Scroll event: offset now:", sn.scrollTop, "_lastSetScroll:", this._lastSetScroll); + // Set the node and notify subscribers of the StickContainer + // By extending StickyContainer, we can set the scroll node to be that of the + // ScrolPanel to allow any `` children to be sticky, namely DateSeparators. this.node = sn; + // Update subscribers - arbitrarily nested `` children this.notifySubscribers(ev); // Sometimes we see attempts to write to scrollTop essentially being From c9c07713557b92eb341552bce87c440bfd63277d Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Thu, 31 Aug 2017 16:29:45 +0100 Subject: [PATCH 04/43] Spelling --- src/components/structures/ScrollPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index abb9ddff49..3ea699798e 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -117,7 +117,7 @@ export default class ScrollPanel extends StickyContainer { debuglog("Scroll event: offset now:", sn.scrollTop, "_lastSetScroll:", this._lastSetScroll); - // Set the node and notify subscribers of the StickContainer + // Set the node and notify subscribers of the StickyContainer // By extending StickyContainer, we can set the scroll node to be that of the // ScrolPanel to allow any `` children to be sticky, namely DateSeparators. this.node = sn; From aa0b94847b088c83bc3a4ea242420c3ef98c6598 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 1 Sep 2017 16:17:22 +0100 Subject: [PATCH 05/43] Prepare changelog for v0.10.3-rc.1 --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5e596144e..f4e9ae9a78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,36 @@ +Changes in [0.10.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.3-rc.1) (2017-09-01) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.2...v0.10.3-rc.1) + + * Fix room change sometimes being very slow + [\#1354](https://github.com/matrix-org/matrix-react-sdk/pull/1354) + * apply shouldHideEvent fn to onRoomTimeline for RoomStatusBar + [\#1346](https://github.com/matrix-org/matrix-react-sdk/pull/1346) + * text4event widget modified, used to show widget added each time. + [\#1345](https://github.com/matrix-org/matrix-react-sdk/pull/1345) + * separate concepts of showing and managing RRs to fix regression + [\#1352](https://github.com/matrix-org/matrix-react-sdk/pull/1352) + * Make staging widgets work with live and vice versa. + [\#1350](https://github.com/matrix-org/matrix-react-sdk/pull/1350) + * Avoid breaking /sync with uncaught exceptions + [\#1349](https://github.com/matrix-org/matrix-react-sdk/pull/1349) + * we need to pass whether it is an invite RoomSubList explicitly (i18n) + [\#1343](https://github.com/matrix-org/matrix-react-sdk/pull/1343) + * Percent encoding isn't a valid thing within _t + [\#1348](https://github.com/matrix-org/matrix-react-sdk/pull/1348) + * Fix spurious notifications + [\#1339](https://github.com/matrix-org/matrix-react-sdk/pull/1339) + * Unbreak password reset with a non-default HS + [\#1347](https://github.com/matrix-org/matrix-react-sdk/pull/1347) + * Remove unnecessary 'load' on notif audio element + [\#1341](https://github.com/matrix-org/matrix-react-sdk/pull/1341) + * _tJsx returns a React Object, the sub fn must return a React Object + [\#1340](https://github.com/matrix-org/matrix-react-sdk/pull/1340) + * Fix deprecation warning about promise.defer() + [\#1292](https://github.com/matrix-org/matrix-react-sdk/pull/1292) + * Fix click to insert completion + [\#1331](https://github.com/matrix-org/matrix-react-sdk/pull/1331) + Changes in [0.10.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.2) (2017-08-24) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.1...v0.10.2) From c07362d7c159c83f1ea0568765e13baa78b4cb29 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 1 Sep 2017 16:17:22 +0100 Subject: [PATCH 06/43] v0.10.3-rc.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc352cb8db..0610d42c0d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.10.2", + "version": "0.10.3-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 79ee41351c106b6504236020b193915775dd27d9 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 4 Sep 2017 15:45:28 +0100 Subject: [PATCH 07/43] Fix typo --- src/components/structures/MyGroups.js | 2 +- src/i18n/strings/basefile.json | 2 +- src/i18n/strings/be.json | 2 +- src/i18n/strings/de_DE.json | 2 +- src/i18n/strings/en_EN.json | 2 +- src/i18n/strings/en_US.json | 2 +- src/i18n/strings/eu.json | 2 +- src/i18n/strings/fi.json | 2 +- src/i18n/strings/fr.json | 2 +- src/i18n/strings/hu.json | 2 +- src/i18n/strings/lv.json | 2 +- src/i18n/strings/nl.json | 2 +- src/i18n/strings/ru.json | 2 +- src/i18n/strings/zh_Hant.json | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js index 0b8055beda..624f3c67dd 100644 --- a/src/components/structures/MyGroups.js +++ b/src/components/structures/MyGroups.js @@ -125,7 +125,7 @@ export default withMatrixClient(React.createClass({ {_tJsx( - 'To join an exisitng group you\'ll have to '+ + 'To join an existing group you\'ll have to '+ 'know its group identifier; this will look '+ 'something like +example:matrix.org.', /(.*)<\/i>/, diff --git a/src/i18n/strings/basefile.json b/src/i18n/strings/basefile.json index 9e26dfeeb6..0967ef424b 100644 --- a/src/i18n/strings/basefile.json +++ b/src/i18n/strings/basefile.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/src/i18n/strings/be.json b/src/i18n/strings/be.json index 9e26dfeeb6..0967ef424b 100644 --- a/src/i18n/strings/be.json +++ b/src/i18n/strings/be.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 24786418a8..d4e61ca310 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1022,7 +1022,7 @@ "You are a member of these groups:": "Du bist Mitglied in folgenden Gruppen:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Erstelle eine Gruppe um deine Community darzustellen! Definiere eine Menge von Räumen und deine eigene angepasste Startseite um deinen Bereich im Matrix-Universum zu markieren.", "Join an existing group": "Trete eine existierenden Gruppe bei", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Um einer bereits vorhandenen Gruppe beitreten zu können, muss dir die Gruppen-Kennung bekannt sein. Diese sieht ungefähr so aus: '+example:matrix.org'.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Um einer bereits vorhandenen Gruppe beitreten zu können, muss dir die Gruppen-Kennung bekannt sein. Diese sieht ungefähr so aus: '+example:matrix.org'.", "Featured Rooms:": "Hervorgehobene Räume:", "Error whilst fetching joined groups": "Fehler beim Laden beigetretener Gruppen", "Featured Users:": "Hervorgehobene Nutzer:", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2ef0fba86d..2340def67c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -966,7 +966,7 @@ "You are a member of these groups:": "You are a member of these groups:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.", "Join an existing group": "Join an existing group", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.", "Featured Rooms:": "Featured Rooms:", "Error whilst fetching joined groups": "Error whilst fetching joined groups", "Featured Users:": "Featured Users:", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index ae9c075683..d75c3d7408 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -985,5 +985,5 @@ "Robot check is currently unavailable on desktop - please use a web browser": "Robot check is currently unavailable on desktop - please use a web browser", "Verifies a user, device, and pubkey tuple": "Verifies a user, device, and pubkey tuple", "It is currently only possible to create groups on your own home server: use a group ID ending with %(domain)s": "It is currently only possible to create groups on your own home server: use a group ID ending with %(domain)s", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org." + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org." } diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index f0821f57df..1c80c9e338 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -971,7 +971,7 @@ "%(widgetName)s widget added by %(senderName)s": "%(widgetName)s trepeta gehitu du %(senderName)s erabiltzaileak", "%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s trepeta kendu du %(senderName)s erabiltzaileak", "Verifies a user, device, and pubkey tuple": "Erabiltzaile, gailu eta gako publiko multzoa egiaztatzen du", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Dagoen talde batetara elkartzeko taldearen identifikatzailea ezagutu behar duzu, honen antza du: +adibidea:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Dagoen talde batetara elkartzeko taldearen identifikatzailea ezagutu behar duzu, honen antza du: +adibidea:matrix.org.", "Robot check is currently unavailable on desktop - please use a web browser": "Robot egiaztaketa orain ez dago eskuragarri mahaigainean - erabili web nabigatzailea", "%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s trepeta aldatu du %(senderName)s erabiltzaileak" } diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index 9e26dfeeb6..0967ef424b 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index aeebc64c83..5ce9eaf02c 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -969,7 +969,7 @@ "You are a member of these groups:": "Vous êtes membre des groupes suivants :", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Créez un groupe pour représenter votre communauté ! Définissez un jeu de salons et votre propre page d'accueil pour marquer votre espace dans l'univers Matrix.", "Join an existing group": "Rejoindre un groupe existant", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Pour rejoindre un groupe existant, vous devez connaître l'identifiant de ce groupe ; il ressemblera à +exemple:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Pour rejoindre un groupe existant, vous devez connaître l'identifiant de ce groupe ; il ressemblera à +exemple:matrix.org.", "Featured Rooms:": "Salons mis en avant :", "Error whilst fetching joined groups": "Erreur en récupérant la liste des groupes", "Featured Users:": "Utilisateurs mis en avant :", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index e935f63cff..a51fc01044 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -953,7 +953,7 @@ "You are a member of these groups:": "Ezeknek a csoportoknak vagy a tagja:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Hozz létre csoportot a közösség meghatározásához! Jelölj ki szobákat és saját kezdőoldalt amivel meghatározhatod a territóriumodat a Matrix univerzumában.", "Join an existing group": "Csatlakozz meglévő csoporthoz", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Ahhoz, hogy meglévő csoporthoz csatlakozhass tudnod kell a csoport azonosítóját ami valahogy így nézhet ki: +példa:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Ahhoz, hogy meglévő csoporthoz csatlakozhass tudnod kell a csoport azonosítóját ami valahogy így nézhet ki: +példa:matrix.org.", "Featured Rooms:": "Kiemelt szobák:", "Error whilst fetching joined groups": "Hiba a csatlakozott csoportok betöltésénél", "Featured Users:": "Kiemelt felhasználók:", diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index d4b4052941..6deceac02b 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -960,7 +960,7 @@ "You are a member of these groups:": "Tu esi sekojošo grupu biedrs:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Izveido grupu, lai prezentētu savu komūnu! Definē istabu grupu un savu personīgo mājaslapu, lai iezīmētu savu vietu Matrix universumā.", "Join an existing group": "Pievienoties eksistējošai grupai", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Lai pievienotos eksistējošai grupai, Tev ir jāzina šīs grupas identifikators. Piemēram: +latvija:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Lai pievienotos eksistējošai grupai, Tev ir jāzina šīs grupas identifikators. Piemēram: +latvija:matrix.org.", "Featured Rooms:": "Ieteiktās istabas:", "Error whilst fetching joined groups": "Notika kļūda, nosakot pievienotās grupas", "Featured Users:": "Ieteiktie lietotāji:", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 1010b31a87..d72813177b 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -964,7 +964,7 @@ "You are a member of these groups:": "Je bent een deelnemer van deze groepen:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Maak een groep aan om je gemeenschap te representateren! Defineer een set van ruimtes en maak je eigen aangepaste homepagina om je eigen plek in het Matrix universum te creëren.", "Join an existing group": "Treed tot een bestaande groep toe", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Om tot een bestaande groep toe te treden moet je groep identificatie weten; dit zal er ongeveer uit zien als +voorbeeld:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Om tot een bestaande groep toe te treden moet je groep identificatie weten; dit zal er ongeveer uit zien als +voorbeeld:matrix.org.", "Featured Rooms:": "Prominente Ruimtes:", "Error whilst fetching joined groups": "Er is een fout opgetreden tijdens het ophalen van de tot toegretreden groepen", "Featured Users:": "Prominente Gebruikers:", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 3ff15f4f5c..e15fce90c4 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -1012,7 +1012,7 @@ "You are a member of these groups:": "Вы являетесь членом этих групп:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "Создайте группу для представления своего сообщества! Определите набор комнат и собственную домашнюю страницу, чтобы выделить свое пространство во вселенной Matrix.", "Join an existing group": "Присоединиться к существующей группе", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Чтобы присоединиться к группе, вам нужно знать ее идентификатор; он выглядит примерно так:+пример:matrix.org.", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "Чтобы присоединиться к группе, вам нужно знать ее идентификатор; он выглядит примерно так:+пример:matrix.org.", "Featured Rooms:": "Рекомендуемые комнаты:", "Error whilst fetching joined groups": "Ошибка при извлечении объединенных групп", "Featured Users:": "Избранные пользователи:", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 27ec122709..2f3d36b481 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -968,7 +968,7 @@ "You are a member of these groups:": "您是這些群組的成員:", "Create a group to represent your community! Define a set of rooms and your own custom homepage to mark out your space in the Matrix universe.": "建立一個群組來代表您的社群!定義一組聊天室與您自己的自訂首頁來標記您在 Matrix 世界中的空間。", "Join an existing group": "加入既有的群組", - "To join an exisitng group you'll have to know its group identifier; this will look something like +example:matrix.org.": "要加入既有的群組,您將會需要知道其群組識別符;其看起來會像是 +範例:matrix.org。", + "To join an existing group you'll have to know its group identifier; this will look something like +example:matrix.org.": "要加入既有的群組,您將會需要知道其群組識別符;其看起來會像是 +範例:matrix.org。", "Featured Rooms:": "特色聊天室:", "Error whilst fetching joined groups": "在擷取已加入的群組時發生錯誤", "Featured Users:": "特色使用者:", From de2940f469730b7278cf0cf0d72906c56457a811 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 4 Sep 2017 17:09:36 +0100 Subject: [PATCH 08/43] Fix plurals in translations Weblate doesn't understand counterpart's multi-level format for plurals and helpfully mangles them to be dot-separated keys when it saves the translation file. Store the source files with pipe separators and convert to counterpart format at build time. --- src/i18n/strings/de_DE.json | 18 +++++++++--------- src/i18n/strings/el.json | 20 +++++++++----------- src/i18n/strings/en_EN.json | 26 +++++++++----------------- src/i18n/strings/en_US.json | 18 +++++++++--------- src/i18n/strings/es.json | 14 +++++++------- src/i18n/strings/eu.json | 18 +++++++++--------- src/i18n/strings/fr.json | 18 +++++++++--------- src/i18n/strings/hu.json | 18 +++++++++--------- src/i18n/strings/ja.json | 4 ++-- src/i18n/strings/ko.json | 20 +++++++++----------- src/i18n/strings/lv.json | 18 +++++++++--------- src/i18n/strings/nl.json | 18 +++++++++--------- src/i18n/strings/pt.json | 18 +++++++++--------- src/i18n/strings/pt_BR.json | 20 +++++++++----------- src/i18n/strings/ru.json | 18 +++++++++--------- src/i18n/strings/sv.json | 8 ++++---- src/i18n/strings/te.json | 4 ++-- src/i18n/strings/th.json | 20 +++++++++----------- src/i18n/strings/tr.json | 20 +++++++++----------- src/i18n/strings/uk.json | 6 ++---- src/i18n/strings/zh_Hans.json | 8 ++++---- src/i18n/strings/zh_Hant.json | 18 +++++++++--------- 22 files changed, 165 insertions(+), 185 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index d4e61ca310..e4a3d335a3 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -552,8 +552,8 @@ "Failed to forget room %(errCode)s": "Das Entfernen des Raums ist fehlgeschlagen %(errCode)s", "Failed to join the room": "Fehler beim Betreten des Raumes", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Eine Textnachricht wurde an +%(msisdn)s gesendet. Bitte den darin enthaltenen Verifizierungscode eingeben", - "and %(count)s others....other": "und %(count)s weitere...", - "and %(count)s others....one": "und ein(e) weitere(r)...", + "and %(count)s others...|other": "und %(count)s weitere...", + "and %(count)s others...|one": "und ein(e) weitere(r)...", "Are you sure?": "Bist du sicher?", "Attachment": "Anhang", "Ban": "Verbannen", @@ -877,15 +877,15 @@ "Start new chat": "Neuen Chat starten", "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", + "%(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 bei der Kommunikation mit dem angegebenen Home-Server.", "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.", - "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", + "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 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", @@ -961,8 +961,8 @@ "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 eventuell mit einem anderen Konto anmelden oder alternativ 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)", + "(~%(count)s results)|one": "(~%(count)s Ergebnis)", + "(~%(count)s results)|other": "(~%(count)s Ergebnis)", "Device Name": "Geräte-Name", "(could not connect media)": "(Medienverbindung konnte nicht hergestellt werden)", "(no answer)": "(keine Antwort)", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index b1b676b505..1211aab6ad 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -175,10 +175,8 @@ "an address": "μία διεύθηνση", "%(items)s and %(remaining)s others": "%(items)s και %(remaining)s ακόμα", "%(items)s and one other": "%(items)s και ένας ακόμα", - "and %(count)s others...": { - "other": "και %(count)s άλλοι...", - "one": "και ένας ακόμα..." - }, + "and %(count)s others...|one": "και ένας ακόμα...", + "and %(count)s others...|other": "και %(count)s άλλοι...", "%(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 άλλοι γράφουν", @@ -405,8 +403,8 @@ "click to reveal": "κάντε κλικ για εμφάνιση", "Click to unmute video": "Κάντε κλικ για άρση σίγασης του βίντεο", "Click to unmute audio": "Κάντε κλικ για άρση σίγασης του ήχου", - "%(count)s new messages.one": "%(count)s νέο μήνυμα", - "%(count)s new messages.other": "%(count)s νέα μηνύματα", + "%(count)s new messages|one": "%(count)s νέο μήνυμα", + "%(count)s new messages|other": "%(count)s νέα μηνύματα", "Custom": "Προσαρμοσμένο", "Decline": "Απόρριψη", "Disable Notifications": "Απενεργοποίηση ειδοποιήσεων", @@ -569,8 +567,8 @@ "Encrypt room": "Κρυπτογράφηση δωματίου", "Room": "Δωμάτιο", "Auto-complete": "Αυτόματη συμπλήρωση", - "(~%(count)s results).one": "(~%(count)s αποτέλεσμα)", - "(~%(count)s results).other": "(~%(count)s αποτελέσματα)", + "(~%(count)s results)|one": "(~%(count)s αποτέλεσμα)", + "(~%(count)s results)|other": "(~%(count)s αποτελέσματα)", "Active call": "Ενεργή κλήση", "strike": "επιγράμμιση", "bullet": "κουκκίδα", @@ -719,8 +717,8 @@ "to start a chat with someone": "για να ξεκινήσετε μια συνομιλία με κάποιον", "Unable to capture screen": "Αδυναμία σύλληψης οθόνης", "Unknown (user, device) pair:": "Άγνωστο ζεύγος (χρήστη, συσκευής):", - "Uploading %(filename)s and %(count)s others.zero": "Γίνεται αποστολή του %(filename)s", - "Uploading %(filename)s and %(count)s others.other": "Γίνεται αποστολή του %(filename)s και %(count)s υπολοίπων", + "Uploading %(filename)s and %(count)s others|zero": "Γίνεται αποστολή του %(filename)s", + "Uploading %(filename)s and %(count)s others|other": "Γίνεται αποστολή του %(filename)s και %(count)s υπολοίπων", "uploaded a file": "ανέβασε ένα αρχείο", "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (δύναμη %(powerLevelNumber)s)", "Verification Pending": "Εκκρεμεί επιβεβαίωση", @@ -820,7 +818,7 @@ "to tag direct chat": "για να οριστεί ετικέτα σε απευθείας συνομιλία", "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "Ο %(senderName)s ενεργοποίησε την από άκρο σε άκρο κρυπτογράφηση (algorithm %(algorithm)s).", "Undecryptable": "Μη αποκρυπτογραφημένο", - "Uploading %(filename)s and %(count)s others.one": "Γίνεται αποστολή του %(filename)s και %(count)s υπολοίπα", + "Uploading %(filename)s and %(count)s others|one": "Γίνεται αποστολή του %(filename)s και %(count)s υπολοίπα", "Would you like to accept or decline this invitation?": "Θα θέλατε να δεχθείτε ή να απορρίψετε την πρόσκληση;", "You already have existing direct chats with this user:": "Έχετε ήδη απευθείας συνομιλίες με τον χρήστη:", "You are trying to access %(roomName)s.": "Προσπαθείτε να έχετε πρόσβαση στο %(roomName)s.", diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2340def67c..35ca698c03 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -158,10 +158,8 @@ "%(items)s and %(remaining)s others": "%(items)s and %(remaining)s others", "%(items)s and one other": "%(items)s and one other", "%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s", - "and %(count)s others...": { - "other": "and %(count)s others...", - "one": "and one other..." - }, + "and %(count)s others...|other": "and %(count)s others...", + "and %(count)s others...|one": "and one other...", "%(names)s and %(lastPerson)s are typing": "%(names)s and %(lastPerson)s are typing", "%(names)s and one other are typing": "%(names)s and one other are typing", "%(names)s and %(count)s others are typing": "%(names)s and %(count)s others are typing", @@ -224,10 +222,8 @@ "Confirm your new password": "Confirm your new password", "Continue": "Continue", "Could not connect to the integration server": "Could not connect to the integration server", - "%(count)s new messages": { - "one": "%(count)s new message", - "other": "%(count)s new messages" - }, + "%(count)s new messages|one": "%(count)s new message", + "%(count)s new messages|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", @@ -627,11 +623,9 @@ "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", - "other": "Uploading %(filename)s and %(count)s others" - }, + "Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s", + "Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other", + "Uploading %(filename)s and %(count)s others|other": "Uploading %(filename)s and %(count)s others", "uploaded a file": "uploaded a file", "Upload avatar": "Upload avatar", "Upload Failed": "Upload Failed", @@ -749,10 +743,8 @@ "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.", - "(~%(count)s results)": { - "one": "(~%(count)s result)", - "other": "(~%(count)s results)" - }, + "(~%(count)s results)|one": "(~%(count)s result)", + "(~%(count)s results)|other": "(~%(count)s results)", "Cancel": "Cancel", "or": "or", "Active call": "Active call", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index d75c3d7408..bb6a6e8c9b 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -154,8 +154,8 @@ "%(items)s and %(remaining)s others": "%(items)s and %(remaining)s others", "%(items)s and one other": "%(items)s and one other", "%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s", - "and %(count)s others....other": "and %(count)s others...", - "and %(count)s others....one": "and one other...", + "and %(count)s others...|other": "and %(count)s others...", + "and %(count)s others...|one": "and one other...", "%(names)s and %(lastPerson)s are typing": "%(names)s and %(lastPerson)s are typing", "%(names)s and one other are typing": "%(names)s and one other are typing", "%(names)s and %(count)s others are typing": "%(names)s and %(count)s others are typing", @@ -841,8 +841,8 @@ "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", + "%(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", @@ -893,9 +893,9 @@ "unknown caller": "unknown caller", "Unnamed Room": "Unnamed Room", "Unverified": "Unverified", - "Uploading %(filename)s and %(count)s others.zero": "Uploading %(filename)s", - "Uploading %(filename)s and %(count)s others.one": "Uploading %(filename)s and %(count)s other", - "Uploading %(filename)s and %(count)s others.other": "Uploading %(filename)s and %(count)s others", + "Uploading %(filename)s and %(count)s others|zero": "Uploading %(filename)s", + "Uploading %(filename)s and %(count)s others|one": "Uploading %(filename)s and %(count)s other", + "Uploading %(filename)s and %(count)s others|other": "Uploading %(filename)s and %(count)s others", "Upload new:": "Upload new:", "%(user)s is a": "%(user)s is a", "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)", @@ -909,8 +909,8 @@ "You must register to use this functionality": "You must register to use this functionality", "Your home server does not support device management.": "Your home server does not support device management.", "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.", - "(~%(count)s results).one": "(~%(count)s result)", - "(~%(count)s results).other": "(~%(count)s results)", + "(~%(count)s results)|one": "(~%(count)s result)", + "(~%(count)s results)|other": "(~%(count)s results)", "New Password": "New Password", "Device Name": "Device Name", "Start chatting": "Start chatting", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 49f7f76b0b..499da6e819 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -140,8 +140,8 @@ "%(items)s and %(remaining)s others": "%(items)s y %(remaining)s otros", "%(items)s and one other": "%(items)s y otro", "%(items)s and %(lastItem)s": "%(items)s y %(lastItem)s", - "and %(count)s others....other": "y %(count)s otros...", - "and %(count)s others....one": "y otro...", + "and %(count)s others...|other": "y %(count)s otros...", + "and %(count)s others...|one": "y otro...", "%(names)s and %(lastPerson)s are typing": "%(names)s y %(lastPerson)s están escribiendo", "%(names)s and one other are typing": "%(names)s y otro están escribiendo", "%(names)s and %(count)s others are typing": "%(names)s y %(count)s otros están escribiendo", @@ -341,8 +341,8 @@ "Anyone": "Cualquiera", "Click here to join the discussion!": "¡Pulse aquí para unirse a la conversación!", "Close": "Cerrar", - "%(count)s new messages.one": "%(count)s mensaje nuevo", - "%(count)s new messages.other": "%(count)s mensajes nuevos", + "%(count)s new messages|one": "%(count)s mensaje nuevo", + "%(count)s new messages|other": "%(count)s mensajes nuevos", "Create a new chat or reuse an existing one": "Cree una nueva conversación o reutilice una existente", "Custom": "Personalizado", "Custom level": "Nivel personalizado", @@ -688,9 +688,9 @@ "unknown": "desconocido", "Unnamed Room": "Sala sin nombre", "Unverified": "Sin verificar", - "Uploading %(filename)s and %(count)s others.zero": "Subiendo %(filename)s", - "Uploading %(filename)s and %(count)s others.one": "Subiendo %(filename)s y %(count)s otros", - "Uploading %(filename)s and %(count)s others.other": "Subiendo %(filename)s y %(count)s otros", + "Uploading %(filename)s and %(count)s others|zero": "Subiendo %(filename)s", + "Uploading %(filename)s and %(count)s others|one": "Subiendo %(filename)s y %(count)s otros", + "Uploading %(filename)s and %(count)s others|other": "Subiendo %(filename)s y %(count)s otros", "Upload avatar": "Subir avatar", "Upload Failed": "Error al subir", "Upload Files": "Subir archivos", diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index 1c80c9e338..aa9857c3dd 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -337,8 +337,8 @@ "Confirm password": "Berretsi pasahitza", "Conference calls are not supported in this client": "Bezero honek ez ditu konferentzia deiak onartzen", "Could not connect to the integration server": "Ezin izan da integrazio zerbitzarira konektatu", - "%(count)s new messages.one": "mezu berri %(count)s", - "%(count)s new messages.other": "%(count)s mezu berri", + "%(count)s new messages|one": "mezu berri %(count)s", + "%(count)s new messages|other": "%(count)s mezu berri", "Create a new chat or reuse an existing one": "Sortu txat berria edo berrerabili aurreko bat", "Create an account": "Sortu kontua", "Create Room": "Sortu gela", @@ -647,9 +647,9 @@ "Unrecognised command:": "Agindu ezezaguna:", "Unrecognised room alias:": "Gelaren ezizen ezezaguna:", "Unverified": "Egiaztatu gabea", - "Uploading %(filename)s and %(count)s others.zero": "%(filename)s igotzen", - "Uploading %(filename)s and %(count)s others.one": "%(filename)s eta beste %(count)s igotzen", - "Uploading %(filename)s and %(count)s others.other": "%(filename)s eta beste %(count)s igotzen", + "Uploading %(filename)s and %(count)s others|zero": "%(filename)s igotzen", + "Uploading %(filename)s and %(count)s others|one": "%(filename)s eta beste %(count)s igotzen", + "Uploading %(filename)s and %(count)s others|other": "%(filename)s eta beste %(count)s igotzen", "uploaded a file": "fitxategi bat igo du", "Upload avatar": "Igo abatarra", "Upload Failed": "Igoerak huts egin du", @@ -754,8 +754,8 @@ "Sent messages will be stored until your connection has returned.": "Bidalitako mezuak zure konexioa berreskuratu arte gordeko dira.", "Auto-complete": "Osatze automatikoa", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Birbidali guztiak edo baztertu guztiak orain. Mezuak banaka aukeratu ditzakezu ere birbidali ala baztertzeko.", - "(~%(count)s results).one": "(~%(count)s emaitza)", - "(~%(count)s results).other": "(~%(count)s emaitza)", + "(~%(count)s results)|one": "(~%(count)s emaitza)", + "(~%(count)s results)|other": "(~%(count)s emaitza)", "bold": "lodia", "italic": "etzana", "strike": "marratua", @@ -916,8 +916,8 @@ "Disable Peer-to-Peer for 1:1 calls": "Desgaitu P2P biren arteko deietan", "Add a widget": "Gehitu trepeta bat", "Allow": "Baimendu", - "and %(count)s others....other": "eta beste %(count)s...", - "and %(count)s others....one": "eta beste bat...", + "and %(count)s others...|other": "eta beste %(count)s...", + "and %(count)s others...|one": "eta beste bat...", "Cannot add any more widgets": "Ezin dira trepeta gehiago gehitu", "Changes colour scheme of current room": "Gela honen kolore eskema aldatzen du", "Delete widget": "Ezabatu trepeta", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 5ce9eaf02c..f6da302fad 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -191,8 +191,8 @@ "%(names)s and %(lastPerson)s are typing": "%(names)s et %(lastPerson)s sont en train d'écrire", "%(names)s and one other are typing": "%(names)s et un autre sont en train d'écrire", "%(names)s and %(count)s others are typing": "%(names)s et %(count)s d'autres sont en train d'écrire", - "and %(count)s others....other": "et %(count)s autres...", - "and %(count)s others....one": "et un autre...", + "and %(count)s others...|other": "et %(count)s autres...", + "and %(count)s others...|one": "et un autre...", "An email has been sent to": "Un e-mail a été envoyé à", "A new password must be entered.": "Un nouveau mot de passe doit être entré.", "Anyone who knows the room's link, apart from guests": "Tout ceux qui connaissent le lien du salon, à part les visiteurs", @@ -822,16 +822,16 @@ "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", "Add": "Ajouter", - "%(count)s new messages.one": "%(count)s nouveau message", - "%(count)s new messages.other": "%(count)s nouveaux messages", + "%(count)s new messages|one": "%(count)s nouveau message", + "%(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 homeserver.", "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", "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.", - "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", + "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 ou tout annuler maintenant. Vous pouvez aussi sélectionner des messages individuels à envoyer ou annuler.", "Create new room": "Créer un nouveau salon", @@ -895,8 +895,8 @@ "You have been kicked from %(roomName)s by %(userName)s.": "Vous avez été expulsé de %(roomName)s by %(userName)s.", "You may wish to login with a different account, or add this email to this account.": "Vous souhaiteriez peut-être vous identifier avec un autre compte, ou ajouter cette e-mail à votre compte.", "Your home server does not support device management.": "Votre homeserver ne supporte pas la gestion d'appareils.", - "(~%(count)s results).one": "(~%(count)s résultat)", - "(~%(count)s results).other": "(~%(count)s résultats)", + "(~%(count)s results)|one": "(~%(count)s résultat)", + "(~%(count)s results)|other": "(~%(count)s résultats)", "Device Name": "Nom de l'appareil", "Encrypted by a verified device": "Chiffré par un appareil vérifié", "Encrypted by an unverified device": "Chiffré par un appareil non vérifié", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index a51fc01044..eea96f9ea3 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -190,8 +190,8 @@ "%(items)s and %(remaining)s others": "%(items)s és még: %(remaining)s", "%(items)s and one other": "%(items)s és még egy", "%(items)s and %(lastItem)s": "%(items)s és %(lastItem)s", - "and %(count)s others....other": "és még: %(count)s ...", - "and %(count)s others....one": "és még egy...", + "and %(count)s others...|other": "és még: %(count)s ...", + "and %(count)s others...|one": "és még egy...", "%(names)s and %(lastPerson)s are typing": "%(names)s és %(lastPerson)s írnak", "%(names)s and one other are typing": "%(names)s és még valaki ír", "%(names)s and %(count)s others are typing": "%(names)s és %(count)s ember ír", @@ -250,8 +250,8 @@ "Confirm password": "Jelszó megerősítése", "Confirm your new password": "Új jelszó megerősítése", "Could not connect to the integration server": "Az integrációs szerverhez nem lehet kapcsolódni", - "%(count)s new messages.one": "%(count)s új üzenet", - "%(count)s new messages.other": "%(count)s új üzenet", + "%(count)s new messages|one": "%(count)s új üzenet", + "%(count)s new messages|other": "%(count)s új üzenet", "Create a new chat or reuse an existing one": "Új csevegés indítása vagy egy meglévő használata", "Create an account": "Fiók készítése", "Create Room": "Szoba készítése", @@ -610,9 +610,9 @@ "Unrecognised command:": "Ismeretlen parancs:", "Unrecognised room alias:": "Ismeretlen szoba becenév:", "Unverified": "Nem ellenőrzött", - "Uploading %(filename)s and %(count)s others.zero": "%(filename)s feltöltése", - "Uploading %(filename)s and %(count)s others.one": "%(filename)s és még %(count)s db másik feltöltése", - "Uploading %(filename)s and %(count)s others.other": "%(filename)s és még %(count)s db másik feltöltése", + "Uploading %(filename)s and %(count)s others|zero": "%(filename)s feltöltése", + "Uploading %(filename)s and %(count)s others|one": "%(filename)s és még %(count)s db másik feltöltése", + "Uploading %(filename)s and %(count)s others|other": "%(filename)s és még %(count)s db másik feltöltése", "uploaded a file": "fájl feltöltése", "Upload avatar": "Avatar kép feltöltése", "Upload Failed": "Feltöltés sikertelen", @@ -729,8 +729,8 @@ "Sent messages will be stored until your connection has returned.": "Az elküldött üzenetek addig lesznek tárolva amíg a kapcsolatod újra elérhető lesz.", "Auto-complete": "Automatikus kiegészítés", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Most újraküldöd mind vagy eldobod mind. Újraküldésre vagy eldobásra egyenként is kiválaszthatod az üzeneteket.", - "(~%(count)s results).one": "(~%(count)s db eredmény)", - "(~%(count)s results).other": "(~%(count)s db eredmény)", + "(~%(count)s results)|one": "(~%(count)s db eredmény)", + "(~%(count)s results)|other": "(~%(count)s db eredmény)", "or": "vagy", "Active call": "Folyamatban lévő hívás", "bold": "félkövér", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index 04a7c8877c..f0be3024a5 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -44,8 +44,8 @@ "Only people who have been invited": "この部屋に招待された人のみ参加可能", "Hide removed messages": "削除された発言の印を表示しない", "Always show message timestamps": "発言時刻を常に表示", - "%(count)s new messages.one": "新しい発言 %(count)s", - "%(count)s new messages.other": "新しい発言 %(count)s", + "%(count)s new messages|one": "新しい発言 %(count)s", + "%(count)s new messages|other": "新しい発言 %(count)s", "Don't send typing notifications": "文字入力中であることを公表しない", "Filter room members": "参加者検索", "Send a message (unencrypted)": "ここに送信文を入力 (暗号化なし)", diff --git a/src/i18n/strings/ko.json b/src/i18n/strings/ko.json index b76dd40c5e..e5faf01da7 100644 --- a/src/i18n/strings/ko.json +++ b/src/i18n/strings/ko.json @@ -225,10 +225,8 @@ "%(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 %(count)s others...": { - "other": "그리고 %(count)s...", - "one": "그리고 다른 하나..." - }, + "and %(count)s others...|one": "그리고 다른 하나...", + "and %(count)s others...|other": "그리고 %(count)s...", "%(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 분들이 입력중", @@ -267,8 +265,8 @@ "Conference calls are not supported in encrypted rooms": "암호화한 방에서는 전화 회의를 할 수 없어요", "Conference calls are not supported in this client": "이 클라이언트에서는 전화 회의를 할 수 없어요", "Could not connect to the integration server": "통합 서버에 연결할 수 없어요", - "%(count)s new messages.one": "%(count)s 새 메시지", - "%(count)s new messages.other": "%(count)s 새 메시지", + "%(count)s new messages|one": "%(count)s 새 메시지", + "%(count)s new messages|other": "%(count)s 새 메시지", "Create a new chat or reuse an existing one": "새 이야기를 시작하거나 기존에 하던 이야기를 이어하세요", "Cryptography": "암호화", "Current password": "현재 비밀번호", @@ -617,9 +615,9 @@ "Unrecognised command:": "인식 할 수 없는 명령:", "Unrecognised room alias:": "인식할 수 없는 방 가명:", "Unverified": "인증하지 않음", - "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 올리는 중", + "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 avatar": "아바타 올리기", "Upload Failed": "파일을 올리지 못했어요", @@ -736,8 +734,8 @@ "Sent messages will be stored until your connection has returned.": "보내신 메시지는 다시 연결될 때까지 저장할 거에요.", "Auto-complete": "자동 완성", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "전부 다시 보내거나 취소하세요. 다시 보내거나 취소할 메시지를 하나씩 고르실 수도 있어요.", - "(~%(count)s results).one": "(~%(count)s 결과)", - "(~%(count)s results).other": "(~%(count)s 결과)", + "(~%(count)s results)|one": "(~%(count)s 결과)", + "(~%(count)s results)|other": "(~%(count)s 결과)", "or": "혹은", "Active call": "전화 중", "bold": "굵은 획", diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index 6deceac02b..041403b32f 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -218,8 +218,8 @@ "Confirm your new password": "Apstiprini jauno paroli", "Continue": "Turpināt", "Could not connect to the integration server": "Neizdevās savienoties ar integrācijas serveri", - "%(count)s new messages.one": "jaunu ziņu skaits: %(count)s", - "%(count)s new messages.other": "%(count)s jaunas ziņas", + "%(count)s new messages|one": "jaunu ziņu skaits: %(count)s", + "%(count)s new messages|other": "%(count)s jaunas ziņas", "Create a new chat or reuse an existing one": "Izveidot jaunu čatu vai izmantot eksistējošu", "Create an account": "Reģistrēt kontu", "Create Room": "Izveidot istabu", @@ -494,9 +494,9 @@ "%(senderName)s turned on end-to-end encryption (algorithm %(algorithm)s).": "%(senderName)s ieslēdza ierīce-ierīce šifrēšanu (algorithm %(algorithm)s).", "%(senderName)s unbanned %(targetName)s.": "%(senderName)s atcēla pieejas ierobežojumu (atbanoja) %(targetName)s.", "Unknown room %(roomId)s": "Nezināma istaba %(roomId)s", - "Uploading %(filename)s and %(count)s others.zero": "Tiek augšuplādēts %(filename)s", - "Uploading %(filename)s and %(count)s others.one": "Tiek augšuplādēts %(filename)s un %(count)s citi", - "Uploading %(filename)s and %(count)s others.other": "Tiek augšuplādēts %(filename)s un %(count)s citi", + "Uploading %(filename)s and %(count)s others|zero": "Tiek augšuplādēts %(filename)s", + "Uploading %(filename)s and %(count)s others|one": "Tiek augšuplādēts %(filename)s un %(count)s citi", + "Uploading %(filename)s and %(count)s others|other": "Tiek augšuplādēts %(filename)s un %(count)s citi", "%(user)s is a": "%(user)s ir", "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)", "Username invalid: %(errMessage)s": "Neatbilstošs lietotājvārds: %(errMessage)s", @@ -512,8 +512,8 @@ "%(weekDayName)s %(time)s": "%(weekDayName)s %(time)s", "Password too short (min %(MIN_PASSWORD_LENGTH)s).": "Parole ir par īsu (jābūt vismaz %(MIN_PASSWORD_LENGTH)s zīmēm).", "An error occurred: %(error_string)s": "Notikusi kļūda: %(error_string)s", - "(~%(count)s results).one": "(~%(count)s rezultāts)", - "(~%(count)s results).other": "(~%(count)s rezultāti)", + "(~%(count)s results)|one": "(~%(count)s rezultāts)", + "(~%(count)s results)|other": "(~%(count)s rezultāti)", "%(severalUsers)sjoined %(repeats)s times": "%(severalUsers)s pievienojās %(repeats)s reizes", "%(oneUser)sjoined %(repeats)s times": "%(oneUser)s pievienojās %(repeats)s reizes", "%(severalUsers)sjoined": "%(severalUsers)s pievienojās", @@ -916,8 +916,8 @@ "Encryption key request": "Šifrēšanas atslēgas pieprasījums", "Add a widget": "Pievienot Widžetu", "Allow": "Atļaut", - "and %(count)s others....other": "un vēl %(count)s citi...", - "and %(count)s others....one": "un vēl viens cits...", + "and %(count)s others...|other": "un vēl %(count)s citi...", + "and %(count)s others...|one": "un vēl viens cits...", "Cannot add any more widgets": "Nav iespējams pievienot vairāk vidžetu", "Changes colour scheme of current room": "Nomaina pašreizējās istabas krāsu paleti", "Delete widget": "Dzēst widžetu", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index d72813177b..ebb1c42056 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -141,8 +141,8 @@ "%(items)s and %(remaining)s others": "%(items)s en %(remaining)s andere", "%(items)s and one other": "%(items)s en één andere", "%(items)s and %(lastItem)s": "%(items)s en %(lastItem)s", - "and %(count)s others....other": "en %(count)s andere...", - "and %(count)s others....one": "en één andere...", + "and %(count)s others...|other": "en %(count)s andere...", + "and %(count)s others...|one": "en één andere...", "%(names)s and %(lastPerson)s are typing": "%(names)s en %(lastPerson)s zijn aan het typen", "%(names)s and one other are typing": "%(names)s en één andere zijn aan het typen", "%(names)s and %(count)s others are typing": "%(names)s en %(count)s andere zijn aan het typen", @@ -222,7 +222,7 @@ "Are you sure you want to upload the following files?": "Weet u zeker dat u de volgende bestanden wil uploaden?", "Click here to join the discussion!": "Klik hier om mee te doen aan de discussie!", "Close": "Sluiten", - "%(count)s new messages.one": "%(count)s nieuw bericht", + "%(count)s new messages|one": "%(count)s nieuw bericht", "Create new room": "Een nieuwe kamer maken", "Custom Server Options": "Aangepaste serverinstellingen", "Dismiss": "Afwijzen", @@ -329,7 +329,7 @@ "Set a Display Name": "Weergavenaam instellen", "Upload an avatar:": "Een avatar uploaden:", "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.": "Geen verbinding met de thuisserver - controleer je verbinding. Controleer het SSL-certificaat van de thuisserver en browser-extensies die verzoeken kunnen blokkeren.", - "%(count)s new messages.other": "%(count)s nieuwe berichten", + "%(count)s new messages|other": "%(count)s nieuwe berichten", "Create an account": "Open een account", "Cryptography": "Cryptografie", "Current password": "Huidig wachtwoord", @@ -644,9 +644,9 @@ "Unrecognised command:": "Onbekende commando:", "Unrecognised room alias:": "Onbekende ruimte alias:", "Unverified": "Niet geverifieerd", - "Uploading %(filename)s and %(count)s others.zero": "Aan het uploaden %(filename)s", - "Uploading %(filename)s and %(count)s others.one": "%(filename)s en %(count)s andere aan het uploaden", - "Uploading %(filename)s and %(count)s others.other": "%(filename)s en %(count)s anderen aan het uploaden", + "Uploading %(filename)s and %(count)s others|zero": "Aan het uploaden %(filename)s", + "Uploading %(filename)s and %(count)s others|one": "%(filename)s en %(count)s andere aan het uploaden", + "Uploading %(filename)s and %(count)s others|other": "%(filename)s en %(count)s anderen aan het uploaden", "uploaded a file": "Bestand geüpload", "Upload avatar": "Avatar uploaden", "Upload Failed": "Uploaden Mislukt", @@ -737,8 +737,8 @@ "Sent messages will be stored until your connection has returned.": "Verstuurde berichten zullen opgeslagen worden tot je connectie weer terug is.", "Auto-complete": "Automatisch aanvullen", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "Verstuur alle of annuleer alle nu. Je kan ook individuele berichten selecteren om te versturen of te annuleren.", - "(~%(count)s results).one": "(~%(count)s resultaat)", - "(~%(count)s results).other": "(~%(count)s resultaten)", + "(~%(count)s results)|one": "(~%(count)s resultaat)", + "(~%(count)s results)|other": "(~%(count)s resultaten)", "or": "of", "Active call": "Actief gesprek", "bold": "vetgedrukt", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 9fd0a6c1a2..cb4ba65ec4 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -556,8 +556,8 @@ "%(items)s and %(remaining)s others": "%(items)s e %(remaining)s outros", "%(items)s and one other": "%(items)s e um outro", "%(items)s and %(lastItem)s": "%(items)s e %(lastItem)s", - "and %(count)s others....other": "e %(count)s outros...", - "and %(count)s others....one": "e um outro...", + "and %(count)s others...|other": "e %(count)s outros...", + "and %(count)s others...|one": "e um outro...", "Are you sure?": "Você tem certeza?", "Attachment": "Anexo", "Autoplay GIFs and videos": "Reproduzir automaticamente GIFs e videos", @@ -877,7 +877,7 @@ "Disable markdown formatting": "Desabilitar formatação MarkDown", "No display name": "Sem nome público de usuária(o)", "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.", - "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|one": "Enviando o arquivo %(filename)s e %(count)s outros arquivos", "Hide removed messages": "Ocultar mensagens removidas", "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.", "Welcome page": "Página de boas-vindas", @@ -887,7 +887,7 @@ "And %(count)s more...": "E mais %(count)s...", "Start chatting": "Iniciar a conversa", "Public Chat": "Conversa pública", - "Uploading %(filename)s and %(count)s others.zero": "Enviando o arquivo %(filename)s", + "Uploading %(filename)s and %(count)s others|zero": "Enviando o arquivo %(filename)s", "Room contains unknown devices": "Esta sala contém dispositivos desconhecidos", "Admin tools": "Ferramentas de administração", "You have been kicked from %(roomName)s by %(userName)s.": "Você foi removido(a) da sala %(roomName)s por %(userName)s.", @@ -918,14 +918,14 @@ "Enable Notifications": "Habilitar notificações", "Username not available": "Nome de usuária(o) indisponível", "Encrypted by a verified device": "Criptografado por um dispositivo verificado", - "(~%(count)s results).other": "(~%(count)s resultados)", + "(~%(count)s results)|other": "(~%(count)s resultados)", "unknown caller": "a pessoa que está chamando é desconhecida", "Start authentication": "Iniciar autenticação", - "(~%(count)s results).one": "(~%(count)s resultado)", + "(~%(count)s results)|one": "(~%(count)s resultado)", "New Password": "Nova senha", "Username invalid: %(errMessage)s": "Nome de usuária(o) inválido: %(errMessage)s", "Disable Notifications": "Desabilitar notificações", - "%(count)s new messages.one": "%(count)s nova mensagem", + "%(count)s new messages|one": "%(count)s nova mensagem", "Device Name": "Nome do dispositivo", "Incoming voice call from %(name)s": "Chamada de voz de %(name)s recebida", "If you already have a Matrix account you can log in instead.": "Se você já tem uma conta Matrix, pode também fazer login.", @@ -934,11 +934,11 @@ "Set": "Definir", "Unencrypted message": "Mensagem não criptografada", "Join as voice or video.": "Participar por voz ou por vídeo.", - "Uploading %(filename)s and %(count)s others.other": "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 available": "Nome de usuária(o) disponível", "Close": "Fechar", "Level:": "Nível:", - "%(count)s new messages.other": "%(count)s novas mensagens", + "%(count)s new messages|other": "%(count)s novas mensagens", "Unverified": "Não verificado", "Click here to join the discussion!": "Clique aqui para participar da conversa!", "Decline": "Recusar", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 63efda25d9..cd6230cd68 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -557,10 +557,8 @@ "%(items)s and %(remaining)s others": "%(items)s e %(remaining)s outros", "%(items)s and one other": "%(items)s e um outro", "%(items)s and %(lastItem)s": "%(items)s e %(lastItem)s", - "and %(count)s others...": { - "other": "e %(count)s outros...", - "one": "e um outro..." - }, + "and %(count)s others...|one": "e um outro...", + "and %(count)s others...|other": "e %(count)s outros...", "Are you sure?": "Você tem certeza?", "Attachment": "Anexo", "Autoplay GIFs and videos": "Reproduzir automaticamente GIFs e videos", @@ -874,16 +872,16 @@ "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", "Add": "Adicionar", - "%(count)s new messages.one": "%(count)s nova mensagem", - "%(count)s new messages.other": "%(count)s novas mensagens", + "%(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", + "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", @@ -958,8 +956,8 @@ "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)", + "(~%(count)s results)|one": "(~%(count)s resultado)", + "(~%(count)s results)|other": "(~%(count)s resultados)", "Device Name": "Nome do dispositivo", "(could not connect media)": "(não foi possível conectar-se à mídia)", "(no answer)": "(sem resposta)", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index e15fce90c4..9a49fca9cb 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -448,8 +448,8 @@ "sx": "Суту", "zh-hk": "Китайский (Гонконг)", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Текстовое сообщение было отправлено на +%(msisdn)s. Введите проверочный код, который оно содержит", - "and %(count)s others....other": "и %(count)s других...", - "and %(count)s others....one": "и ещё один...", + "and %(count)s others...|other": "и %(count)s других...", + "and %(count)s others...|one": "и ещё один...", "Are you sure?": "Вы уверены?", "Autoplay GIFs and videos": "Автовоспроизведение GIF и видео", "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Невозможно соединиться с домашним сервером - проверьте своё соединение и убедитесь, что SSL-сертификат вашего домашнего сервера включён в доверяемые.", @@ -863,14 +863,14 @@ "Start chat": "Начать чат", "Welcome page": "Страница приветствия", "Add": "Добавить", - "%(count)s new messages.one": "%(count)s новое сообщение", - "%(count)s new messages.other": "%(count)s новых сообщений", + "%(count)s new messages|one": "%(count)s новое сообщение", + "%(count)s new messages|other": "%(count)s новых сообщений", "Error: Problem communicating with the given homeserver.": "Ошибка: проблема связи с данным сервером.", "Failed to fetch avatar URL": "Не удалось извлечь URL-адрес аватара", "The phone number entered looks invalid": "Введенный номер телефона недействителен", - "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 других", + "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": "Вы должны зарегистрироваться, чтобы использовать эту функцию", @@ -918,7 +918,7 @@ "Set": "Установить", "Start authentication": "Начать проверку подлинности", "This room": "В этой комнате", - "(~%(count)s results).other": "(~%(count)s результаты)", + "(~%(count)s results)|other": "(~%(count)s результаты)", "Device Name": "Имя устройства", "Custom": "Пользовательские", "Decline": "Отклонить", @@ -941,7 +941,7 @@ "%(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 результат)", + "(~%(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-сертификат домашнего сервера является доверенным и что расширение браузера не блокирует запросы.", "You have been banned from %(roomName)s by %(userName)s.": "%(userName)s заблокировал вас в %(roomName)s.", "You have been kicked from %(roomName)s by %(userName)s.": "%(userName)s выгнал вас из %(roomName)s.", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 662215b541..c38aeec36e 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -150,8 +150,8 @@ "%(items)s and %(remaining)s others": "%(items)s och %(remaining)s andra", "%(items)s and one other": "%(items)s och en annan", "%(items)s and %(lastItem)s": "%(items)s och %(lastItem)s", - "and %(count)s others....other": "och %(count)s andra...", - "and %(count)s others....one": "och en annan...", + "and %(count)s others...|other": "och %(count)s andra...", + "and %(count)s others...|one": "och en annan...", "%(names)s and %(lastPerson)s are typing": "%(names)s och %(lastPerson)s skriver", "%(names)s and one other are typing": "%(names)s och en annan skriver", "%(names)s and %(count)s others are typing": "%(names)s och %(count)s andra skriver", @@ -303,8 +303,8 @@ "changing room on a RoomView is not supported": "det går inte att byta rum i en RoomView", "Click here to join the discussion!": "Klicka här för att gå med i diskussionen!", "Close": "Stäng", - "%(count)s new messages.one": "%(count)s nytt meddelande", - "%(count)s new messages.other": "%(count)s nya meddelanden", + "%(count)s new messages|one": "%(count)s nytt meddelande", + "%(count)s new messages|other": "%(count)s nya meddelanden", "Create a new chat or reuse an existing one": "Skapa en ny chatt eller använd en existerande", "Custom": "Egen", "Decline": "Avvisa", diff --git a/src/i18n/strings/te.json b/src/i18n/strings/te.json index f3c65d808f..a1487a594e 100644 --- a/src/i18n/strings/te.json +++ b/src/i18n/strings/te.json @@ -214,8 +214,8 @@ "Confirm your new password": "మీ క్రొత్త పాస్వర్డ్ను నిర్ధారించండి", "Continue": "కొనసాగించు", "Could not connect to the integration server": "ఇంటిగ్రేషన్ సర్వర్కు కనెక్ట్ చేయడం సాధ్యం కాలేదు", - "%(count)s new messages.one": "%(count)s కొత్త సందేశం", - "%(count)s new messages.other": "%(count)s కొత్త సందేశాలు", + "%(count)s new messages|one": "%(count)s కొత్త సందేశం", + "%(count)s new messages|other": "%(count)s కొత్త సందేశాలు", "Create a new chat or reuse an existing one": "క్రొత్త చాట్ ను సృష్టించుకోండి లేదా ఇప్పటికే ఉన్న ఒకదాన్ని తిరిగి ఉపయోగించండి", "Create an account": "ఒక ఎకౌంటు ను సృష్టించండి", "Create Room": "రూమ్ ని సృష్టించండి", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index f5471db7cf..3cf4355821 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -98,10 +98,8 @@ "%(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 %(count)s others...": { - "other": "และอีก %(count)s ผู้ใช้...", - "one": "และอีกหนึ่งผู้ใช้..." - }, + "and %(count)s others...|one": "และอีกหนึ่งผู้ใช้...", + "and %(count)s others...|other": "และอีก %(count)s ผู้ใช้...", "%(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 คนกำลังพิมพ์", @@ -330,8 +328,8 @@ "Start chat": "เริ่มแชท", "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 ข้อความใหม่", + "%(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": "ข้อมูลการเข้ารหัสจากปลายทางถึงปลายทาง", @@ -368,9 +366,9 @@ "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 ไฟล์", + "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": "อัปโหลดไฟล์", @@ -598,8 +596,8 @@ "This room": "ห้องนี้", "Unnamed Room": "ห้องที่ยังไม่ได้ตั้งชื่อ", "%(user)s is a": "%(user)s เป็น", - "(~%(count)s results).one": "(~%(count)s ผลลัพท์)", - "(~%(count)s results).other": "(~%(count)s ผลลัพท์)", + "(~%(count)s results)|one": "(~%(count)s ผลลัพท์)", + "(~%(count)s results)|other": "(~%(count)s ผลลัพท์)", "Admin tools": "เครื่องมือผู้ดูแล", "And %(count)s more...": "เพิ่มอีก %(count)s ชิ้น...", "Missing Media Permissions, click here to request.": "ไม่มีสิทธิ์เข้าถึงสื่อ, คลิกที่นี่เพื่อขอสิทธิ์", diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index 035fd69e8a..fccef004dc 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -156,10 +156,8 @@ "%(items)s and %(remaining)s others": "%(items)s ve %(remaining)s diğerleri", "%(items)s and one other": "%(items)s ve bir başkası", "%(items)s and %(lastItem)s": "%(items)s ve %(lastItem)s", - "and %(count)s others...": { - "other": "ve %(count)s diğerleri...", - "one": "ve bir diğeri..." - }, + "and %(count)s others...|one": "ve bir diğeri...", + "and %(count)s others...|other": "ve %(count)s diğerleri...", "%(names)s and %(lastPerson)s are typing": "%(names)s ve %(lastPerson)s yazıyorlar", "%(names)s and one other are typing": "%(names)s ve birisi yazıyor", "%(names)s and %(count)s others are typing": "%(names)s ve %(count)s diğeri yazıyor", @@ -220,8 +218,8 @@ "Confirm your new password": "Yeni Şifrenizi Onaylayın", "Continue": "Devam Et", "Could not connect to the integration server": "Bütünleştirme (Integration) Sunucusuna bağlanamadı", - "%(count)s new messages.one": "%(count)s yeni mesaj", - "%(count)s new messages.other": "%(count)s yeni mesajlar", + "%(count)s new messages|one": "%(count)s yeni mesaj", + "%(count)s new messages|other": "%(count)s yeni mesajlar", "Create a new chat or reuse an existing one": "Yeni sohbet oluştur veya mevcut sohbetinizi tekrar kullanın", "Create an account": "Hesap Oluştur", "Create Room": "Oda Oluştur", @@ -600,9 +598,9 @@ "Unrecognised command:": "Tanınmayan komut :", "Unrecognised room alias:": "Tanınmayan oda isimleri :", "Unverified": "Doğrulanmamış", - "Uploading %(filename)s and %(count)s others.zero": "%(filename)s yükleniyor", - "Uploading %(filename)s and %(count)s others.one": "%(filename)s ve %(count)s kadarı yükleniyor", - "Uploading %(filename)s and %(count)s others.other": "%(filename)s ve %(count)s kadarları yükleniyor", + "Uploading %(filename)s and %(count)s others|zero": "%(filename)s yükleniyor", + "Uploading %(filename)s and %(count)s others|one": "%(filename)s ve %(count)s kadarı yükleniyor", + "Uploading %(filename)s and %(count)s others|other": "%(filename)s ve %(count)s kadarları yükleniyor", "uploaded a file": "bir dosya yüklendi", "Upload avatar": "Avatar yükle", "Upload Failed": "Yükleme Başarısız", @@ -719,8 +717,8 @@ "Sent messages will be stored until your connection has returned.": "Gönderilen iletiler bağlantınız geri gelene kadar saklanacak.", "Auto-complete": "Otomatik tamamlama", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": " Hepsini yeniden gönderin veya Hepsini iptal edin şimdi . Ayrıca yeniden göndermek veya iptal etmek için özel iletiler seçebilirsin.", - "(~%(count)s results).one": "(~%(count)s sonuç)", - "(~%(count)s results).other": "(~%(count)s sonuçlar)", + "(~%(count)s results)|one": "(~%(count)s sonuç)", + "(~%(count)s results)|other": "(~%(count)s sonuçlar)", "Cancel": "İptal Et", "or": "veya", "Active call": "Aktif çağrı", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index ae538d76bf..15ddefc956 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -192,10 +192,8 @@ "%(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 %(count)s others...": { - "other": "та %(count)s інші...", - "one": "і інше..." - }, + "and %(count)s others...|one": "і інше...", + "and %(count)s others...|other": "та %(count)s інші...", "%(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 інших пишуть", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 77c2232619..f8ee16f67e 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -239,8 +239,8 @@ "%(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 %(count)s others....other": "和其它 %(count)s 个...", - "and %(count)s others....one": "和其它一个...", + "and %(count)s others...|other": "和其它 %(count)s 个...", + "and %(count)s others...|one": "和其它一个...", "%(names)s and one other are typing": "%(names)s 和另一个人正在打字", "anyone": "任何人", "Anyone": "任何人", @@ -282,8 +282,8 @@ "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 新消息", + "%(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": "自定义级别", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 2f3d36b481..028336f3be 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -463,8 +463,8 @@ "Conference calls are not supported in encrypted rooms": "不支援在加密房間的會議通話", "Conference calls are not supported in this client": "這個客戶端不支援會議通話", "Could not connect to the integration server": "無法連線到整合的伺服器", - "%(count)s new messages.one": "%(count)s 個訊息", - "%(count)s new messages.other": "%(count)s 個訊息", + "%(count)s new messages|one": "%(count)s 個訊息", + "%(count)s new messages|other": "%(count)s 個訊息", "Create a new chat or reuse an existing one": "建立新聊天或重新使用既有的", "Curve25519 identity key": "Curve25519 辨識金鑰", "Custom": "自訂", @@ -661,9 +661,9 @@ "Unrecognised command:": "無法識別的命令:", "Unrecognised room alias:": "無法室別的房間別名:", "Unverified": "未驗證", - "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 個", + "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 avatar": "上傳大頭貼", "Upload Failed": "上傳失敗", @@ -772,8 +772,8 @@ "Sent messages will be stored until your connection has returned.": "傳送的訊息會在您的連線恢復前先儲存起來。", "Auto-complete": "自動完成", "Resend all or cancel all now. You can also select individual messages to resend or cancel.": "現在重新傳送全部或是取消全部。您也可以單獨選擇訊息來重新傳送或取消。", - "(~%(count)s results).one": "(~%(count)s 結果)", - "(~%(count)s results).other": "(~%(count)s 結果)", + "(~%(count)s results)|one": "(~%(count)s 結果)", + "(~%(count)s results)|other": "(~%(count)s 結果)", "or": "或", "Active call": "活躍的通話", "bold": "粗體", @@ -923,8 +923,8 @@ "Encryption key request": "加密金鑰請求", "Add a widget": "新增小工具", "Allow": "允許", - "and %(count)s others....other": "與其他 %(count)s 個……", - "and %(count)s others....one": "與其他 1 個……", + "and %(count)s others...|other": "與其他 %(count)s 個……", + "and %(count)s others...|one": "與其他 1 個……", "Cannot add any more widgets": "無法新增更多的小工具", "Changes colour scheme of current room": "變更目前聊天室的配色方案", "Delete widget": "刪除小工具", From c67a6e9d2ec71a6bbb743e928d8a8994ee93137c Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 5 Sep 2017 13:13:02 +0100 Subject: [PATCH 09/43] Prepare changelog for v0.10.3-rc.2 --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4e9ae9a78..af82ef2e1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +Changes in [0.10.3-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.3-rc.2) (2017-09-05) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.3-rc.1...v0.10.3-rc.2) + + * Fix plurals in translations + [\#1358](https://github.com/matrix-org/matrix-react-sdk/pull/1358) + * Fix typo + [\#1357](https://github.com/matrix-org/matrix-react-sdk/pull/1357) + * Update from Weblate. + [\#1356](https://github.com/matrix-org/matrix-react-sdk/pull/1356) + Changes in [0.10.3-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.3-rc.1) (2017-09-01) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.2...v0.10.3-rc.1) From c75bc42585c8aa5e8e193ca7f6096d83734f921a Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 5 Sep 2017 13:13:02 +0100 Subject: [PATCH 10/43] v0.10.3-rc.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0610d42c0d..e1fbfb58d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.10.3-rc.1", + "version": "0.10.3-rc.2", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 5684b6a23c4e14ec5feda73add2b135f9fc7948a Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 5 Sep 2017 17:35:03 +0200 Subject: [PATCH 11/43] Remove unused translation code translations --- src/i18n/strings/en_EN.json | 120 ------------------------------------ 1 file changed, 120 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 35ca698c03..1d706a135d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,125 +1,5 @@ { "Add a widget": "Add a widget", - "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": "Belarusian", - "bg": "Bulgarian", - "ca": "Catalan", - "cs": "Czech", - "da": "Danish", - "de-at": "German (Austria)", - "de-ch": "German (Switzerland)", - "de": "German", - "de-li": "German (Liechtenstein)", - "de-lu": "German (Luxembourg)", - "el": "Greek", - "en-au": "English (Australia)", - "en-bz": "English (Belize)", - "en-ca": "English (Canada)", - "en": "English", - "en-gb": "English (United Kingdom)", - "en-ie": "English (Ireland)", - "en-jm": "English (Jamaica)", - "en-nz": "English (New Zealand)", - "en-tt": "English (Trinidad)", - "en-us": "English (United States)", - "en-za": "English (South Africa)", - "es-ar": "Spanish (Argentina)", - "es-bo": "Spanish (Bolivia)", - "es-cl": "Spanish (Chile)", - "es-co": "Spanish (Colombia)", - "es-cr": "Spanish (Costa Rica)", - "es-do": "Spanish (Dominican Republic)", - "es-ec": "Spanish (Ecuador)", - "es-gt": "Spanish (Guatemala)", - "es-hn": "Spanish (Honduras)", - "es-mx": "Spanish (Mexico)", - "es-ni": "Spanish (Nicaragua)", - "es-pa": "Spanish (Panama)", - "es-pe": "Spanish (Peru)", - "es-pr": "Spanish (Puerto Rico)", - "es-py": "Spanish (Paraguay)", - "es": "Spanish (Spain)", - "es-sv": "Spanish (El Salvador)", - "es-uy": "Spanish (Uruguay)", - "es-ve": "Spanish (Venezuela)", - "et": "Estonian", - "eu": "Basque (Basque)", - "fa": "Farsi", - "fi": "Finnish", - "fo": "Faeroese", - "fr-be": "French (Belgium)", - "fr-ca": "French (Canada)", - "fr-ch": "French (Switzerland)", - "fr": "French", - "fr-lu": "French (Luxembourg)", - "ga": "Irish", - "gd": "Gaelic (Scotland)", - "he": "Hebrew", - "hi": "Hindi", - "hr": "Croatian", - "hu": "Hungarian", - "id": "Indonesian", - "is": "Icelandic", - "it-ch": "Italian (Switzerland)", - "it": "Italian", - "ja": "Japanese", - "ji": "Yiddish", - "ko": "Korean", - "lt": "Lithuanian", - "lv": "Latvian", - "mk": "Macedonian (FYROM)", - "ms": "Malaysian", - "mt": "Maltese", - "nl-be": "Dutch (Belgium)", - "nl": "Dutch", - "no": "Norwegian", - "pl": "Polish", - "pt-br": "Brazilian Portuguese", - "pt": "Portuguese", - "rm": "Rhaeto-Romanic", - "ro-mo": "Romanian (Republic of Moldova)", - "ro": "Romanian", - "ru-mo": "Russian (Republic of Moldova)", - "ru": "Russian", - "sb": "Sorbian", - "sk": "Slovak", - "sl": "Slovenian", - "sq": "Albanian", - "sr": "Serbian", - "sv-fi": "Swedish (Finland)", - "sv": "Swedish", - "sx": "Sutu", - "sz": "Sami (Lappish)", - "th": "Thai", - "tn": "Tswana", - "tr": "Turkish", - "ts": "Tsonga", - "uk": "Ukrainian", - "ur": "Urdu", - "ve": "Venda", - "vi": "Vietnamese", - "xh": "Xhosa", - "zh-cn": "Chinese (PRC)", - "zh-hk": "Chinese (Hong Kong SAR)", - "zh-sg": "Chinese (Singapore)", - "zh-tw": "Chinese (Taiwan)", - "zu": "Zulu", "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", From 4a362c141ad124e3e04ca1f8af93bfd6f9ccec23 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Tue, 5 Sep 2017 17:54:49 +0200 Subject: [PATCH 12/43] Cleanup unused language code translations --- src/i18n/strings/ar.json | 1 - src/i18n/strings/cs.json | 119 --------------------------------- src/i18n/strings/da.json | 74 --------------------- src/i18n/strings/de_DE.json | 115 -------------------------------- src/i18n/strings/el.json | 120 --------------------------------- src/i18n/strings/en_US.json | 120 --------------------------------- src/i18n/strings/eo.json | 16 +---- src/i18n/strings/es.json | 120 --------------------------------- src/i18n/strings/eu.json | 121 ---------------------------------- src/i18n/strings/fr.json | 120 --------------------------------- src/i18n/strings/he.json | 22 +------ src/i18n/strings/hu.json | 117 -------------------------------- src/i18n/strings/it.json | 115 -------------------------------- src/i18n/strings/ja.json | 120 --------------------------------- src/i18n/strings/ko.json | 118 --------------------------------- src/i18n/strings/lv.json | 120 --------------------------------- src/i18n/strings/ml.json | 5 +- src/i18n/strings/nl.json | 121 ---------------------------------- src/i18n/strings/pl.json | 117 -------------------------------- src/i18n/strings/pt.json | 114 -------------------------------- src/i18n/strings/pt_BR.json | 118 --------------------------------- src/i18n/strings/ru.json | 120 --------------------------------- src/i18n/strings/sv.json | 120 --------------------------------- src/i18n/strings/te.json | 117 -------------------------------- src/i18n/strings/th.json | 117 -------------------------------- src/i18n/strings/tr.json | 120 --------------------------------- src/i18n/strings/uk.json | 120 --------------------------------- src/i18n/strings/zh_Hans.json | 120 --------------------------------- src/i18n/strings/zh_Hant.json | 120 --------------------------------- 29 files changed, 3 insertions(+), 2964 deletions(-) diff --git a/src/i18n/strings/ar.json b/src/i18n/strings/ar.json index c1aba2edeb..8718e842a7 100644 --- a/src/i18n/strings/ar.json +++ b/src/i18n/strings/ar.json @@ -1,5 +1,4 @@ { - "ar-iq": "العربية", "Continue": "استمر", "Username available": "اسم المستخدم متاح", "Username not available": "الإسم المستخدم غير موجود", diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index c592e14076..797b045386 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -75,125 +75,6 @@ "to demote": "upozadíte", "Drop here %(toAction)s": "Přetažením sem %(toAction)s", "Add a widget": "Přidat widget", - "af": "Afrikánština", - "ar-ae": "Arabština (SAE)", - "ar-bh": "Arabština (Bahrajn)", - "ar-dz": "Arabština (Alžírsko)", - "ar-eg": "Arabština (Egypt)", - "ar-iq": "Arabština (Irák)", - "ar-jo": "Arabština (Jordánsko)", - "ar-kw": "Arabština (Kuvajt)", - "ar-lb": "Arabština (Libanon)", - "ar-ly": "Arabština (Libye)", - "ar-ma": "Arabština (Maroko)", - "ar-om": "Arabština (Omán)", - "ar-qa": "Arabština (Katar)", - "ar-sa": "Arabština (Saúdská Arábie)", - "ar-sy": "Arabština (Sýrie)", - "ar-tn": "Arabština (Tunisko)", - "ar-ye": "Arabština (Jemen)", - "be": "Běloruština", - "bg": "Bulharština", - "ca": "Katalánština", - "cs": "Čeština", - "da": "Dánština", - "de-at": "Němčina (Rakousko)", - "de-ch": "Němčina (Švýcarsko)", - "de": "Němčina", - "de-li": "Němčina (Lichtenštejnsko)", - "de-lu": "Němčina (Lucembursko)", - "el": "Řečtina", - "en-au": "Angličtina (Austrálie)", - "en-bz": "Angličtina (Belize)", - "en-ca": "Angličtina (Kanada)", - "en": "Angličtina", - "en-gb": "Angličtina (Spojené království)", - "en-ie": "Angličtina (Irsko)", - "en-jm": "Angličtina (Jamajka)", - "en-nz": "Angličtina (Nový Zéland)", - "en-tt": "Angličtina (Trinidad)", - "en-us": "Angličtina (Spojené státy)", - "en-za": "Angličtina (Jihoafrická republika)", - "es-ar": "Španělština (Argentina)", - "es-bo": "Španělština (Bolívie)", - "es-cl": "Španělština (Chile)", - "es-co": "Španělština (Kolumbie)", - "es-cr": "Španělština (Kostarika)", - "es-do": "Španělština (Dominikánská republika)", - "es-ec": "Španělština (Ekvádor)", - "es-gt": "Španělština (Guatemala)", - "es-hn": "Španělština (Honduras)", - "es-mx": "Španělština (Mexiko)", - "es-ni": "Španělština (Nikaragua)", - "es-pa": "Španělština (Panama)", - "es-pe": "Španělština (Peru)", - "es-pr": "Španělština (Portoriko)", - "es-py": "Španělština (Paraguay)", - "es": "Španělština (Španělsko)", - "es-sv": "Španělština (Salvador)", - "es-uy": "Španělština (Uruguay)", - "es-ve": "Španělština (Venezuela)", - "et": "Estonština", - "eu": "Baskičtina (Baskicko)", - "fa": "Perština", - "fi": "Finština", - "fo": "Faerština", - "fr-be": "Francouzština (Belgie)", - "fr-ca": "Francouzština (Kanada)", - "fr-ch": "Francouzština (Švýcarsko)", - "fr": "Francouzština", - "fr-lu": "Francouzština (Lucembursko)", - "ga": "Irština", - "gd": "Gaelština (Skotsko)", - "he": "Hebrejština", - "hi": "Hindština", - "hr": "Chorvatština", - "hu": "Maďarština", - "id": "Indonéština", - "is": "Islandština", - "it-ch": "Italština (Švýcarsko)", - "it": "Italština", - "ja": "Japonština", - "ji": "Jidiš", - "ko": "Korejština", - "lt": "Litevština", - "lv": "Lotyština", - "mk": "Makedonština (Makedonie)", - "ms": "Malajština", - "mt": "Maltština", - "nl-be": "Nizozemština (Belgie)", - "nl": "Nizozemština", - "no": "Norština", - "pl": "Polština", - "pt-br": "Brazilská portugalština", - "pt": "Portugalština", - "rm": "Rétorománština", - "ro-mo": "Rumunština (Moldavsko)", - "ro": "Rumunština", - "ru-mo": "Ruština (Moldavsko)", - "ru": "Ruština", - "sb": "Lužická srbština", - "sk": "Slovenština", - "sl": "Slovinština", - "sq": "Albánština", - "sr": "Srbština", - "sv-fi": "Švédština (Finsko)", - "sv": "Švédština", - "sz": "Sámština (Laponsko)", - "th": "Thajština", - "tr": "Turečtina", - "uk": "Ukrajinština", - "ur": "Urdština", - "vi": "Vietnamština", - "zh-cn": "Čínština (ČLR)", - "zh-hk": "Čínština (Hongkong)", - "xh": "Xhoština", - "ve": "Luvendština", - "ts": "Tsonga", - "tn": "Setswanština", - "zh-sg": "Čínština (Singapur)", - "zh-tw": "Čínština (Tchaj-wan)", - "zu": "Zuluština", "a room": "místnost", "Accept": "Přijmout", "%(targetName)s accepted an invitation.": "%(targetName)s přijal/a pozvání.", diff --git a/src/i18n/strings/da.json b/src/i18n/strings/da.json index dec3219da9..11d7bffdd3 100644 --- a/src/i18n/strings/da.json +++ b/src/i18n/strings/da.json @@ -137,80 +137,6 @@ "%(names)s and one other are typing": "%(names)s og den anden skriver", "%(names)s and %(count)s others are typing": "%(names)s og %(count)s andre skriver", "%(senderName)s answered the call.": "%(senderName)s besvarede opkaldet.", - "af": "Afrikaans", - "ar-eg": "Arabisk (Egypten)", - "ar-ma": "Arabisk (Marokko)", - "ar-sa": "Arabisk (Saudiarabien", - "ar-sy": "Arabisk (Syrien)", - "be": "Hviderussisk", - "bg": "Bulgarisk", - "ca": "Catalansk", - "cs": "Tjekkisk", - "de-at": "Tysk (Østrig)", - "de-ch": "Tysk (Schweiz)", - "el": "Græsk", - "en-au": "Engelsk (Australien)", - "en-ca": "Engelsk (Canada)", - "en-ie": "Engelsk (Irland)", - "en-nz": "Engelsk (New Zealand)", - "en-us": "Engelsk (USA)", - "en-za": "Engelsk (Sydafrika)", - "es-ar": "Spansk (Argentina)", - "es-bo": "Spansk (Bolivia)", - "es-cl": "Spansk (Chile)", - "es-ec": "Spansk (Ecuador)", - "es-hn": "Spansk (Honduras)", - "es-mx": "Spansk (Mexico)", - "es-ni": "Spansk (Nicaragua)", - "es-py": "Spansk (Paraguay)", - "es": "Spansk (Spanien)", - "es-uy": "Spansk (Uruguay)", - "es-ve": "Spansk (Venezuela)", - "et": "Estisk", - "fa": "Farsi", - "fi": "Finsk", - "fr-be": "Fransk (Belgien)", - "fr-ca": "Fransk (Canada)", - "fr-ch": "Fransk (Schweiz)", - "fr": "Fransk", - "ga": "Irsk", - "he": "Hebraisk", - "hi": "Hindi", - "hr": "Kroatisk", - "hu": "Ungarsk", - "id": "Indonesisk", - "is": "Islandsk", - "it": "Italiensk", - "ja": "Japansk", - "ji": "Jiddisch", - "lt": "Litauisk", - "lv": "Lettisk", - "ms": "Malaysisk", - "mt": "Maltesisk", - "nl": "Hollandsk", - "no": "Norsk", - "pl": "Polsk", - "pt": "Portugisisk", - "ro": "Rumænsk", - "sb": "Sorbisk", - "sk": "Slovakisk", - "sl": "Slovensk", - "sq": "Albansk", - "sr": "Serbisk", - "sv": "Svensk", - "th": "Thai", - "tn": "Tswana", - "tr": "Tyrkisk", - "ts": "Tsonga", - "uk": "Ukrainsk", - "ur": "Urdu", - "ve": "Venda", - "vi": "Vietnamesisk", - "xh": "Xhosa", - "zh-cn": "Kinesisk (Folkerepublikken Kina)", - "zh-sg": "Kinesisk (Singapore)", - "zh-tw": "Kinesisk (Taiwan)", - "zu": "Zulu", "Add a widget": "Tilføj en widget", "ar-ae": "Arabisk (U.A.E.)", "ar-bh": "Arabisk (Bahrain)", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index e4a3d335a3..241cce3135 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -427,121 +427,6 @@ "click to reveal": "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.", - "af": "Afrikaans", - "ar-ae": "Arabisch (VAE)", - "ar-bh": "Arabisch (Bahrain)", - "ar-dz": "Arabisch (Algerien)", - "ar-eg": "Arabisch (Ägypten)", - "ar-iq": "Arabisch (Irak)", - "ar-jo": "Arabisch (Jordanien)", - "ar-kw": "Arabisch (Kuwait)", - "ar-lb": "Arabisch (Libanon)", - "ar-ly": "Arabisch (Lybien)", - "ar-ma": "Arabisch (Marokko)", - "ar-om": "Arabisch (Oman)", - "ar-qa": "Arabisch (Katar)", - "ar-sa": "Arabisch (Saudi Arabien)", - "ar-sy": "Arabisch (Syrien)", - "ar-tn": "Arabisch (Tunesien)", - "ar-ye": "Arabisch (Jemen)", - "be": "Weißrussisch", - "bg": "Bulgarisch", - "cs": "Tschechisch", - "de-at": "Deutsch (Österreich)", - "de-ch": "Deutsch (Schweiz)", - "de-li": "Deutsch (Liechtenstein)", - "de-lu": "Deutsch (Luxemburg)", - "el": "Neugriechisch", - "en-au": "Englisch (Australien)", - "en-bz": "Englisch (Belize)", - "en-ca": "Englisch (Kanada)", - "en-gb": "Englisch (Vereinigtes Königreich)", - "en-ie": "Englisch (Irland)", - "en-jm": "Englisch (Jamaika)", - "en-nz": "Englisch (Neuseeland)", - "en-tt": "Englisch (Trinidad)", - "en-us": "Englisch (Vereinigte Staaten)", - "en-za": "Englisch (Südafrika)", - "es-ar": "Spanisch (Argentinien)", - "es-bo": "Spanisch (Bolivien)", - "es-cl": "Spanisch (Chile)", - "es-co": "Spanisch (Kolumbien)", - "es-cr": "Spanisch (Costa Rica)", - "es-do": "Spanisch (Dominikanische Republik)", - "es-ec": "Spanisch (Ecuador)", - "es-gt": "Spanisch (Guatemala)", - "es-hn": "Spanisch (Honduras)", - "es-mx": "Spanisch (Mexiko)", - "es-ni": "Spanisch (Nicaragua)", - "es-pa": "Spanisch (Panama)", - "es-pe": "Spanisch (Peru)", - "es-pr": "Spanisch (Puerto Rico)", - "es-py": "Spanisch (Paraguay)", - "es": "Spanisch (Spanien)", - "es-sv": "Spanisch (El Salvador)", - "es-uy": "Spanisch (Uruguay)", - "es-ve": "Spanisch (Venezuela)", - "et": "Estländisch", - "eu": "Baskisch (Baskenland)", - "fa": "Persisch (Farsi)", - "fr-be": "Französisch (Belgien)", - "fr-ca": "Französisch (Kanada)", - "fr-ch": "Französisch (Schweiz)", - "fr": "Französisch", - "fr-lu": "Französisch (Luxemburg)", - "gd": "Gälisch (Schottland)", - "he": "Hebräisch", - "hr": "Kroatisch", - "hu": "Ungarisch", - "id": "Indonesisch", - "is": "Isländisch", - "it-ch": "Italienisch (Schweiz)", - "it": "Italienisch", - "ja": "Japanisch", - "ji": "Jiddisch", - "ko": "Koreanisch", - "lt": "Litauisch", - "lv": "Lettisch", - "mk": "Mazedonisch (FYROM)", - "ms": "Malaysisch", - "mt": "Maltesisch", - "nl-be": "Niederländisch (Belgien)", - "nl": "Niederländisch", - "no": "Norwegisch", - "pl": "Polnisch", - "pt": "Portugiesisch", - "rm": "Rätoromanisch", - "ro-mo": "Rumänisch (Republik Moldau/Moldawien)", - "ro": "Rumänisch", - "ru-mo": "Russisch (Republik Moldau/Moldawien)", - "sb": "Sorbisch", - "sk": "Slowakisch", - "sl": "Slowenisch", - "sq": "Albanisch", - "sr": "Serbisch", - "sv-fi": "Schwedisch (Finnland)", - "sv": "Schwedisch", - "sx": "Sutu", - "sz": "Samisch (Lappisch)", - "th": "Thailändisch", - "tn": "Setswana", - "tr": "Türkisch", - "ts": "Tsonga", - "uk": "Ukrainisch", - "ur": "Urdu", - "ve": "Tshivenda", - "vi": "Vietnamesisch", - "zh-cn": "Chinesisch (Volksrepublik China)", - "zh-hk": "Chinesisch (Hong Kong SAR)", - "zh-sg": "Chinesisch (Singapur)", - "zh-tw": "Chinesisch (Taiwan)", - "zu": "Zulu", - "ca": "Katalanisch", - "fi": "Finnisch", - "fo": "Färöisch", - "ga": "Irisch", - "hi": "Hindi", - "xh": "Xhosa", "Monday": "Montag", "Tuesday": "Dienstag", "Wednesday": "Mittwoch", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 1211aab6ad..9b127f3c4f 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -1,5 +1,4 @@ { - "af": "Αφρικάνικα", "Error": "Σφάλμα", "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου (%(errCode)s)", "Failed to join the room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο", @@ -12,22 +11,6 @@ "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.", @@ -64,109 +47,6 @@ "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": "Ξόσα", - "zh-cn": "Κινέζικα (ΛΔΚ)", - "zh-hk": "Κινέζικα (ΕΔΠ Χονγκ Κονγκ)", - "zh-sg": "Κινέζικα (Σιγκαπούρη)", - "zh-tw": "Κινέζικα (Ταϊβάν)", - "zu": "Ζουλού", - "id": "Ινδονησιακά", - "lv": "Λετονικά", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Ένα μήνυμα στάλθηκε στο +%(msisdn)s. Παρακαλώ γράψε τον κωδικό επαλήθευσης που περιέχει", "Access Token:": "Κωδικός πρόσβασης:", "Always show message timestamps": "Εμφάνιση πάντα της ένδειξης ώρας στα μηνύματα", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index bb6a6e8c9b..3e08c386f8 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -1,125 +1,5 @@ { "Add a widget": "Add a widget", - "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": "Belarusian", - "bg": "Bulgarian", - "ca": "Catalan", - "cs": "Czech", - "da": "Danish", - "de-at": "German (Austria)", - "de-ch": "German (Switzerland)", - "de": "German", - "de-li": "German (Liechtenstein)", - "de-lu": "German (Luxembourg)", - "el": "Greek", - "en-au": "English (Australia)", - "en-bz": "English (Belize)", - "en-ca": "English (Canada)", - "en": "English", - "en-gb": "English (United Kingdom)", - "en-ie": "English (Ireland)", - "en-jm": "English (Jamaica)", - "en-nz": "English (New Zealand)", - "en-tt": "English (Trinidad)", - "en-us": "English (United States)", - "en-za": "English (South Africa)", - "es-ar": "Spanish (Argentina)", - "es-bo": "Spanish (Bolivia)", - "es-cl": "Spanish (Chile)", - "es-co": "Spanish (Colombia)", - "es-cr": "Spanish (Costa Rica)", - "es-do": "Spanish (Dominican Republic)", - "es-ec": "Spanish (Ecuador)", - "es-gt": "Spanish (Guatemala)", - "es-hn": "Spanish (Honduras)", - "es-mx": "Spanish (Mexico)", - "es-ni": "Spanish (Nicaragua)", - "es-pa": "Spanish (Panama)", - "es-pe": "Spanish (Peru)", - "es-pr": "Spanish (Puerto Rico)", - "es-py": "Spanish (Paraguay)", - "es": "Spanish (Spain)", - "es-sv": "Spanish (El Salvador)", - "es-uy": "Spanish (Uruguay)", - "es-ve": "Spanish (Venezuela)", - "et": "Estonian", - "eu": "Basque (Basque)", - "fa": "Farsi", - "fi": "Finnish", - "fo": "Faeroese", - "fr-be": "French (Belgium)", - "fr-ca": "French (Canada)", - "fr-ch": "French (Switzerland)", - "fr": "French", - "fr-lu": "French (Luxembourg)", - "ga": "Irish", - "gd": "Gaelic (Scotland)", - "he": "Hebrew", - "hi": "Hindi", - "hr": "Croatian", - "hu": "Hungarian", - "id": "Indonesian", - "is": "Icelandic", - "it-ch": "Italian (Switzerland)", - "it": "Italian", - "ja": "Japanese", - "ji": "Yiddish", - "ko": "Korean", - "lt": "Lithuanian", - "lv": "Latvian", - "mk": "Macedonian (FYROM)", - "ms": "Malaysian", - "mt": "Maltese", - "nl-be": "Dutch (Belgium)", - "nl": "Dutch", - "no": "Norwegian", - "pl": "Polish", - "pt-br": "Brazilian Portuguese", - "pt": "Portuguese", - "rm": "Rhaeto-Romanic", - "ro-mo": "Romanian (Republic of Moldova)", - "ro": "Romanian", - "ru-mo": "Russian (Republic of Moldova)", - "ru": "Russian", - "sb": "Sorbian", - "sk": "Slovak", - "sl": "Slovenian", - "sq": "Albanian", - "sr": "Serbian", - "sv-fi": "Swedish (Finland)", - "sv": "Swedish", - "sx": "Sutu", - "sz": "Sami (Lappish)", - "th": "Thai", - "tn": "Tswana", - "tr": "Turkish", - "ts": "Tsonga", - "uk": "Ukrainian", - "ur": "Urdu", - "ve": "Venda", - "vi": "Vietnamese", - "xh": "Xhosa", - "zh-cn": "Chinese (PRC)", - "zh-hk": "Chinese (Hong Kong SAR)", - "zh-sg": "Chinese (Singapore)", - "zh-tw": "Chinese (Taiwan)", - "zu": "Zulu", "AM": "AM", "PM": "PM", "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", diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 91cd6c3450..0967ef424b 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -1,15 +1 @@ -{ - "ar-ae": "la araba (Unuiĝintaj Arabaj Emirlandoj)", - "ar-bh": "la araba (Bareijno)", - "ar-dz": "la araba (Alĝerio)", - "ar-eg": "la araba (Egiptio)", - "ar-iq": "la araba (Irako)", - "ar-jo": "la araba (Jordanio)", - "ar-kw": "la araba (Kuvayto)", - "ar-lb": "la araba (Libano)", - "ar-ly": "la araba (Libio)", - "ar-ma": "la araba (Maroko)", - "ar-om": "la araba (Omano)", - "ar-qa": "la araba (Kataro)", - "ar-sa": "la araba (Sauda Arabio)" -} +{} diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 499da6e819..ecadaa31d7 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -1,124 +1,4 @@ { - "af": "Afrikáans", - "ar-ae": "Árabe (Emiratos Árabes Unidos)", - "ar-bh": "Árabe (Baréin)", - "ar-dz": "Árabe (Argelia)", - "ar-eg": "Árabe (Egipto)", - "ar-iq": "Árabe (Irak)", - "ar-jo": "Árabe (Jordania)", - "ar-kw": "Árabe (Kuwait)", - "ar-lb": "Árabe (Líbano)", - "ar-ly": "Árabe (Libia)", - "ar-ma": "Árabe (Marruecos)", - "ar-om": "Árabe (Omán)", - "ar-qa": "Árabe (Catar)", - "ar-sa": "Árabe (Arabia Saudita)", - "ar-sy": "Árabe (Siria)", - "ar-tn": "Árabe (Túnez)", - "ar-ye": "Árabe (Yemen)", - "be": "Bielorrusia", - "bg": "Bulgaria", - "ca": "Catalán", - "cs": "Checo", - "da": "Danés", - "de-at": "Alemán (Austria)", - "de-ch": "Alemán (Suiza)", - "de": "Alemán", - "de-li": "Alemán (Liechtenstein)", - "de-lu": "Alemán (Luxemburgo)", - "el": "Griego", - "en-au": "Inglés (Australia)", - "en-bz": "Inglés (Belice)", - "en-ca": "Inglés (Canadá)", - "en": "Inglés", - "en-gb": "Inglés (Reino Unido)", - "en-ie": "Inglés (Irlanda)", - "en-jm": "Inglés (Jamaica)", - "en-nz": "Inglés (Nueva Zelanda)", - "en-tt": "Inglés (Trinidad y Tobago)", - "en-us": "Inglés (Estados Unidos)", - "en-za": "Inglés (Sudáfrica)", - "es-ar": "Español (Argentina)", - "es-bo": "Español (Bolivia)", - "es-cl": "Español (Chile)", - "es-co": "Español (Colombia)", - "es-cr": "Español (Costa Rica)", - "es-do": "Español (República Dominicana)", - "es-ec": "Español (Ecuador)", - "es-gt": "Español (Guatemala)", - "es-hn": "Español (Honduras)", - "es-mx": "Español (México)", - "es-ni": "Español (Nicaragua)", - "es-pa": "Español (Panamá)", - "es-pe": "Español (Perú)", - "es-pr": "Español (Puerto Rico)", - "es-py": "Español (Paraguay)", - "es": "Español (España)", - "es-sv": "Español (El Salvador)", - "es-uy": "Español (Uruguay)", - "es-ve": "Español (Venezuela)", - "et": "Estonio", - "eu": "Vasco", - "fa": "Persa", - "fi": "Finés", - "fo": "Feroés", - "fr-be": "Francés (Bélgica)", - "fr-ca": "Francés (Canadá)", - "fr-ch": "Francés (Suiza)", - "fr": "Francés", - "fr-lu": "Francés (Luxemburgo)", - "ga": "Irlandés", - "gd": "Gaélico (Escocia)", - "he": "Hebreo", - "hi": "Hindi", - "hr": "Croata", - "hu": "Húngaro", - "id": "Indonesio", - "is": "Islandés", - "it-ch": "Italiano (Suiza)", - "it": "Italiano", - "ja": "Japonés", - "ji": "Yidis", - "ko": "Coreano", - "lt": "Lituano", - "lv": "Letón", - "mk": "Macedonio", - "ms": "Malayo", - "mt": "Maltés", - "nl-be": "Holandés (Bélgica)", - "nl": "Holandés", - "no": "Noruego", - "pl": "Polaco", - "pt-br": "Portugués (Brasil)", - "pt": "Portugués", - "rm": "Retorrománico", - "ro-mo": "Rumano (República de Moldavia)", - "ro": "Rumano", - "ru-mo": "Ruso (República de Moldavia)", - "ru": "Ruso", - "sb": "Sorbio", - "sk": "Eslovaco", - "sl": "Esloveno", - "sq": "Albanés", - "sr": "Serbio", - "sv-fi": "Sueco (Finlandia)", - "sv": "Sueco", - "sx": "Sotho", - "sz": "Sami (Lapón)", - "th": "Tailandés", - "tn": "Setsuana", - "tr": "Turco", - "ts": "Songa", - "uk": "Ucraniano", - "ur": "Urdú", - "ve": "Venda", - "vi": "Vietnamita", - "xh": "Josa", - "zh-cn": "Chino Mandarín", - "zh-hk": "Chino (Hong Kong RAE)", - "zh-sg": "Chino (Singapur)", - "zh-tw": "Chino (Taiwanés)", - "zu": "Zulú", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Un mensaje de texto ha sido enviado a +%(msisdn)s. Por favor ingrese el código de verificación que lo contiene", "accept": "Aceptar", "%(targetName)s accepted an invitation.": "%(targetName)s ha aceptado una invitación.", diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index aa9857c3dd..3a17e46c98 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -1,125 +1,4 @@ { - "af": "Afrikaans", - "ar-ae": "Arabiera (Arabiar Emirerri Batuak)", - "ar-bh": "Arabiera (Bahrain)", - "ar-dz": "Arabiera (Algeria)", - "ar-eg": "Arabiera (Egipto)", - "ar-iq": "Arabiera (Irak)", - "ar-jo": "Arabiera (Jordania)", - "ar-kw": "Arabiera (Kuwait)", - "ar-lb": "Arabiera (Libano)", - "ar-ly": "Arabiera (Libia)", - "ar-ma": "Arabiera (Maroko)", - "ar-om": "Arabiera (Oman)", - "ar-qa": "Arabiera (Qatar)", - "ar-sa": "Arabiera (Saudi Arabia)", - "Cancel": "Utzi", - "ar-sy": "Arabiera (Siria)", - "ar-tn": "Arabiera (Tunisia)", - "ar-ye": "Arabiera (Yemen)", - "be": "Bielorrusiera", - "bg": "Bulgariera", - "ca": "Katalana", - "cs": "Txekiera", - "da": "Daniera", - "de-at": "Alemana (Austria)", - "de-ch": "Alemana (Suitza)", - "de": "Alemana", - "de-li": "Alemana (Liechtenstein)", - "de-lu": "Alemana (Luxenburgo)", - "el": "Greziera", - "en-au": "Ingelesa (Australia)", - "en-bz": "Ingelesa (Belize)", - "en-ca": "Ingelesa (Kanada)", - "en": "Ingelesa", - "en-gb": "Ingelesa (Erresuma batua)", - "en-ie": "Ingelesa (Irlanda)", - "en-jm": "Ingelesa (Jamaika)", - "en-nz": "Ingelesa (Zeelanda Berria)", - "en-tt": "Ingelesa (Trinidad)", - "en-us": "Ingelesa (Estatu Batuak)", - "en-za": "Ingelesa (Hego Afrika)", - "es-ar": "Espainiera (Argentina)", - "es-bo": "Espainiera (Bolivia)", - "es-cl": "Espainiera (Txile)", - "es-co": "Espainiera (Kolonbia)", - "es-cr": "Espainiera (Costa Rica)", - "es-do": "Espainiera (Dominikar Errepublika)", - "es-ec": "Espainiera (Ekuador)", - "es-gt": "Espainiera (Guatemala)", - "es-hn": "Espainiera (Honduras)", - "es-mx": "Espainiera (Mexiko)", - "es-ni": "Espainiera (Nikaragua)", - "es-pa": "Espainiera (Panama)", - "es-pe": "Espainiera (Peru)", - "es-pr": "Espainiera (Puerto Rico)", - "es-py": "Espainiera (Paraguay)", - "es": "Espainiera (Espainia)", - "es-sv": "Espainiera (El Salvador)", - "es-uy": "Espainiera (Uruguai)", - "es-ve": "Espainiera (Venezuela)", - "et": "Estoniera", - "eu": "Euskara", - "fa": "Farsiera", - "fi": "Finlandiera", - "fo": "Faroera", - "fr-be": "Frantsesa (Belgika)", - "fr-ca": "Frantsesa (Kanada)", - "fr-ch": "Frantsesa (Suitza)", - "fr": "Frantsesa", - "fr-lu": "Frantsesa (Luxenburgo)", - "ga": "Irlandera", - "gd": "Gaelikoa (Eskozia)", - "he": "Hebreera", - "hi": "Hindi", - "hr": "Kroaziera", - "hu": "Hungariera", - "id": "Indonesiera", - "is": "Islandiera", - "it-ch": "Italiera (Suitza)", - "it": "Italiera", - "ja": "Japoniera", - "ji": "Yiddish", - "ko": "Korearra", - "lt": "Lituaniera", - "lv": "Letoniera", - "mk": "Mazedoniera (FYROM)", - "ms": "Malaysiera", - "mt": "Maltera", - "nl-be": "Nederlandera (Belgika)", - "nl": "Nederlandera", - "no": "Norvegiera", - "pl": "Poloniera", - "pt-br": "Brasilgo portugalera", - "pt": "Portugalera", - "rm": "Erretorromaniera", - "ro-mo": "Errumaniera (Moldavia)", - "ro": "Errumaniera", - "ru-mo": "Errusiera (Moldavia)", - "ru": "Errusiera", - "sb": "Sorbiera", - "sk": "Eslovakiera", - "sl": "Esloveniera", - "sq": "Albaniera", - "sr": "Serbiera", - "sv-fi": "Suediera (Finlandia)", - "sv": "Suediera", - "sx": "Sutu", - "sz": "Sami (Laponiera)", - "th": "Thailandiera", - "tn": "Tswanera", - "tr": "Turkiera", - "ts": "Tsonga", - "uk": "Ukrainera", - "ur": "Urdu", - "ve": "Vendera", - "vi": "Vietnamera", - "xh": "Xhosera", - "zh-cn": "Txinera (PRC)", - "zh-hk": "Txinera (Hong Kong)", - "zh-sg": "Txinera (Singapur)", - "zh-tw": "Txinera (Taiwan)", - "zu": "Zulu", "a room": "gela bat", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Mezu bat bidali da +%(msisdn)s zenbakira. Sartu hemen mezuko egiaztaketa kodea", "Accept": "Onartu", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index f6da302fad..0dd2a6fcbb 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -1,124 +1,4 @@ { - "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": "Belarusian", - "bg": "Bulgarian", - "ca": "Catalan", - "cs": "Czech", - "da": "Danish", - "de-at": "German (Austria)", - "de-ch": "German (Switzerland)", - "de": "German", - "de-li": "German (Liechtenstein)", - "de-lu": "German (Luxembourg)", - "el": "Greek", - "en-au": "English (Australia)", - "en-bz": "English (Belize)", - "en-ca": "English (Canada)", - "en": "English", - "en-gb": "English (United Kingdom)", - "en-ie": "English (Ireland)", - "en-jm": "English (Jamaica)", - "en-nz": "English (New Zealand)", - "en-tt": "English (Trinidad)", - "en-us": "English (United States)", - "en-za": "English (South Africa)", - "es-ar": "Spanish (Argentina)", - "es-bo": "Spanish (Bolivia)", - "es-cl": "Spanish (Chile)", - "es-co": "Spanish (Colombia)", - "es-cr": "Spanish (Costa Rica)", - "es-do": "Spanish (Dominican Republic)", - "es-ec": "Spanish (Ecuador)", - "es-gt": "Spanish (Guatemala)", - "es-hn": "Spanish (Honduras)", - "es-mx": "Spanish (Mexico)", - "es-ni": "Spanish (Nicaragua)", - "es-pa": "Spanish (Panama)", - "es-pe": "Spanish (Peru)", - "es-pr": "Spanish (Puerto Rico)", - "es-py": "Spanish (Paraguay)", - "es": "Spanish (Spain)", - "es-sv": "Spanish (El Salvador)", - "es-uy": "Spanish (Uruguay)", - "es-ve": "Spanish (Venezuela)", - "et": "Estonian", - "eu": "Basque (Basque)", - "fa": "Farsi", - "fi": "Finnish", - "fo": "Faeroese", - "fr-be": "French (Belgium)", - "fr-ca": "French (Canada)", - "fr-ch": "French (Switzerland)", - "fr": "French", - "fr-lu": "French (Luxembourg)", - "ga": "Irish", - "gd": "Gaelic (Scotland)", - "he": "Hebrew", - "hi": "Hindi", - "hr": "Croatian", - "hu": "Hungarian", - "id": "Indonesian", - "is": "Icelandic", - "it-ch": "Italian (Switzerland)", - "it": "Italian", - "ja": "Japanese", - "ji": "Yiddish", - "ko": "Coréen", - "lt": "Lithuanian", - "lv": "Latvian", - "mk": "Macedonian (FYROM)", - "ms": "Malaysian", - "mt": "Maltese", - "nl-be": "Dutch (Belgium)", - "nl": "Dutch", - "no": "Norwegian", - "pl": "Polish", - "pt-br": "Brazilian Portuguese", - "pt": "Portuguese", - "rm": "Rhaeto-Romanic", - "ro-mo": "Romanian (Republic of Moldova)", - "ro": "Romanian", - "ru-mo": "Russian (Republic of Moldova)", - "ru": "Russian", - "sb": "Sorbian", - "sk": "Slovak", - "sl": "Slovenian", - "sq": "Albanian", - "sr": "Serbe", - "sv-fi": "Swedish (Finland)", - "sv": "Swedish", - "sx": "Sutu", - "sz": "Sami (Lappish)", - "th": "Thai", - "tn": "Tswana", - "tr": "Turkish", - "ts": "Tsonga", - "uk": "Ukrainian", - "ur": "Urdu", - "ve": "Venda", - "vi": "Vietnamese", - "xh": "Xhosa", - "zh-cn": "Chinese (PRC)", - "zh-hk": "Chinese (Hong Kong SAR)", - "zh-sg": "Chinese (Singapore)", - "zh-tw": "Chinese (Taiwan)", - "zu": "Zulu", "anyone": "n'importe qui", "Direct Chat": "Discussion directe", "Direct chats": "Conversations directes", diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index 2d9daecc49..0967ef424b 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -1,21 +1 @@ -{ - "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": "בולגרית" -} +{} diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index eea96f9ea3..4809cb6559 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -25,123 +25,6 @@ "Thursday": "Csütörtök", "Friday": "Péntek", "Saturday": "Szombat", - "af": "Afrikaans", - "ar-ae": "Arabic (U.A.E.)", - "ar-bh": "Arab (Bahrain)", - "ar-dz": "Arab (Algeria)", - "ar-eg": "Arab (Egypt)", - "ar-iq": "Arab (Iraq)", - "ar-jo": "Arab (Jordan)", - "ar-kw": "Arab (Kuwait)", - "ar-lb": "Arab (Lebanon)", - "ar-ly": "Arab (Libya)", - "ar-ma": "Arab (Morocco)", - "ar-om": "Arab (Oman)", - "ar-qa": "Arab (Qatar)", - "ar-sa": "Arab (Saudi Arabia)", - "ar-sy": "Arab (Syria)", - "ar-tn": "Arab (Tunisia)", - "ar-ye": "Arab (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", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 71b2f145a6..67df5bc332 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -20,10 +20,6 @@ "Error": "Errore", "Failed to join the room": "Impossibile entrare nella stanza", "Favourite": "Preferito", - "ar-ae": "Arabo (U.A.E.)", - "ar-bh": "Arabo (Bahrain)", - "ar-dz": "Arabo (Algeria)", - "ar-eg": "Arabo (Egitto)", "Sunday": "Domenica", "Monday": "Lunedì", "Tuesday": "Martedì", @@ -36,117 +32,6 @@ "Drop here %(toAction)s": "Rilascia qui %(toAction)s", "Failed to change password. Is your password correct?": "Modifica password fallita. La tua password è corretta?", "Continue": "Continua", - "ar-iq": "Arabo (Iraq)", - "ar-jo": "Arabo (Giordania)", - "ar-kw": "Arabo (Kuwait)", - "ar-lb": "Arabo (Libano)", - "ar-ly": "Arabo (Libia)", - "ar-ma": "Arabo (Marocco)", - "ar-om": "Arabo (Oman)", - "ar-qa": "Arabo (Qatar)", - "ar-sa": "Arabo (Arabia Saudita)", - "ar-sy": "Arabo (Siria)", - "ar-tn": "Arabo (Tunisia)", - "ar-ye": "Arabo (Yemen)", - "be": "Bielorusso", - "bg": "Bulgaro", - "ca": "Catalano", - "da": "Danese", - "de-at": "Tedesco (Austria)", - "de-ch": "Tedesco (Svizzera)", - "de": "Tedesco", - "de-li": "Tedesco (Liechtenstein)", - "de-lu": "Tedesco (Lussemburgo)", - "el": "Greco", - "en-au": "Inglese (Australia)", - "en-bz": "Inglese (Belize)", - "en-ca": "Inglese (Canada)", - "en": "Inglese", - "en-gb": "Inglese (Regno Unito)", - "en-ie": "Inglese (Irlanda)", - "en-jm": "Inglese (Jamaica)", - "en-nz": "Inglese (Nuova Zelanda)", - "en-tt": "Inglese (Trinidad)", - "en-us": "Inglese (Stati Uniti)", - "en-za": "Inglese (Sud Africa)", - "es-ar": "Spagnolo (Argentina)", - "es-bo": "Spagnolo (Bolivia)", - "es-cl": "Spagnolo (Cile)", - "es-co": "Spagnolo (Colombia)", - "es-cr": "Spagnolo (Costa Rica)", - "es-do": "Spagnolo (Repubblica Dominicana)", - "es-ec": "Spagnolo (Ecuador)", - "es-gt": "Spagnolo (Guatemala)", - "es-hn": "Spagnolo (Honduras)", - "es-mx": "Spagnolo (Messico)", - "es-ni": "Spagnolo (Nicaragua)", - "es-pa": "Spagnolo (Panama)", - "es-pe": "Spagnolo (Perù)", - "es-pr": "Spagnolo (Porto Rico)", - "es-py": "Spagnolo (Paraguay)", - "es": "Spagnolo (Spagna)", - "es-sv": "Spagnolo (El Salvador)", - "es-uy": "Spagnolo (Uruguay)", - "es-ve": "Spagnolo (Venezuela)", - "et": "Estone", - "eu": "Basco (Basco)", - "fa": "Farsi", - "fi": "Finlandese", - "fo": "Faeroese", - "fr-be": "Francese (Belgio)", - "fr-ca": "Francese (Canada)", - "fr-ch": "Francese (Svizzera)", - "fr": "Francese", - "fr-lu": "Francese (Lussemburgo)", - "ga": "Irlandese", - "gd": "Gaelico (Scozia)", - "he": "Ebraico", - "hi": "Hindi", - "hr": "Croato", - "hu": "Ungherese", - "id": "Indonesiano", - "is": "Islandese", - "it-ch": "Italiano (Svizzera)", - "it": "Italiano", - "ja": "Giapponese", - "ji": "Yiddish", - "ko": "Coreano", - "lt": "Lituano", - "lv": "Lettone", - "mk": "Macedone (FYROM)", - "ms": "Malese", - "mt": "Maltese", - "nl-be": "Olandese (Belgio)", - "nl": "Olandese", - "no": "Norvegese", - "pl": "Polacco", - "pt-br": "Portoghese Brasiliano", - "pt": "Portoghese", - "rm": "Romancio", - "ro-mo": "Rumeno (Repubblica di Moldavia)", - "ro": "Rumeno", - "ru-mo": "Russo (Repubblica di Moldavia)", - "ru": "Russo", - "sk": "Slovacco", - "sl": "Sloveno", - "sq": "Albanese", - "sr": "Serbo", - "sv-fi": "Svedese (Finlandia)", - "sv": "Svedese", - "sx": "Sutu", - "th": "Tailandese", - "tn": "Tswana", - "tr": "Turco", - "ts": "Tsonga", - "uk": "Ucraino", - "ur": "Urdu", - "vi": "Vietnamese", - "xh": "Xhosa", - "zh-cn": "Cinese (PRC)", - "zh-hk": "Cinese (Honk Kong SAR)", - "zh-sg": "Cinese (Singapore)", - "zh-tw": "Cinese (Taiwan)", - "zu": "Zulu", "a room": "una stanza", "%(targetName)s accepted an invitation.": "%(targetName)s ha accettato un invito.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s ha accettato l'invito per %(displayName)s.", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index f0be3024a5..37eb3cfa5c 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -1,5 +1,4 @@ { - "ja": "日本語", "Anyone": "誰でも", "Anyone who knows the room's link, apart from guests": "誰でも部屋に参加できる (ゲストユーザは不可)", "Anyone who knows the room's link, including guests": "誰でも部屋に参加できる (ゲストユーザも可能)", @@ -63,125 +62,6 @@ "Riot collects anonymous analytics to allow us to improve the application.": "Riotはアプリケーションを改善するために匿名の分析情報を収集しています。", "Start chatting": "対話開始", "Start Chatting": "対話開始", - "af": "アフリカーンス語", - "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": "英語 (トリニダード)", - "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": "アラビア語 (イエメン)", - "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": "ハンガリー語", - "id": "インドネシア語", - "is": "アイスランド語", - "it-ch": "イタリア語 (スイス)", - "it": "イタリア語 (イタリア)", - "ji": "イディッシュ語", - "ko": "韓国語", - "lt": "リトアニア語", - "lv": "ラトビア語", - "mk": "マケドニア語 (FYROM)", - "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": "ヴェンダ語", - "vi": "ベトナム語", - "xh": "コーサ語", - "zh-cn": "中国語 (中華人民共和国)", - "zh-hk": "中国語 (香港)", - "zh-sg": "中国語 (シンガポール)", - "zh-tw": "中国語 (台湾)", - "zu": "ズールー語", "Add": "追加", "No Microphones detected": "マイクが見つかりません", "No Webcams detected": "カメラが見つかりません", diff --git a/src/i18n/strings/ko.json b/src/i18n/strings/ko.json index e5faf01da7..89de8eae1f 100644 --- a/src/i18n/strings/ko.json +++ b/src/i18n/strings/ko.json @@ -1,32 +1,4 @@ { - "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": "독일어", - "de-li": "독일어 (리히텐슈타인)", - "de-lu": "독일어 (룩셈부르크)", - "el": "그리스어", "Cancel": "취소", "Close": "닫기", "Create new room": "새 방 만들기", @@ -54,96 +26,6 @@ "OK": "알았어요", "Welcome page": "환영 화면", "Continue": "게속하기", - "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": "헝가리어", - "id": "인도네시아어", - "is": "아이슬란드어", - "it-ch": "이탈리아어 (스위스)", - "it": "이탈리아어", - "ja": "일본어", - "ji": "이디시어", - "ko": "한국어", - "lt": "리투아니아어", - "lv": "라트비아어", - "mk": "마케도니아어 (마케도니아 공화국)", - "ms": "말레이시아어", - "mt": "몰타어", - "nl-be": "네덜란드어 (벨기에)", - "nl": "네덜란드어", - "no": "노르웨이어", - "pl": "폴란드어", - "pt-br": "브라질 포르투갈어", - "pt": "포르투갈어", - "rm": "레토로만어", - "ro-mo": "루마니아어 (몰도바 공화국)", - "ro": "루마니아어", - "ru-mo": "러시아어 (몰도바 공확국)", - "ru": "러시아어", - "sb": "소르비아어", - "sk": "슬로바키아어", - "sr": "세르비아어", - "sv-fi": "스웨덴어 (핀란드)", - "sv": "스웨덴어", - "sx": "수투어", - "sz": "라플란드어 (라플란드)", - "th": "태국", - "tn": "츠와나어", - "tr": "터키어", - "ts": "총가어", - "uk": "우크라이나어", - "ur": "우르두어", - "ve": "벤다어", - "vi": "베트남어", - "xh": "코사어", - "zh-cn": "중국어 (중국)", - "zh-hk": "중국어 (홍콩)", - "zh-sg": "중국어 (싱가포르)", - "zh-tw": "중국어 (대만)", - "zu": "줄루어", "a room": "방", "Accept": "수락", "Account": "계정", diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index 041403b32f..9599d2e2d1 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -1,124 +1,4 @@ { - "af": "Afrikandu", - "ar-ae": "Arābu (A.A.E.)", - "ar-bh": "Arābu (Bahraina)", - "ar-dz": "Arābu (Alžīrija)", - "ar-eg": "Arābu (Ēģipte)", - "ar-iq": "Arābu (Irāka)", - "ar-jo": "Arābu (Jordāna)", - "ar-kw": "Arābu (Kuveita)", - "ar-lb": "Arābu (Lebanēna)", - "ar-ly": "Arābu (Lībija)", - "ar-ma": "Arābu (Maroka)", - "ar-om": "Arābu (Omāna)", - "ar-qa": "Arābu (Kvatara)", - "ar-sa": "Arābu (Saūda Arābija)", - "ar-sy": "Arābu (Sīrija)", - "ar-tn": "Arābu (Tunisija)", - "ar-ye": "Arābu (Jemena)", - "be": "Baltkrievu", - "bg": "Bulgāru", - "ca": "Katalāņu", - "cs": "Čehu", - "da": "Dāņu", - "de-at": "Vācu (Austrija)", - "de-ch": "Vācu (Šveice)", - "de": "Vācu", - "de-li": "Vācu (Lihtenšteina)", - "de-lu": "Vācu (Luksemburga)", - "el": "Grieķu", - "en-au": "Angļu (Austrālija)", - "en-bz": "Angļu (Beliza)", - "en-ca": "Angļu (Kanāda)", - "en": "Angļu", - "en-gb": "Angļu (Apvienotā Karaliste)", - "en-ie": "Angļu (Īrija)", - "en-jm": "Angļu (Jamaika)", - "en-nz": "Angļu (Jaunzēlande)", - "en-tt": "Angļu (Trinidāda)", - "en-us": "Angļu (ASV)", - "en-za": "Angļu (Dienvidāfrika)", - "es-ar": "Spāņu (Argentīna)", - "es-bo": "Spāņu (Bolīvija)", - "es-cl": "Spāņu (Čīle)", - "es-co": "Spāņu (Kolumbija)", - "es-cr": "Spāņu (Kostarika)", - "es-do": "Spāņu (Dominikānas Republika)", - "es-ec": "Spāņu (Ekvadora)", - "es-gt": "Spāņu (Gvatemala)", - "es-hn": "Spāņu (Hondurasa)", - "es-mx": "Spāņu (Meksika)", - "es-ni": "Spāņu (Nikaragva)", - "es-pa": "Spāņu (Panama)", - "es-pe": "Spāņu (Peru)", - "es-pr": "Spāņu (Puertoriko)", - "es-py": "Spāņu (Paragvaja)", - "es": "Spāņu (Spānija)", - "es-sv": "Spāņu (Salvadora)", - "es-uy": "Spāņu (Urugvaja)", - "es-ve": "Spāņu (Venecuēla)", - "et": "Igauņu", - "eu": "Basku (Basku Zeme)", - "fa": "Farsi", - "fi": "Somu", - "fo": "Fēriešu", - "fr-be": "Franču (Beļģija)", - "fr-ca": "Franču (Kanāda)", - "fr-ch": "Franču (Šveice)", - "fr": "Franču", - "fr-lu": "Franču (Luksemburga)", - "ga": "Īru", - "gd": "Gallu (Skotija)", - "he": "Ebreju", - "hi": "Hindi", - "hr": "Kroātu", - "hu": "Ungāru", - "id": "Indonēziešu", - "is": "Islandiešu", - "it-ch": "Itāļu (Šveice)", - "it": "Itāļu", - "ja": "Japāņu", - "ji": "Jidišs", - "ko": "Korejiešu", - "lt": "Lietuviešu", - "lv": "Latviešu", - "mk": "Maķedoniešu (FYROM)", - "ms": "Malaiziešu", - "mt": "Maltiešu", - "nl-be": "Nīderlandiešu (Beļģija)", - "nl": "Nīderlandiešu", - "no": "Norvēģu", - "pl": "Poļu", - "pt-br": "Brazīlijas portugāļu", - "pt": "Portugāļu", - "rm": "Retoromāņu", - "ro-mo": "Rumāņu (Moldovas Republika)", - "ro": "Rumāņu", - "ru-mo": "Krievu (Moldovas Republika)", - "ru": "Krievu", - "sb": "Sorbu", - "sk": "Slovāku", - "sl": "Slovēņu", - "sq": "Albāniešu", - "sr": "Serbu", - "sv-fi": "Zviedru (Somija)", - "sv": "Zviedru", - "sx": "Sutu", - "sz": "Sāmu (Lapu)", - "th": "Taju", - "tn": "Cvanu", - "tr": "Turku", - "ts": "Congu", - "uk": "Ukraiņu", - "ur": "Urdu", - "ve": "Vendu", - "vi": "Vjetnamiešu", - "xh": "Khosu", - "zh-cn": "Ķīniešu (ĶTR)", - "zh-hk": "Ķīniešu (Honkongas SAR)", - "zh-sg": "Ķīniešu (Singapūra)", - "zh-tw": "Ķīniešu (Taivāna)", - "zu": "Zulu", "a room": "istaba", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Teksta ziņa tika nosūtīta +%(msisdn)s. Lūdzu ievadi tajā atrodamo verifikācijas kodu", "Accept": "Apstiprināt", diff --git a/src/i18n/strings/ml.json b/src/i18n/strings/ml.json index 97c9edd749..9f10cd25b7 100644 --- a/src/i18n/strings/ml.json +++ b/src/i18n/strings/ml.json @@ -33,8 +33,5 @@ "Failed to change password. Is your password correct?": "രഹസ്യവാക്ക് മാറ്റാന്‍ സാധിച്ചില്ല. രഹസ്യവാക്ക് ശരിയാണോ ?", "Continue": "മുന്നോട്ട്", "Microphone": "മൈക്രോഫോൺ", - "Camera": "ക്യാമറ", - "af": "ആഫ്രിക്കാൻസ്", - "ar-ae": "അറബി (യു.എ.ഇ.)", - "ar-bh": "അറബി (ബഹറിൻ)" + "Camera": "ക്യാമറ" } diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index ebb1c42056..bc92d7bcad 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -1,125 +1,4 @@ { - "af": "Afrikaans", - "ar-ae": "Arabisch (U.A.E.)", - "Direct Chat": "Privégesprek", - "ar-bh": "Arabisch (Bahrain)", - "ar-dz": "Arabisch (Algerije)", - "ar-eg": "Arabisch (Egypte)", - "ar-iq": "Arabisch (Irak)", - "ar-jo": "Arabisch (Jordanië)", - "ar-kw": "Arabisch (Koeweit)", - "ar-lb": "Arabisch (Libanon)", - "ar-ly": "Arabisch (Libië)", - "ar-ma": "Arabisch (Marokko)", - "ar-om": "Arabisch (Oman)", - "ar-qa": "Arabisch (Katar)", - "ar-sa": "Arabisch (Saoedi-Arabië)", - "ar-sy": "Arabisch (Syrië)", - "ar-tn": "Arabisch (Tunesië)", - "ar-ye": "Arabisch (Jemen)", - "be": "Wit-Russisch", - "bg": "Bulgaars", - "ca": "Catalaans", - "cs": "Tsjechisch", - "da": "Deens", - "de-at": "Duits (Oostenrijk)", - "de-ch": "Duits (Zwitserland)", - "de": "Duits", - "de-li": "Duits (Liechtenstein)", - "de-lu": "Duits (Luxemburg)", - "el": "Grieks", - "en-au": "Engels (Australië)", - "en-bz": "Engels (Belize)", - "en-ca": "Engels (Canada)", - "en": "Engels", - "en-gb": "Engels (Verenigd Koningkrijk)", - "en-ie": "Engels (Ierland)", - "en-jm": "Engels (Jamaica)", - "en-nz": "Engels (Nieuw Zeeland)", - "en-tt": "Engels (Trinidad)", - "en-us": "Engels (Verenigde Staten)", - "en-za": "Engels (Zuid-Afrika)", - "es-ar": "Spaans (Argentinië)", - "es-bo": "Spaans (Bolivië)", - "es-cl": "Spaans (Chili)", - "es-co": "Spaans (Colombia)", - "es-cr": "Spaans (Costa Rica)", - "es-do": "Spaans (Dominicaanse Republiek)", - "es-ec": "Spaans (Ecuador)", - "es-gt": "Spaans (Guatemala)", - "es-hn": "Spaans (Honduras)", - "es-mx": "Spaans (Mexico)", - "es-ni": "Spaans (Nicaragua)", - "es-pa": "Spaans (Panama)", - "es-pe": "Spaans (Peru)", - "es-pr": "Spaans (Puerto Rico)", - "es-py": "Spaans (Paraguay)", - "es": "Spaans (Spanje)", - "es-sv": "Spaans (El Salvador)", - "es-uy": "Spaans (Uruguay)", - "es-ve": "Spaans (Venezuela)", - "et": "Estlands", - "eu": "Baskisch (Bask)", - "fa": "Perzisch (Farsi)", - "fi": "Fins", - "fo": "Faeroesisch", - "fr-be": "Frans (België)", - "fr-ca": "Frans (Canada)", - "fr-ch": "Frans (Zwitserland)", - "fr": "Frans", - "fr-lu": "Frans (Luxemburg)", - "ga": "Iers", - "gd": "Keltisch (Schotland)", - "he": "Hebreeuws", - "hi": "Hindi", - "hr": "Kroatisch", - "hu": "Hongaars", - "id": "Indonesisch", - "is": "IJslands", - "it-ch": "Italiaans (Zwitserland)", - "it": "Italiaans", - "ja": "Japans", - "ji": "Jiddisch", - "ko": "Koreaans", - "lt": "Litouws", - "lv": "Lets", - "mk": "Macedonië (FYROM)", - "ms": "Maleisisch", - "mt": "Maltees", - "nl-be": "Nederlands (België)", - "nl": "Nederlands", - "no": "Noors", - "pl": "Pools", - "pt-br": "Braziliaans Portugees", - "pt": "Portugees", - "rm": "Rhetoromaans", - "ro-mo": "Roemeens (Moldavië)", - "ro": "Roemeens", - "ru-mo": "Russisch (Moldavië)", - "ru": "Russisch", - "sb": "Sorbisch", - "sk": "Slovaaks", - "sl": "Sloveens", - "sq": "Albanees", - "sr": "Servisch", - "sv-fi": "Zweeds (Finland)", - "sv": "Zweeds", - "sx": "Sutu", - "sz": "Sami (Lapland)", - "th": "Thais", - "tn": "Tswana", - "tr": "Turks", - "ts": "Tsonga", - "uk": "Oekraïens", - "ur": "Urdu", - "ve": "Venda", - "vi": "Vietnamees", - "xh": "Xhosa", - "zh-cn": "Chinees (PRC)", - "zh-hk": "Chinees (Hong Kong SAR)", - "zh-sg": "Chinees (Singapore)", - "zh-tw": "Chinees (Taiwan)", - "zu": "Zulu", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Voer alsjeblieft de verificatiecode in die is verstuurd naar +%(msisdn)s", "accept": "accepteer", "%(targetName)s accepted an invitation.": "%(targetName)s heeft een uitnodiging geaccepteerd.", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 624302543d..724fa24564 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -72,21 +72,6 @@ "Usage": "Użycie", "Upload file": "Prześlij plik", "Unban": "Odbanuj", - "en": "Angielski", - "fi": "Fiński", - "fr": "Francuski", - "he": "Hebrajski", - "hu": "Węgierski", - "it": "Włoski", - "ja": "Japoński", - "no": "Norweski", - "pl": "Polski", - "ru": "Rosyjski", - "sq": "Albański", - "sr": "Serbski", - "th": "Tajski", - "uk": "Ukraiński", - "vi": "Wietnamski", "Accept": "Akceptuj", "Account": "Konto", "Add": "Dodaj", @@ -129,109 +114,7 @@ "Please Register": "Proszę się zarejestrować", "powered by Matrix": "napędzany przez Matrix", "Failed to change password. Is your password correct?": "Zmiana hasła nie powiodła się. Czy Twoje hasło jest poprawne?", - "be": "Białoruski", - "bg": "Bułgarski", - "cs": "Czeski", - "da": "Duński", - "de": "Niemiecki", - "el": "Grecki", - "et": "Estoński", - "ga": "Irlandzki", - "hr": "Chorwacki", - "is": "Islandzki", - "hi": "Hindi", - "lt": "Litewski", - "lv": "Łotewski", - "nl": "Holenderski", - "pt": "Portugalski", - "sl": "Słoweński", - "sk": "Słowacki", - "sv": "Szwedzki", - "tr": "Turecki", "Add a topic": "Dodaj temat", - "af": "Afrikaans", - "ar-ae": "Arabski (ZEA)", - "ar-bh": "Arabski (Bahrajn)", - "ar-dz": "Arabski (Algieria)", - "ar-eg": "Arabski (Egipt)", - "ar-iq": "Arabski (Irak)", - "ar-jo": "Arabski (Jordania)", - "ar-kw": "Arabski (Kuwejt)", - "ar-lb": "Arabski (Liban)", - "ar-ly": "Arabski (Libia)", - "ar-ma": "Arabski (Maroko)", - "ar-om": "Arabski (Oman)", - "ar-qa": "Arabski (Katar)", - "ar-sa": "Arabski (Arabia Saudyjska)", - "ar-sy": "Arabski (Syria)", - "ar-tn": "Arabski (Tunezja)", - "ar-ye": "Arabski (Jemen)", - "ca": "Kataloński", - "de-at": "Niemiecki (Austria)", - "de-ch": "Niemiecki (Szwajcaria)", - "de-li": "Niemiecki (Liechtenstein)", - "de-lu": "Niemiecki (Luksemburg)", - "en-au": "Angielski (Australia)", - "en-bz": "Angielski (Belize)", - "en-ca": "Angielski (Kanada)", - "en-gb": "Angielski (Wielka Brytania)", - "en-ie": "Angielski (Irlandia)", - "en-jm": "Angielski (Jamajka)", - "en-nz": "Angielski (Nowa Zelandia)", - "en-tt": "Angielski (Trynidad)", - "en-us": "Angielski (Stany Zjednoczone)", - "en-za": "Angielski (Afryka Południowa)", - "es-ar": "Hiszpański (Argentyna)", - "es-bo": "Hiszpański (Boliwia)", - "es-cl": "Hiszpański (Chile)", - "es-co": "Hiszpański (Kolumbia)", - "es-cr": "Hiszpański (Kostaryka)", - "es-do": "Hiszpański (Dominikana)", - "es-ec": "Hiszpański (Ekwador)", - "es-gt": "Hiszpański (Gwatemala)", - "es-hn": "Hiszpański (Honduras)", - "es-mx": "Hiszpański (Meksyk)", - "es-ni": "Hiszpański (Nikaragua)", - "es-pa": "Hiszpański (Panama)", - "es-pe": "Hiszpański (Peru)", - "es-pr": "Hiszpański (Portoryko)", - "es-py": "Hiszpański (Paragwaj)", - "es": "Hiszpański (Hiszpania)", - "es-sv": "Hiszpański (Salwador)", - "es-uy": "Hiszpański (Urugwaj)", - "es-ve": "Hiszpański (Wenezuela)", - "eu": "Baskijski", - "fa": "Perski", - "fr-be": "Francuski (Belgia)", - "fr-ca": "Francuski (Kanada)", - "fr-ch": "Francuski (Szwajcaria)", - "fr-lu": "Francuski (Luksemburg)", - "gd": "Gaelicki (Szkocja)", - "id": "Indonezyjski", - "it-ch": "Włoski (Szwajcaria)", - "ji": "Jidysz", - "ko": "Koreański", - "mk": "Macedoński (BJRM)", - "ms": "Malezyjski", - "mt": "Maltański", - "nl-be": "Holenderski (Belgia)", - "pt-br": "Portugalski (Brazylia)", - "ro-mo": "Rumuński (Republika Mołdawii)", - "ro": "Rumuński", - "ru-mo": "Rosyjski (Republika Mołdawii)", - "sb": "Łużycki", - "sv-fi": "Szwedzki (Finlandia)", - "sx": "Sutu", - "sz": "Sami (Lapoński)", - "ts": "Tsonga", - "ur": "Urdu", - "ve": "Venda", - "xh": "Xhosa", - "zh-cn": "Chiński (ChRL)", - "zh-hk": "Chiński (Hongkong)", - "zh-sg": "Chiński (Singapur)", - "zh-tw": "Chiński (Tajwan)", - "zu": "Zuluski", "a room": "pokój", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Wysłano wiadomość tekstową do +%(msisdn)s. Proszę wprowadzić kod w niej zawarty", "%(targetName)s accepted an invitation.": "%(targetName)s zaakceptował(a) zaproszenie.", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index cb4ba65ec4..6342ab8f59 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -303,11 +303,6 @@ "Dec": "Dez", "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(day)s de %(monthName)s às %(time)s", "%(weekDayName)s %(time)s": "%(weekDayName)s às %(time)s", - "en": "Inglês", - "pt-br": "Português do Brasil", - "de": "Alemão", - "da": "Dinamarquês", - "ru": "Russo", "%(targetName)s accepted an invitation.": "%(targetName)s aceitou um convite.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s aceitou o convite para %(displayName)s.", "all room members, from the point they are invited": "todas/os as/os integrantes da sala, a partir do momento em que foram convidadas/os", @@ -431,70 +426,10 @@ "cancel all": "cancelar todas", "now. You can also select individual messages to resend or cancel.": "agora. Você também pode escolher mensagens individuais e definir se vai reenviar ou cancelar o envio.", "Active call": "Chamada ativa", - "af": "Afrikaans", - "ar-ae": "Árabe (E.A.U.)", - "ar-bh": "Árabe (Bahrain)", - "ar-dz": "Árabe (Argélia)", "Sunday": "Domingo", "Monday": "Segunda-feira", "ar-eg": "Árabe (Egito)", "ar-tn": "Árabe (Tunísia)", - "be": "Bielorrusso", - "bg": "Búlgaro", - "ca": "Catalão", - "cs": "Checo", - "el": "Grego", - "en-au": "Inglês (Austrália)", - "en-ca": "Inglês (Canadá)", - "en-gb": "Inglês (Reino Unido)", - "en-ie": "Inglês (Irlanda)", - "en-nz": "Inglês (Nova Zelândia)", - "en-us": "Inglês (Estados Unidos)", - "es-ar": "Espanhol (Argentina)", - "es-py": "Espanhol (Paraguai)", - "es": "Espanhol (Espanha)", - "et": "Estônia", - "fa": "Farsi", - "fi": "Finlandês", - "fr-be": "Francês (Bélgica)", - "fr-ca": "Francês (Canadá)", - "fr-ch": "Francês (Suíça)", - "fr": "Francês", - "ga": "Irlandês", - "he": "Hebreu", - "hi": "Hindu", - "hr": "Croácia", - "hu": "Hungria", - "id": "Indonésio", - "is": "Islandês", - "it": "Italiano", - "ja": "Japonês", - "ji": "Ídiche", - "lt": "Lituânia", - "lv": "Letão", - "ms": "Malaio", - "mt": "Maltês", - "nl-be": "Holandês (Bélgica)", - "nl": "Holandês", - "no": "Norueguês", - "pl": "Polonês", - "pt": "Português (Portugal)", - "rm": "Romanche", - "ro": "Romeno", - "sk": "Eslovaco", - "sl": "Esloveno", - "sq": "Albanês", - "sr": "Sérvio", - "sv": "Suécia", - "th": "Tailandês", - "tn": "Tsuana", - "tr": "Turquia", - "ts": "Tsonga", - "uk": "Ucraniano", - "ur": "Urdu", - "vi": "Vietnamita", - "xh": "Xhosa", - "zu": "Zulu", "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", @@ -502,56 +437,7 @@ "Thursday": "Quinta-feira", "Friday": "Sexta-feira", "Saturday": "Sábado", - "ar-iq": "Árabe (Iraque)", - "ar-jo": "Árabe (Jordânia)", - "ar-kw": "Árabe (Kuwait)", - "ar-lb": "Árabe (Líbano)", - "ar-ly": "Árabe (Líbia)", - "ar-ma": "Árabe (Marrocos)", - "ar-om": "Árabe (Omã)", - "ar-qa": "Árabe (Catar)", - "ar-sa": "Árabe (Arábia Saudita)", - "ar-sy": "Árabe (Síria)", - "ar-ye": "Árabe (Iémen)", - "de-at": "Alemão (Áustria)", - "de-ch": "Alemão (Suíça)", - "de-li": "Alemão (Liechtenstein)", - "de-lu": "Alemão (Luxemburgo)", - "en-bz": "Inglês (Belize)", - "en-jm": "Inglês (Jamaica)", - "en-tt": "Inglês (Trindade)", - "en-za": "English (África do Sul)", - "es-bo": "Espanhol (Bolívia)", - "es-cl": "Espanhol (Chile)", - "es-co": "Espanhol (Colômbia)", - "es-cr": "Espanhol (Costa Rica)", - "es-do": "Espanhol (República Dominicana)", - "es-ec": "Espanhol (Equador)", - "es-gt": "Espanhol (Guatemala)", - "es-hn": "Espanhol (Honduras)", - "es-mx": "Espanhol (México)", - "es-ni": "Espanhol (Nicarágua)", - "es-pa": "Espanhol (Panamá)", "%(oneUser)schanged their avatar": "%(oneUser)salterou sua imagem pública", - "es-pe": "Espanhol (Peru)", - "es-pr": "Espanhol (Porto Rico)", - "es-sv": "Espanhol (El Salvador)", - "es-uy": "Espanhol (Uruguai)", - "es-ve": "Espanhol (Venezuela)", - "eu": "Basco (Basco)", - "fr-lu": "Francês (Luxemburgo)", - "gd": "Galês (Escócia)", - "it-ch": "Italiano (Suíça)", - "ko": "Coreano", - "mk": "Macedônio (República da Macedônia)", - "ro-mo": "Romano (Moldávia)", - "ru-mo": "Russo (Moldávia)", - "sb": "Sorábio", - "sv-fi": "Sueco (Finlândia)", - "zh-cn": "Chinês (República Popular da China)", - "zh-hk": "Chinês (Hong Kong SAR)", - "zh-sg": "Chinês (Singapura)", - "zh-tw": "Chinês (Taiwan)", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Uma mensagem de texto foi enviada para +%(msisdn)s. Gentileza entrar com o código de verificação que contém", "%(items)s and %(remaining)s others": "%(items)s e %(remaining)s outros", "%(items)s and one other": "%(items)s e um outro", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index cd6230cd68..18294eae55 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -303,11 +303,6 @@ "Dec": "Dez", "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(day)s de %(monthName)s às %(time)s", "%(weekDayName)s %(time)s": "%(weekDayName)s às %(time)s", - "en": "Inglês", - "pt-br": "Português do Brasil", - "de": "Alemão", - "da": "Dinamarquês", - "ru": "Russo", "%(targetName)s accepted an invitation.": "%(targetName)s aceitou um convite.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s aceitou o convite para %(displayName)s.", "all room members, from the point they are invited": "todas/os as/os integrantes da sala, a partir do momento em que foram convidadas/os", @@ -432,70 +427,6 @@ "cancel all": "cancelar todas", "now. You can also select individual messages to resend or cancel.": "agora. Você também pode escolher mensagens individuais e definir se vai reenviar ou cancelar o envio.", "Active call": "Chamada ativa", - "af": "Afrikaans", - "ar-ae": "Árabe (U.A.E.)", - "ar-bh": "Árabe (Bahrain)", - "ar-dz": "Árabe (Algéria)", - "Sunday": "Domingo", - "Monday": "Segunda", - "ar-eg": "Árabe (Egito)", - "ar-tn": "Árabe (Tunisia)", - "be": "Bielorusso", - "bg": "Búlgaro", - "ca": "Catalão", - "cs": "Tcheco", - "el": "Grego", - "en-au": "Inglês (Austrália)", - "en-ca": "Inglês (Canadá)", - "en-gb": "Inglês (Reino Unido)", - "en-ie": "Inglês (Irlanda)", - "en-nz": "Inglês (Nova Zelândia)", - "en-us": "Inglês (Estados Unidos)", - "es-ar": "Espanhol (Argentina)", - "es-py": "Espanhol (Paraguai)", - "es": "Espanhol (Espanha)", - "et": "Estônia", - "fa": "Farsi", - "fi": "Finlandês", - "fr-be": "Francês (Bélgica)", - "fr-ca": "Francês (Canadá)", - "fr-ch": "Francês (Suíça)", - "fr": "Francês", - "ga": "Irlandês", - "he": "Hebreu", - "hi": "Hindu", - "hr": "Croácia", - "hu": "Hungria", - "id": "Indonésio", - "is": "Islandês", - "it": "Italiano", - "ja": "Japonês", - "ji": "Ídiche", - "lt": "Lituânia", - "lv": "Letão", - "ms": "Malaio", - "mt": "Maltês", - "nl-be": "Holandês (Bélgica)", - "nl": "Holandês", - "no": "Norueguês", - "pl": "Polonês", - "pt": "Português (Portugal)", - "rm": "Romanche", - "ro": "Romeno", - "sk": "Eslovaco", - "sl": "Esloveno", - "sq": "Albanês", - "sr": "Sérvio", - "sv": "Suécia", - "th": "Tailandês", - "tn": "Tsuana", - "tr": "Turquia", - "ts": "Tsonga", - "uk": "Ucraniano", - "ur": "Urdu", - "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", @@ -503,56 +434,7 @@ "Thursday": "Quinta", "Friday": "Sexta", "Saturday": "Sábado", - "ar-iq": "Árabe (Iraque)", - "ar-jo": "Árabe (Jordânia)", - "ar-kw": "Árabe (Kuwait)", - "ar-lb": "Árabe (Líbano)", - "ar-ly": "Árabe (Líbia)", - "ar-ma": "Árabe (Marrocos)", - "ar-om": "Árabe (Omã)", - "ar-qa": "Árabe (Catar)", - "ar-sa": "Árabe (Arábia Saudita)", - "ar-sy": "Árabe (Síria)", - "ar-ye": "Árabe (Iémen)", - "de-at": "Alemão (Austria)", - "de-ch": "Alemão (Suíça)", - "de-li": "Alemão (Liechtenstein)", - "de-lu": "Alemão (Luxemburgo)", - "en-bz": "Inglês (Belize)", - "en-jm": "Inglês (Jamaica)", - "en-tt": "English (Trindade)", - "en-za": "English (África do Sul)", - "es-bo": "Espanhol (Bolívia)", - "es-cl": "Espanhol (Chile)", - "es-co": "Espanhol (Colômbia)", - "es-cr": "Espanhol (Costa Rica)", - "es-do": "Espanhol (República Dominicana)", - "es-ec": "Espanhol (Equador)", - "es-gt": "Espanhol (Guatemala)", - "es-hn": "Espanhol (Honduras)", - "es-mx": "Espanhol (México)", - "es-ni": "Espanhol (Nicarágua)", - "es-pa": "Espanhol (Panamá)", "%(oneUser)schanged their avatar": "%(oneUser)salterou sua imagem pública", - "es-pe": "Espanhol (Peru)", - "es-pr": "Espanhol (Porto Rico)", - "es-sv": "Espanhol (El Salvador)", - "es-uy": "Espanhol (Uruguai)", - "es-ve": "Espanhol (Venezuela)", - "eu": "Basco (Basco)", - "fr-lu": "Francês (Luxemburgo)", - "gd": "Galês (Escócia)", - "it-ch": "Italiano (Suíça)", - "ko": "Coreano", - "mk": "Macedônio (República da Macedônia)", - "ro-mo": "Romano (Moldávia)", - "ru-mo": "Russo (Moldávia)", - "sb": "Sorábio", - "sv-fi": "Sueco (Finlândia)", - "zh-cn": "Chinês (República Popular da China)", - "zh-hk": "Chinês (Hong Kong SAR)", - "zh-sg": "Chinês (Singapura)", - "zh-tw": "Chinês (Taiwan)", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Uma mensagem de texto foi enviada para +%(msisdn)s. Gentileza entrar com o código de verificação que contém", "%(items)s and %(remaining)s others": "%(items)s e %(remaining)s outros", "%(items)s and one other": "%(items)s e um outro", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 9a49fca9cb..3a1ca3f331 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -211,11 +211,6 @@ "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": "Пароль успешно изменен. До повторной авторизации вы не будете получать push-уведомления на других устройствах", "You should not yet trust it to secure data": "На сегодняшний день не следует полностью полагаться на то, что ваши данные будут надежно зашифрованы", - "en": "Английский", - "pt-br": "Португальский (Бразилия)", - "de": "Немецкий", - "da": "Датский", - "ru": "Русский", "%(targetName)s accepted an invitation.": "%(targetName)s принял приглашение.", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s принял приглашение от %(displayName)s.", "Resend all": "Переслать снова всем", @@ -260,65 +255,6 @@ "Must be viewing a room": "Необходимо посмотреть комнату", "New Composer & Autocomplete": "Новый текстовый редактор и автозаполнение", "(not supported by this browser)": "(не поддерживается этим браузером)", - "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": "Чешский", - "de-at": "Немецкий (Австрия)", - "de-ch": "Немецкий (Швейцария)", - "de-li": "Немецкий (Лихтенштейн)", - "de-lu": "Немецкий (Люксембург)", - "el": "Греческий", - "en-au": "Английский (Австралия)", - "en-bz": "Английский (Белиз)", - "en-ca": "Английский (Канада)", - "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": "Испанский (Панама)", - "et": "Эстонский", - "fi": "Финский", - "fr": "Французский", - "hr": "Хорватский", - "it": "Итальянский", - "ja": "Японский", - "pl": "Польский", - "pt": "Португальский", - "ru-mo": "Русский (Республика Молдова)", - "ro": "Румынский", - "uk": "Украинский", "now. You can also select individual messages to resend or cancel.": "теперь. Вы можете также выбрать отдельные сообщения, чтобы снова послать или отменить.", "Auto-complete": "Автозаполнение", "Error changing language": "Ошибка изменения языка", @@ -341,13 +277,6 @@ "Make this room private": "Сделать эту комнату приватной", "Share message history with new users": "Разрешить доступ к истории сообщений новым пользователям", "Encrypt room": "Шифрование комнаты", - "es-pe": "Испанский (Перу)", - "hu": "Венгерский", - "nl": "Датский", - "no": "Норвежский", - "sv": "Шведский", - "th": "Тайский", - "vi": "Ветнамский", "Monday": "Понедельник", "Tuesday": "Вторник", "Wednesday": "Среда", @@ -398,55 +327,6 @@ "Usage": "Использование", "Use with caution": "Использовать с осторожностью", "VoIP is unsupported": "VoIP не поддерживается", - "es-pr": "Испанский (Пуэрто-Рико)", - "es-py": "Испанский язык (Парагвай)", - "es": "Испанский (Испания)", - "es-sv": "Испанский (Сальвадор)", - "es-uy": "Испанский (Уругвай)", - "es-ve": "Испанский (Венесуэла)", - "fa": "Фарси", - "fo": "Фарерский", - "fr-be": "Французский (Бельгия)", - "fr-ca": "Французский (Канада)", - "fr-ch": "Французский (Швейцария)", - "ga": "Ирландский", - "he": "Иврит", - "hi": "Хинди", - "id": "Индонезийский", - "is": "Исландский", - "ji": "Идиш", - "lt": "Литовский", - "lv": "Латвийский", - "ms": "Малазийский", - "mt": "Мальтийский", - "nl-be": "Голландский (Бельгия)", - "rm": "Ретороманский", - "sb": "Лужицкий", - "sk": "Словацкий", - "sl": "Словенский", - "sq": "Албанский", - "sr": "Сербский", - "sv-fi": "Шведский (Финляндия)", - "sz": "Сами (Саамы)", - "tn": "Тсвана", - "tr": "Турецкий", - "ts": "Тсонга", - "ur": "Урду", - "ve": "Венда", - "xh": "Кхоса", - "zh-cn": "Китайский (КНР)", - "zh-sg": "Китайский (Сингапур)", - "zh-tw": "Китайский (Тайвань)", - "zu": "Зулусский", - "eu": "Баскский", - "fr-lu": "Французский (Люксембург)", - "gd": "Гаэльский (Шотландия)", - "it-ch": "Итальянский (Швейцария)", - "ko": "Корейский", - "mk": "Македонский (БЮРМ)", - "ro-mo": "Румынский (Республика Молдова)", - "sx": "Суту", - "zh-hk": "Китайский (Гонконг)", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Текстовое сообщение было отправлено на +%(msisdn)s. Введите проверочный код, который оно содержит", "and %(count)s others...|other": "и %(count)s других...", "and %(count)s others...|one": "и ещё один...", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index c38aeec36e..202098ab0f 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -1,124 +1,4 @@ { - "af": "Afrikaans", - "ar-ae": "Arabiska (U.A.E.)", - "ar-bh": "Arabiska (Bahrain)", - "ar-dz": "Arabiska (Algeriet)", - "ar-eg": "Arabiska (Egypten)", - "ar-iq": "Arabiska (Irak)", - "ar-jo": "Arabiska (Jordanien)", - "ar-kw": "Arabiska (Kuwait)", - "ar-lb": "Arabiska (Libanon)", - "ar-ly": "Arabiska (Libyen)", - "ar-ma": "Arabiska (Marocko)", - "ar-om": "Arabiska (Oman)", - "ar-qa": "Arabiska (Qatar)", - "ar-sa": "Arabiska (Saudiarabien)", - "ar-sy": "Arabiska (Syrien)", - "ar-tn": "Arabiska (Tunisien)", - "ar-ye": "Arabiska (Yemen)", - "be": "Vitryska", - "bg": "Bulgariska", - "ca": "Katalanska", - "cs": "Tjeckiska", - "da": "Danska", - "de-at": "Tyska (Österrike)", - "de-ch": "Tyska (Schweiz)", - "de": "Tyska", - "de-li": "Tyska (Liechtenstein)", - "de-lu": "Tyska (Luxembourg)", - "el": "Grekiska", - "en-au": "Engelska (Australien)", - "en-bz": "Engelska (Belize)", - "en-ca": "Engelska (Kanada)", - "en": "Engelska", - "en-gb": "Engelska (Förenta kungariket)", - "en-ie": "Engelska (Irland)", - "en-jm": "Engelska (Jamaica)", - "en-nz": "Engelska (Nya Zeeland)", - "en-tt": "Engelska (Trinidad)", - "en-us": "Engelska (Förenta staterna)", - "en-za": "Engelska (Sydafrika)", - "es-ar": "Spanska (Argentina)", - "es-bo": "Spanska (Bolivia)", - "es-cl": "Spanska (Chile)", - "es-co": "Spanska (Colombia)", - "es-cr": "Spanska (Costa Rica)", - "es-do": "Spanska (Dominikanska republiken)", - "es-ec": "Spanska (Ecuador)", - "es-gt": "Spanska (Guatemala)", - "es-hn": "Spanska (Honduras)", - "es-mx": "Spanska (Mexico)", - "es-ni": "Spanska (Nicaragua)", - "es-pa": "Spanska (Panama)", - "es-pe": "Spanska (Peru)", - "es-pr": "Spanska (Puerto Rico)", - "es-py": "Spanska (Paraguay)", - "es": "Spanska (Spanien)", - "es-sv": "Spanska (El Salvador)", - "es-uy": "Spanska (Uruguay)", - "es-ve": "Spanska (Venezuela)", - "et": "Estniska", - "eu": "Baskiska", - "fa": "Persiska", - "fi": "Finska", - "fo": "Färöiska", - "fr-be": "Franska (Belgien)", - "fr-ca": "Franska (Kanada)", - "fr-ch": "Franska (Schweiz)", - "fr": "Franska", - "fr-lu": "Franska (Luxembourg)", - "ga": "Irländska", - "gd": "Gaeliska (Skottland)", - "he": "Hebreiska", - "hi": "Hindi", - "hr": "Kroatiska", - "hu": "Ungerska", - "id": "Indonesiska", - "is": "Isländska", - "it-ch": "Italienska (Schweiz)", - "it": "Italienska", - "ja": "Japanska", - "ji": "Jiddisch", - "ko": "Koreanska", - "lt": "Litauiska", - "lv": "Lettiska", - "mk": "Makedonska (FYROM)", - "ms": "Malaysiska", - "mt": "Maltesiska", - "nl-be": "Nederländska (Belgien)", - "nl": "Nederländska", - "no": "Norska", - "pl": "Polska", - "pt-br": "Brasiliansk portugisiska", - "pt": "Portugisiska", - "rm": "Rätoromanska", - "ro-mo": "Rumänska (Republiken Moldavien)", - "ro": "Rumänska", - "ru-mo": "Ryska (Republiken Moldavien)", - "ru": "Ryska", - "sb": "Sorbiska", - "sk": "Slovakiska", - "sl": "Slovenska", - "sq": "Albanska", - "sr": "Serbiska", - "sv-fi": "Svenska (Finland)", - "sv": "Svenska", - "sx": "Sutu", - "sz": "Samiska", - "th": "Thailändska", - "tn": "Tswana", - "tr": "Turkiska", - "ts": "Tsonga", - "uk": "Ukrainska", - "ur": "Urdu", - "ve": "Venda", - "vi": "Vietnamesiska", - "xh": "Xhosa", - "zh-cn": "Kinesiska (Folkrepubliken Kina)", - "zh-hk": "Kinesiska (Hongkong SAR)", - "zh-sg": "Kinesiska (Singapore)", - "zh-tw": "Kinesiska (Taiwan)", - "zu": "Zulu", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Ett SMS har skickats till +%(msisdn)s. Vänligen ange verifieringskoden ur meddelandet", "accept": "acceptera", "%(targetName)s accepted an invitation.": "%(targetName)s accepterade en inbjudan.", diff --git a/src/i18n/strings/te.json b/src/i18n/strings/te.json index a1487a594e..b3773d4449 100644 --- a/src/i18n/strings/te.json +++ b/src/i18n/strings/te.json @@ -1,89 +1,5 @@ { "was invited": "తనని ఆహ్వానించారు", - "ar-iq": "అరబిక్ (ఇరాక్)", - "ar-jo": "అరబిక్ (జోర్డాన్)", - "ar-kw": "అరబిక్ (కువైట్)", - "ar-lb": "అరబిక్ (లెబనాన్)", - "ar-ly": "అరబిక్ (లిబియా)", - "ar-ma": "అరబిక్ (మొరాకో)", - "ar-om": "అరబిక్ (ఒమన్)", - "ar-qa": "అరబిక్ (కతర్)", - "ar-sa": "అరబిక్ (సౌదీ అరేబియా)", - "ar-sy": "అరబిక్ (సిరియా)", - "ar-tn": "అరబిక్ (ట్యునీషియా)", - "ar-ye": "అరబిక్ (యెమెన్)", - "bg": "బల్గేరియన్", - "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": "స్పానిష్ (కోస్టా రికా)", - "af": "ఆఫ్రికాన్స్", - "ar-ae": "అరబిక్ (యు.ఏ.ఈ.)", - "ar-bh": "అరబిక్ (బహ్రెయిన్)", - "ar-dz": "అరబిక్ (అల్జీరియా)", - "ar-eg": "అరబిక్ (ఈజిప్ట్)", - "be": "భెలరుసీన్", - "ca": "కతలన్", - "cs": "ఛ్జెచ్", - "es-do": "స్పానిష్ (డొమినికన్ రిపబ్లిక్)", - "lt": "లిథూనీన్", - "lv": "లత్వీన్", - "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": "వెండా", - "vi": "వియత్నమెసె", - "xh": "షోసా", - "zh-cn": "చైనీస్ (ప్ ర్ సీ)", - "zh-hk": "చైనీస్ (హాంకాంగ్ స్ఎఅర్)", - "zh-sg": "చైనీస్ (సింగపూర్)", - "zh-tw": "చైనీస్ (తైవాన్)", - "zu": "జూలూ", "a room": "ఓ గది", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "ఒక టెక్స్ట్ సందేశం +%(msisdn)s కు పంపబడింది. దయచేసి దీనిలో ఉన్న ధృవీకరణ కోడ్ను నమోదు చేయండి", "Accept": "అంగీకరించు", @@ -114,39 +30,6 @@ "all room members": "అన్ని గదుల సభ్యులు", "You do not have permission to post to this room": "మీకు ఈ గదికి పోస్ట్ చేయడానికి అనుమతి లేదు", "You have been invited to join this room by %(inviterName)s": "%(inviterName)s ఈ గదిలో చేరడానికి మీరు ఆహ్వానించబడ్డారు", - "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": "స్పానిష్ (వెనిజులా)", - "eu": "బాస్క్ (బాస్క్)", - "fa": "ఫార్సి", - "fi": "ముగించు", - "fo": "ఫెరోయెస్", - "fr-be": "ఫ్రెంచ్ (బెల్జియం)", - "fr-ca": "ఫ్రెంచ్ (కెనడా)", - "fr-ch": "ఫ్రెంచ్ (స్విట్జర్లాండ్)", - "fr": "ఫ్రెంచ్", - "fr-lu": "ఫ్రెంచ్ (లక్సెంబర్గ్)", - "ga": "ఐరిష్", - "gd": "గేలిక్ (స్కాట్లాండ్)", - "he": "హిబ్రూ", - "hi": "హిందీ", - "hu": "హంగేరియన్", - "id": "ఇండోనేషియన్", - "is": "ఐస్లాండిక్", - "it-ch": "ఇటాలియన్ (స్విట్జర్లాండ్)", - "it": "ఇటాలియన్", - "ja": "జపనీస్", - "ko": "కొరియన్", "Active call (%(roomName)s)": "క్రియాశీల కాల్ల్ (%(roomName)s)", "And %(count)s more...": "మరియు %(count)s ఇంకా ...", "all room members, from the point they are invited": "అన్ని గది సభ్యులు, పాయింట్ నుండి వారు ఆహ్వానించబడ్డారు", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 3cf4355821..c27b6c0b7f 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -1,13 +1,4 @@ { - "de": "เยอร์มัน", - "en-us": "อังกฤษ (สหรัฐอเมริกา)", - "en": "อังกฤษ", - "en-ca": "อังกฤษ(แคนาดา)", - "ja": "ญี่ปุ่น", - "fr": "ฝรั่งเศส", - "ko": "เกาหลี", - "th": "ไทย", - "vi": "เวียดนาม", "accept": "ยอมรับ", "Account": "บัญชี", "Add phone number": "เพิ่มหมายเลขโทรศัพท์", @@ -474,115 +465,7 @@ "%(oneUser)sleft %(repeats)s times": "%(oneUser)sออกจากห้อง %(repeats)s ครั้ง", "%(severalUsers)sleft": "%(severalUsers)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", diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index fccef004dc..185dc788ec 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -1,124 +1,4 @@ { - "af": "Afrikanca (Taal)", - "ar-ae": "Arapça (B.A.E)", - "ar-bh": "Arapça (Bahreyn)", - "ar-dz": "Arapça (Cezayir)", - "ar-eg": "Arapça (Mısır)", - "ar-iq": "Arapça (Irak)", - "ar-jo": "Arapça (Ürdün)", - "ar-kw": "Arapça (Kuveyt)", - "ar-lb": "Arapça (Lübnan)", - "ar-ly": "Arapça (Libya)", - "ar-ma": "Arapça (Fas)", - "ar-om": "Arapça (Umman)", - "ar-qa": "Arapça (Katar)", - "ar-sa": "Arapça (Suudi Arabistan)", - "ar-sy": "Arapça (Suriye)", - "ar-tn": "Arapça (Tunus)", - "ar-ye": "Arapça (Yemen)", - "be": "Beyaz Rusça", - "bg": "Bulgarca", - "ca": "Katalanca", - "cs": "Çek Dili", - "da": "Danimarkaca", - "de-at": "Almanca (Avusturya)", - "de-ch": "Almanca (İsviçre)", - "de": "Almanca", - "de-li": "Almanca (Liechtenstein)", - "de-lu": "Almanca (Lüksemburg)", - "el": "Yunanca", - "en-au": "İngilizce (Avustralya)", - "en-bz": "İngilizce (Belize)", - "en-ca": "İngilizce (Kanada)", - "en": "İngilizce", - "en-gb": "İngilizce (İngiltere)", - "en-ie": "İngilizce (İrlanda)", - "en-jm": "İngilizce (Jamaika)", - "en-nz": "İngilizce (Yeni Zellanda)", - "en-tt": "İngilizce (Trinidad)", - "en-us": "İngilizce (Amerika)", - "en-za": "İngilizce (Güney Afrika)", - "es-ar": "İspanyolca (Arjantin)", - "es-bo": "İspanyolca (Bolivya)", - "es-cl": "İspanyolca (Şili)", - "es-co": "İspanyolca (Kolombiya)", - "es-cr": "İspanyolca (Kosta Rika)", - "es-do": "İspanyolca (Dominik Cumhuriyeti)", - "es-ec": "İspanyolca (Ekvador)", - "es-gt": "İspanyolca (Guatemala)", - "es-hn": "İspanyolca (Honduras)", - "es-mx": "İspanyolca (Meksika)", - "es-ni": "İspanyolca (Nikaragua)", - "es-pa": "İspanyolca (Panama)", - "es-pe": "İspanyolca (Peru)", - "es-pr": "İspanyolca (Porto Riko)", - "es-py": "İspanyolca (Paraguay)", - "es": "İspanyolca (İspanya)", - "es-sv": "İspanyolca (El Salvador)", - "es-uy": "İspanyolca (Uruguay)", - "es-ve": "İspanyolca (Venezuela)", - "et": "Estonya Dili", - "eu": "Baskça", - "fa": "Farsça", - "fi": "Fince", - "fo": "Faroe", - "fr-be": "Fransızca (Belçika)", - "fr-ca": "Fransızca (Kanada)", - "fr-ch": "Fransızca (İsviçre)", - "fr": "Fransızca", - "fr-lu": "Fransızca (Lüxemburg)", - "ga": "İrlandaca", - "gd": "Gaelik (İskoçya)", - "he": "İbranice", - "hi": "Hintçe", - "hr": "Hırvatça", - "hu": "Macarca", - "id": "Endonezya Dili", - "is": "İzlandaca", - "it-ch": "İtalyanca (İsviçre)", - "it": "İtalyanca", - "ja": "Japonca", - "ji": "Eskenazi Dili", - "ko": "Korece", - "lt": "Litvanya Dili", - "lv": "Letonya Dili", - "mk": "Makedonca (FYROM)", - "ms": "Malezyanca", - "mt": "Malta Dili", - "nl-be": "Hollandaca (Belçika)", - "nl": "Hollandaca", - "no": "Norveççe", - "pl": "Polonya Dili", - "pt-br": "Brezilya Portekizcesi", - "pt": "Portekizce", - "rm": "Reto-Latince", - "ro-mo": "Romence (Moldova Cumhuriyeti)", - "ro": "Romence", - "ru-mo": "Rusça (Moldova Cumhuriyeti)", - "ru": "Rusça", - "sb": "Sorbca", - "sk": "Slovakça", - "sl": "Slovence", - "sq": "Arnavutça", - "sr": "Sırpça", - "sv-fi": "İsveççe (Finlandiya)", - "sv": "İsveççe", - "sx": "Sutu Dili", - "sz": "Sami Dili", - "th": "Tayland Dili", - "tn": "Setsvana", - "tr": "Türkçe", - "ts": "Tsonga Dili", - "uk": "Ukraynaca", - "ur": "Urduca", - "ve": "Venda Dili", - "vi": "Vietnam Dili", - "xh": "Xhosa Dili", - "zh-cn": "Çince (PRC)", - "zh-hk": "Çince (Hong Kong)", - "zh-sg": "Çince (Singapur)", - "zh-tw": "Çince (Tayvan)", - "zu": "Zulu Dili", "a room": "bir oda", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "+%(msisdn)s 'ye bir kısa mesaj gönderildi . Lütfen içerdiği doğrulama kodunu girin", "Accept": "Kabul Et", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 15ddefc956..ed11668ddd 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -1,67 +1,4 @@ { - "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": "німецька", - "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": "фарерська", "Cancel": "Скасувати", "Close": "Закрити", "Create new room": "Створити нову кімнату", @@ -95,63 +32,6 @@ "Welcome page": "Ласкаво просимо", "Failed to change password. Is your password correct?": "Не вдалось змінити пароль. Ви впевнені, що пароль введено правильно?", "Continue": "Продовжити", - "fr-be": "французька (Бельгія)", - "fr-ca": "французька (Канада)", - "fr-ch": "французька (Швейцарія)", - "fr": "французька", - "fr-lu": "французька (Люксембург)", - "ga": "ірландська", - "gd": "гельська (Шотландія)", - "he": "іврит", - "hi": "гінді", - "hr": "хорватська", - "hu": "угорська", - "id": "індонезійська", - "is": "ісландська", - "it-ch": "італійська (Швейцарія)", - "it": "італійська", - "ja": "японська", - "ji": "ідиш", - "ko": "корейська", - "lt": "литовська", - "lv": "латвійська", - "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": "венда", - "vi": "в’єтнамська", - "xh": "коса", - "zh-cn": "спрощена китайська (КНР)", - "zh-hk": "традиційна китайська (Гонконг)", - "zh-sg": "спрощена китайська (Сингапур)", - "zh-tw": "традиційна китайська (Тайвань)", - "zu": "зулу", "a room": "кімната", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Текстове повідомлення було надіслано +%(msisdn)s. Введіть, будь ласка, код підтвердження з цього повідомлення", "Accept": "Прийняти", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index f8ee16f67e..417a47a79e 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -155,21 +155,6 @@ "The file '%(fileName)s' exceeds this home server's size limit for uploads": "文件 '%(fileName)s' 超过了此主服务器的上传大小限制", "The file '%(fileName)s' failed to upload": "文件 '%(fileName)s' 上传失败", "Disable URL previews for this room (affects only you)": "在这个房间禁止URL预览(只影响你)", - "af": "南非荷兰语", - "ca": "加泰罗尼亚语", - "cs": "捷克语", - "da": "丹麦语", - "de-at": "德语(奥地利)", - "de-ch": "德语(瑞士)", - "de": "德语", - "de-lu": "德语 (卢森堡)", - "el": "希腊语", - "en-au": "英语 (澳大利亚)", - "en": "英语", - "zh-cn": "中文(中国)", - "zh-hk": "中文(香港)", - "zh-sg": "中文(新加坡)", - "zh-tw": "中国(台湾)", "Add email address": "添加邮件地址", "Add phone number": "添加电话号码", "Advanced": "高级", @@ -206,21 +191,6 @@ "Leave room": "离开聊天室", "Login as guest": "以游客的身份登录", "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": "管理工具", @@ -371,15 +341,6 @@ "Friday": "星期五", "Saturday": "星期六", "Welcome page": "欢迎页面", - "ar-om": "阿拉伯语(阿曼)", - "ar-qa": "阿拉伯语(卡塔尔)", - "ar-sa": "阿拉伯语(沙特阿拉伯)", - "fi": "芬兰语", - "fr": "法语", - "he": "希伯来语", - "it": "意大利语", - "ja": "日语", - "ko": "韩语", "Account": "账户", "Add": "添加", "Allow": "允许", @@ -503,24 +464,6 @@ "Edit Group": "编辑群", "Failed to upload image": "上传图像失败", "Add a widget": "添加一个小部件", - "en-us": "英语(美国)", - "en-za": "英语(南非)", - "es-ar": "西班牙语(阿根廷)", - "es-cl": "西班牙语(智利)", - "es-co": "西班牙语(哥伦比亚)", - "es-cr": "西班牙语(哥斯达黎加)", - "es-mx": "西班牙语(墨西哥)", - "es": "西班牙语(西班牙)", - "fr-be": "法语(比利时)", - "fr-ca": "法语(加拿大)", - "fr-ch": "法语(瑞士)", - "hi": "印地语", - "hr": "克罗地亚语", - "hu": "匈牙利语", - "id": "印尼语", - "is": "冰岛语", - "it-ch": "意大利语(瑞士)", - "ji": "意第绪语", "a room": "一个聊天室", "Accept": "接受", "Access Token:": "访问令牌:", @@ -590,20 +533,6 @@ "I already have an account": "我已经有一个帐号", "Unblacklist": "移出黑名单", "Not a valid Riot keyfile": "不是一个合法的 Riot 密钥文件", - "en-jm": "英语(牙买加)", - "es-pe": "西班牙语(秘鲁)", - "lv": "拉脱维亚语", - "ms": "马来西亚语", - "pl": "波兰语", - "pt": "葡萄牙语", - "ro": "罗马尼亚语", - "ru": "俄语", - "sk": "斯洛伐克语", - "sl": "斯洛文尼亚语", - "sr": "塞尔维亚语", - "th": "泰语", - "tr": "土耳其语", - "vi": "越南语", "%(targetName)s accepted an invitation.": "%(targetName)s 接受了一个邀请。", "Do you want to load widget from URL:": "你想从此 URL 加载小组件吗:", "Hide join/leave messages (invites/kicks/bans unaffected)": "隐藏加入/离开消息(邀请/踢出/封禁不受影响)", @@ -620,55 +549,6 @@ "Seen by %(userName)s at %(dateTime)s": "在 %(dateTime)s 被 %(userName)s 看到", "Show Apps": "显示应用", "Tagged as: ": "标记为:", - "ar-sy": "阿拉伯语(Syria)", - "ar-tn": "阿拉伯语(Tunisia)", - "be": "白俄罗斯", - "bg": "保加利亚", - "de-li": "德语(列支敦士登)", - "en-bz": "英语(伯利兹)", - "en-tt": "英语(特立尼达)", - "es-bo": "西班牙语(玻利维亚)", - "es-do": "西班牙语(Dominican)", - "es-ec": "西班牙语(Ecuador)", - "es-gt": "西班牙语(Guatemala)", - "es-hn": "西班牙语(Honduras)", - "es-ni": "西班牙语(Nicaragua)", - "es-pa": "西班牙语(Panama)", - "es-pr": "西班牙语(Puerto Rico)", - "es-py": "西班牙语(Paraguay)", - "es-sv": "西班牙语(El Salvador)", - "es-uy": "西班牙语(Uruguay)", - "es-ve": "西班牙语(Venezuela)", - "et": "爱沙尼亚", - "eu": "巴斯克", - "fa": "波斯语", - "fo": "法罗群岛", - "fr-lu": "法语(Luxembourg)", - "ga": "爱尔兰", - "gd": "盖尔", - "lt": "立陶宛", - "mk": "马其顿", - "mt": "马耳他", - "nl-be": "荷兰语(Belgium)", - "nl": "荷兰语", - "no": "挪威", - "pt-br": "巴西葡萄牙语", - "rm": "瑞士南部", - "sb": "索布语", - "ru-mo": "俄语(Moldova)", - "ro-mo": "罗马尼亚(Moldova)", - "sq": "阿尔巴尼亚", - "sv-fi": "瑞典(Finland)", - "sv": "瑞典", - "sx": "苏图", - "sz": "萨米(Lappish)", - "tn": "茨瓦纳语", - "ts": "聪加", - "uk": "乌克兰", - "ur": "乌尔都语", - "ve": "文达", - "xh": "科萨", - "zu": "祖鲁语", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "验证码将发送到+%(msisdn),请输入接收到的验证码", "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName) 接受了 %(displayName)的邀请。", "Active call (%(roomName)s)": "%(roomName)的呼叫", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 028336f3be..5027f2c28e 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -21,73 +21,6 @@ "Can't load user settings": "無法載入使用者設定", "Change Password": "變更密碼", "%(targetName)s left the room.": "%(targetName)s 離開了聊天室。.", - "af": "南非荷蘭語", - "ar-ae": "阿拉伯語 (U.A.E.)", - "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": "德語", - "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": "西班牙語 (委內瑞拉)", - "fr-be": "法語 (比利時)", - "fr-ca": "法語 (加拿大)", - "fr-ch": "法語 (瑞士)", - "fr": "法語 (法國)", - "fr-lu": "法語 (慮森堡)", - "zh-cn": "中文(中國)", - "zh-hk": "中文(香港)", - "zh-sg": "中文(新加坡)", - "zh-tw": "中文(台灣)", - "zu": "祖魯語", "accept": "接受", "Account": "帳號", "Access Token:": "取用令牌:", @@ -366,59 +299,6 @@ "Room directory": "聊天室目錄", "Start chat": "開始聊天", "Welcome page": "歡迎頁面", - "de-li": "德語(列支敦斯登)", - "et": "愛沙尼亞語", - "eu": "巴斯克語(巴斯克)", - "fa": "波斯語", - "fi": "芬蘭語", - "fo": "法羅語", - "ga": "愛爾蘭語", - "gd": "蓋爾語(蘇格蘭)", - "he": "希伯來語", - "hi": "印地語", - "hr": "克羅埃西亞語", - "hu": "匈牙利語", - "id": "印尼語", - "is": "冰島語", - "it-ch": "義大利語(瑞士)", - "it": "義大利語", - "ja": "日語", - "ji": "意第緒語", - "ko": "韓語", - "lt": "立陶宛語", - "lv": "拉脫維亞語", - "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": "文達語", - "vi": "越南語", - "xh": "科薩語", "a room": "房間", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "文字訊息將會傳送到 +%(msisdn)s。請輸入其中包含的驗證碼", "Accept": "接受", From 7ba8aa95c5485468850f50f59075e1ac275dec17 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Tue, 5 Sep 2017 18:00:57 +0200 Subject: [PATCH 13/43] readd translations that got removed by accident --- src/i18n/strings/pt_BR.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 18294eae55..6b06f39e7c 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -392,6 +392,8 @@ "Usage": "Uso", "Use with caution": "Use com cautela", "VoIP is unsupported": "Chamada de voz não permitida", + "Sunday": "Domingo", + "Monday": "Segunda", "%(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 to make a room or to browse the directory": "Você ainda não está em nenhuma sala! Clique em para criar uma sala ou em para navegar pela lista pública de salas", From 5449224dec750b98203db04a65636b31b4d6e4ea Mon Sep 17 00:00:00 2001 From: MTRNord Date: Tue, 5 Sep 2017 18:01:57 +0200 Subject: [PATCH 14/43] readd translations that got removed by accident 2 --- src/i18n/strings/nl.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index bc92d7bcad..ac2f3e0e58 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -1,4 +1,5 @@ { + "Direct Chat": "Privégesprek", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains": "Voer alsjeblieft de verificatiecode in die is verstuurd naar +%(msisdn)s", "accept": "accepteer", "%(targetName)s accepted an invitation.": "%(targetName)s heeft een uitnodiging geaccepteerd.", From a573a396ad3ca2b90693b1c9db3020398ff19681 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 5 Sep 2017 18:07:22 +0200 Subject: [PATCH 15/43] Remove unused string "changing room on a RoomView is not supported" --- 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 c1ba1d0c74..fec3e83616 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -201,7 +201,6 @@ "Changes to who can read history will only apply to future messages in this room": "Changes to who can read history will only apply to future messages in this room", "Changes your display nickname": "Changes your display nickname", "Changes colour scheme of current room": "Changes colour scheme of current room", - "changing room on a RoomView is not supported": "changing room on a RoomView is not supported", "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.": "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.", "Claimed Ed25519 fingerprint key": "Claimed Ed25519 fingerprint key", "Clear Cache and Reload": "Clear Cache and Reload", From da3336172f0f088c48229d8116cb3ec575506b75 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Tue, 5 Sep 2017 18:12:00 +0200 Subject: [PATCH 16/43] Remove more unused translation strings --- src/i18n/strings/de_DE.json | 1 - src/i18n/strings/el.json | 1 - src/i18n/strings/en_US.json | 1 - src/i18n/strings/es.json | 1 - src/i18n/strings/eu.json | 1 - src/i18n/strings/fr.json | 1 - src/i18n/strings/hu.json | 1 - src/i18n/strings/id.json | 1 - src/i18n/strings/ko.json | 1 - src/i18n/strings/lv.json | 1 - src/i18n/strings/nl.json | 1 - src/i18n/strings/pt.json | 1 - src/i18n/strings/pt_BR.json | 1 - src/i18n/strings/ru.json | 1 - src/i18n/strings/sv.json | 1 - src/i18n/strings/te.json | 1 - src/i18n/strings/th.json | 1 - src/i18n/strings/tr.json | 1 - src/i18n/strings/zh_Hant.json | 1 - 19 files changed, 19 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 2fbee2717d..020a13c98d 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -561,7 +561,6 @@ "Ban": "Dauerhaft aus dem Raum ausschließen", "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.": "Es kann keine Verbindung zum Heimserver via HTTP aufgebaut werden, wenn die Adresszeile des Browsers eine HTTPS-URL enthält. Entweder HTTPS verwenden oder alternativ unsichere Skripte erlauben.", - "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", "Click to mute video": "Klicken, um das Video stummzuschalten", "Command error": "Befehlsfehler", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 3ea83a322c..974ca37c5b 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -849,7 +849,6 @@ "You must join the room to see its files": "Πρέπει να συνδεθείτε στο δωμάτιο για να δείτε τα αρχεία του", "Reject all %(invitedRooms)s invites": "Απόρριψη όλων των προσκλήσεων %(invitedRooms)s", "Failed to invite the following users to the %(roomName)s room:": "Δεν ήταν δυνατή η πρόσκληση των χρηστών στο δωμάτιο %(roomName)s:", - "changing room on a RoomView is not supported": "Δεν υποστηρίζεται η αλλαγή δωματίου σε RoomView", "demote": "υποβίβαση", "Deops user with given id": "Deop χρήστη με το συγκεκριμένο αναγνωριστικό", "Disable inline URL previews by default": "Απενεργοποίηση προεπισκόπησης συνδέσμων από προεπιλογή", diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index a68ce5d982..cb528e1e22 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -195,7 +195,6 @@ "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s changed the topic to \"%(topic)s\".", "Changes to who can read history will only apply to future messages in this room": "Changes to who can read history will only apply to future messages in this room", "Changes your display nickname": "Changes your display nickname", - "changing room on a RoomView is not supported": "changing room on a RoomView is not supported", "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.": "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.", "Claimed Ed25519 fingerprint key": "Claimed Ed25519 fingerprint key", "Clear Cache and Reload": "Clear Cache and Reload", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 96a986decc..b90a58a245 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -178,7 +178,6 @@ "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s ha cambiado el tema de la sala a \"%(topic)s\".", "Changes to who can read history will only apply to future messages in this room": "Cambios para quien pueda leer el historial solo serán aplicados a futuros mensajes en la sala", "Changes your display nickname": "Cambia la visualización de tu apodo", - "changing room on a RoomView is not supported": "cambiando la sala en un RoomView no esta soportado", "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.": "El cambio de contraseña restablecerá actualmente todas las claves de cifrado de extremo a extremo de todos los dispositivos, haciendo que el historial de chat cifrado sea ilegible, a menos que primero exporte las claves de la habitación y vuelva a importarlas después. En el futuro esto será mejorado.", "Claimed Ed25519 fingerprint key": "Clave Ed25519 es necesaria", "Clear Cache and Reload": "Borrar caché y recargar", diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index 308fa36900..09d10368ff 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -436,7 +436,6 @@ "%(senderName)s changed their profile picture.": "%(senderName)s erabiltzaileak bere profileko argazkia aldatu du.", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s erabiltzaileak %(powerLevelDiffText)s erabiltzailearen botere maila aldatu du.", "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s erabiltzaileak gelaren izena aldatu du, orain %(roomName)s da.", - "changing room on a RoomView is not supported": "ez da onartzen gela ikuspegi batean gelaz aldatzea", "Drop here to tag %(section)s": "Jaregin hona %(section)s atalari etiketa jartzeko", "Incoming voice call from %(name)s": "%(name)s erabiltzailearen deia jasotzen", "Incorrect username and/or password.": "Erabiltzaile-izen edo pasahitz okerra.", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 50d9113245..99df78ac34 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -574,7 +574,6 @@ "You seem to be in a call, are you sure you want to quit?": "Vous semblez avoir un appel en cours, êtes-vous sûr(e) de vouloir quitter ?", "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 annuler ce changement car vous promouvez l’utilisateur au même niveau d'autorité que le vôtre.", "Sun": "Dim", "Mon": "Lun", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 7c38e41c9b..d6eab3fa87 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -229,7 +229,6 @@ "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s megváltoztatta a témát erre \"%(topic)s\".", "Changes to who can read history will only apply to future messages in this room": "Változtatások a napló olvasási jogosultságon csak a szoba új üzeneteire fog vonatkozni", "Changes your display nickname": "Becenév megváltoztatása", - "changing room on a RoomView is not supported": "Szoba nézetben nem lehet szobát váltani", "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.": "Jelszó megváltoztatása jelenleg alaphelyzetbe állítja a titkosításnál használt kulcsokat minden készüléken, ezzel a régi titkosított üzenetek olvashatatlanok lesznek hacsak először nem mented ki a kulcsokat és újra betöltöd. A jövőben ezen javítunk.", "Claimed Ed25519 fingerprint key": "Igényelt Ed25519 ujjlenyomat kulcs", "Clear Cache and Reload": "Gyorsítótár törlése és újratöltés", diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index a4edd6892d..2e08aedf4a 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -214,7 +214,6 @@ "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s telah mengubah nama ruang menjadi %(roomName)s.", "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s telah mengubah topik menjadi \"%(topic)s\".", "Changes to who can read history will only apply to future messages in this room": "Pengubahan siapa yang dapat membaca sejarah akan berlaku untuk pesan selanjutnya di ruang ini", - "changing room on a RoomView is not supported": "tidak dapat mengubah ruang di RoomView", "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.": "Mengubah password saat ini akan mengatur ulang semua kunci enkripsi end-to-end di semua perangkat, menyebabkan sejarah obrolan yang terenkripsi menjadi tidak dapat dibaca, kecuali sebelumnya Anda ekspor dahulu kunci ruang lalu kemudian impor ulang setelahnya. Ke depan hal ini akan diperbaiki.", "Click here to join the discussion!": "Klik di sini untuk gabung diskusi!", "click to reveal": "Klik untuk menampilkan", diff --git a/src/i18n/strings/ko.json b/src/i18n/strings/ko.json index 411d1ccfe1..547bc7ff48 100644 --- a/src/i18n/strings/ko.json +++ b/src/i18n/strings/ko.json @@ -250,7 +250,6 @@ "%(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": "방의 이후 메시지부터 기록을 읽을 수 있는 조건의 변화가 적용되어요", - "changing room on a RoomView is not supported": "룸뷰에서 방을 바꾸는 건 지원하지 않아요", "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.": "비밀번호를 바꾸면 현재 모든 장치의 종단간 암호화 키가 다시 설정되고, 먼저 방의 키를 내보내고 나중에 다시 불러오지 않는 한, 암호화한 이야기 기록을 읽을 수 없게 되어요. 앞으로는 이 기능을 더 좋게 만들 거에요.", "Claimed Ed25519 fingerprint key": "Ed25519 지문 키가 필요", "Click here to join the discussion!": "여기를 눌러서 같이 논의해요!", diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index c2a55b3fc2..3c7c4ea733 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -195,7 +195,6 @@ "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s nomainīja tēmas nosaukumu uz \"%(topic)s\".", "Changes to who can read history will only apply to future messages in this room": "Izmaiņas attiecībā uz to, kurš varēs lasīt vēstures ziņas, stāsies spēkā tikai uz ziņām,kuras vēl tiks pievienotas šajā istabā", "Changes your display nickname": "Nomaina tavu publisko segvārdu (niku)", - "changing room on a RoomView is not supported": "istabas maiņa nav iespējama, atrodoties istabu skata lapā", "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.": "Paroles maiņa dzēsīs pašreizējās šifrēšanas atslēgas visās savstarpēji saistītajās ierīcēs, padarot čata vēsturi neizlasāmu, ja vien vien istabas atslēgas nav tikušas iepriekš eksportētas un no jauna importētas atpakaļ. Nākotnē to plānojam uzlabot.", "Claimed Ed25519 fingerprint key": "Norādīta Ed25519 identificējošās zīmju virknes atslēga", "Clear Cache and Reload": "Iztīri kešatmiņu un pārlādē", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 234fc8c03a..6c72f4ee14 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -179,7 +179,6 @@ "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s heeft het onderwerp gewijzigd naar \"%(topic)s\".", "Changes to who can read history will only apply to future messages in this room": "Veranderingen aan wie de historie kan lezen worden alleen maar toegepast op toekomstige berichten in deze kamer", "Changes your display nickname": "Verandert jouw weergavenaam", - "changing room on a RoomView is not supported": "veranderen van een kamer in een RoomView wordt niet ondersteund", "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.": "Het veranderen van het wachtwoord zal op het moment alle eind-tot-eind encryptie sleutels resetten, wat alle versleutelde chat geschiedenis onleesbaar zou maken, behalve als je eerst je kamer sleutels exporteert en achteraf opnieuw importeert. Dit zal worden verbeterd in de toekomst.", "Clear Cache and Reload": "Legen cache en herlaad", "Clear Cache": "Legen cache", diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 827efeb16a..fdbf9ebfd9 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -571,7 +571,6 @@ "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Não consigo conectar ao servidor padrão - favor checar sua conexão à internet e verificar se o certificado SSL do seu servidor padrão é confiável.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Não consigo conectar ao servidor padrão através de HTTP quando uma URL HTTPS está na barra de endereços do seu navegador. Use HTTPS ou então habilite scripts não seguros no seu navegador.", "Change Password": "Alterar senha", - "changing room on a RoomView is not supported": "mudar a sala em uma 'RoomView' não é permitido", "Click to mute audio": "Clique para colocar o áudio no mudo", "Click to mute video": "Clique para desabilitar imagens de vídeo", "Click to unmute video": "Clique para voltar a mostrar imagens de vídeo", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 7e7ca123b9..4779aada14 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -572,7 +572,6 @@ "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Não consigo conectar ao servidor padrão - favor checar sua conexão à internet e verificar se o certificado SSL do seu servidor padrão é confiável.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Não consigo conectar ao servidor padrão através de HTTP quando uma URL HTTPS está na barra de endereços do seu navegador. Use HTTPS ou então habilite scripts não seguros no seu navegador.", "Change Password": "Alterar senha", - "changing room on a RoomView is not supported": "mudar a sala em uma 'RoomView' não é permitido", "Click to mute audio": "Clique para colocar o áudio no mudo", "Click to mute video": "Clique para desabilitar imagens de vídeo", "Click to unmute video": "Clique para voltar a mostrar imagens de vídeo", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 3f3403d716..aee4ec9b30 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -455,7 +455,6 @@ "Are you sure?": "Вы уверены?", "Autoplay GIFs and videos": "Автовоспроизведение GIF и видео", "Can't connect to homeserver - please check your connectivity and ensure your homeserver's SSL certificate is trusted.": "Невозможно соединиться с домашним сервером - проверьте своё соединение и убедитесь, что SSL-сертификат вашего домашнего сервера включён в доверяемые.", - "changing room on a RoomView is not supported": "изменение комнаты в RoomView не поддерживается", "Click to mute audio": "Щелкните, чтобы выключить звук", "Click to mute video": "Щелкните, чтобы выключить видео", "Click to unmute video": "Щелкните, чтобы включить видео", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index d3b512900c..e28ab4ebbc 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -302,7 +302,6 @@ "Alias (optional)": "Alias (valfri)", "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.": "Det gick inte att ansluta till servern - kontrollera anslutningen, försäkra att din hemservers TLS-certifikat är betrott, och att inget webbläsartillägg blockerar förfrågningar.", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s ändrade maktnivån av %(powerLevelDiffText)s.", - "changing room on a RoomView is not supported": "det går inte att byta rum i en RoomView", "Click here to join the discussion!": "Klicka här för att gå med i diskussionen!", "Close": "Stäng", "%(count)s new messages.one": "%(count)s nytt meddelande", diff --git a/src/i18n/strings/te.json b/src/i18n/strings/te.json index 0f1d5b9a6d..3dcb6d5a1f 100644 --- a/src/i18n/strings/te.json +++ b/src/i18n/strings/te.json @@ -183,7 +183,6 @@ "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s గది పేరు తొలగించబడింది.", "Changes to who can read history will only apply to future messages in this room": "చరిత్ర చదివేవారికి మార్పులు ఈ గదిలో భవిష్య సందేశాలకు మాత్రమే వర్తిస్తాయి", "Changes your display nickname": "మీ ప్రదర్శన మారుపేరుని మారుస్తుంది", - "changing room on a RoomView is not supported": "ఒక రూమ్వ్యూలో గది మార్చుకునేకి మద్దతు లేదు", "You cannot place a call with yourself.": "మీరు మీతో కాల్ చేయలేరు.", "You are already in a call.": "మీరు ఇప్పటికే కాల్లో ఉన్నారు.", "You are trying to access %(roomName)s.": "మీరు %(roomName)s లను యాక్సెస్ చేయడానికి ప్రయత్నిస్తున్నారు.", diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json index 01ffa729d7..cbb0bd9f49 100644 --- a/src/i18n/strings/th.json +++ b/src/i18n/strings/th.json @@ -126,7 +126,6 @@ "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s เปลี่ยนชื่อห้องไปเป็น %(roomName)s", "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s ลบชื่อห้อง", "Changes your display nickname": "เปลี่ยนชื่อเล่นที่แสดงของคุณ", - "changing room on a RoomView is not supported": "ไม่รองรับการเปลี่ยนห้องใน RoomView", "Clear Cache and Reload": "ล้างแคชแล้วโหลดใหม่", "Clear Cache": "ล้างแคช", "Click here": "คลิกที่นี่", diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index 2933e2433b..8d6d607b0d 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -197,7 +197,6 @@ "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s konuyu \"%(topic)s\" olarak değiştirdi.", "Changes to who can read history will only apply to future messages in this room": "Geçmişi kimlerin okuyabileceğine ait değişiklikler yalnızca bu odada gelecekteki iletiler için geçerli olur", "Changes your display nickname": "Görünen takma adınızı değiştirir", - "changing room on a RoomView is not supported": "Oda Ekranında oda değiştirme desteklenmiyor", "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.": "Şifre değiştirme eğer oda anahtarlarınızı dışa aktarmaz ve daha sonra tekrar içe aktarmazsanız , şu anda tüm cihazlarda uçtan uca şifreleme anahtarlarını sıfırlayacak ve geçmişi okunamaz hale getirecek . Gelecekte bu geliştirilecek.", "Claimed Ed25519 fingerprint key": "Ed25519 parmak izi anahtarı istendi", "Clear Cache and Reload": "Önbelleği Temizle ve Yeniden Yükle", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 93ac57330a..5e8f8ddc99 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -448,7 +448,6 @@ "%(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 room on a RoomView is not supported": "不支援在房間檢視時變更房間", "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.": "目前變更密碼將會重設在所有裝置上的端對端加密金鑰,讓加密的聊天歷史無法讀取,除非您先匯出您的房間金鑰,並在稍後重新匯入它們。這會在未來改進。", "Claimed Ed25519 fingerprint key": "已索取 Ed25519 指紋金鑰", "Clear Cache and Reload": "清除快取並重新載入", From 738c81b5062f162d709a5308b9d689e1f2230d9b Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 5 Sep 2017 17:36:41 +0100 Subject: [PATCH 17/43] Add missing translations --- src/i18n/strings/en_EN.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index d260548e45..8c0f3c8db7 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -597,6 +597,8 @@ "Dec": "Dec", "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s, %(monthName)s %(day)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, %(monthName)s %(day)s": "%(weekDayName)s, %(monthName)s %(day)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)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", From 9dd98d1085dbd807742613934e4d722890884d63 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 6 Sep 2017 13:25:57 +0100 Subject: [PATCH 18/43] Prepare changelog for v0.10.3 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af82ef2e1f..090f5a49da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in [0.10.3](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.3) (2017-09-06) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.3-rc.2...v0.10.3) + + * No changes + Changes in [0.10.3-rc.2](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v0.10.3-rc.2) (2017-09-05) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v0.10.3-rc.1...v0.10.3-rc.2) From f5cf2aece2ac39a172b2b08adc6b66c006c4790c Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 6 Sep 2017 13:25:58 +0100 Subject: [PATCH 19/43] v0.10.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1fbfb58d7..38a647ff67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "0.10.3-rc.2", + "version": "0.10.3", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 609d61d53c55eae0660fb01724bb51518ec5f46c Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 6 Sep 2017 17:40:58 +0100 Subject: [PATCH 20/43] Revert "Implement sticky date separators" --- package.json | 1 - src/DateUtils.js | 44 --- src/components/structures/MessagePanel.js | 9 +- src/components/structures/ScrollPanel.js | 278 +++++++++--------- src/components/structures/TimelinePanel.js | 1 + .../structures/TimelinePanel-test.js | 3 + 6 files changed, 143 insertions(+), 193 deletions(-) diff --git a/package.json b/package.json index bb7f33492d..38a647ff67 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "react-addons-css-transition-group": "15.3.2", "react-dom": "^15.4.0", "react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef", - "react-sticky": "^6.0.1", "sanitize-html": "^1.14.1", "text-encoding-utf-8": "^1.0.1", "url": "^0.11.0", diff --git a/src/DateUtils.js b/src/DateUtils.js index e7be394c17..78eef57eae 100644 --- a/src/DateUtils.js +++ b/src/DateUtils.js @@ -30,18 +30,6 @@ function getDaysArray() { ]; } -function getLongDaysArray() { - return [ - _t('Sunday'), - _t('Monday'), - _t('Tuesday'), - _t('Wednesday'), - _t('Thursday'), - _t('Friday'), - _t('Saturday'), - ]; -} - function getMonthsArray() { return [ _t('Jan'), @@ -108,38 +96,6 @@ module.exports = { }); }, - formatDateSeparator: function(date) { - const days = getDaysArray(); - const longDays = getLongDaysArray(); - const months = getMonthsArray(); - - const today = new Date(); - const yesterday = new Date(); - yesterday.setDate(today.getDate() - 1); - - if (date.toDateString() === today.toDateString()) { - return _t('Today'); - } else if (date.toDateString() === yesterday.toDateString()) { - return _t('Yesterday'); - } else if (today.getTime() - date.getTime() < 6 * 24 * 60 * 60 * 1000) { - return longDays[date.getDay()]; - } else if (today.getTime() - date.getTime() < 365 * 24 * 60 * 60 * 1000) { - return _t('%(weekDayName)s, %(monthName)s %(day)s', { - weekDayName: days[date.getDay()], - monthName: months[date.getMonth()], - day: date.getDate(), - fullYear: date.getFullYear(), - }); - } else { - return _t('%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s', { - weekDayName: days[date.getDay()], - monthName: months[date.getMonth()], - day: date.getDate(), - fullYear: date.getFullYear(), - }); - } - }, - formatTime: function(date, showTwelveHour=false) { if (showTwelveHour) { return twelveHourTime(date); diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index aad4e1957a..e5884973c6 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -61,6 +61,9 @@ module.exports = React.createClass({ // for pending messages. ourUserId: React.PropTypes.string, + // true to suppress the date at the start of the timeline + suppressFirstDateSeparator: React.PropTypes.bool, + // whether to show read receipts showReadReceipts: React.PropTypes.bool, @@ -514,10 +517,10 @@ module.exports = React.createClass({ _wantsDateSeparator: function(prevEvent, nextEventDate) { if (prevEvent == null) { - // First event in the panel always wants a DateSeparator - return true; + // first event in the panel: depends if we could back-paginate from + // here. + return !this.props.suppressFirstDateSeparator; } - const prevEventDate = prevEvent.getDate(); if (!nextEventDate || !prevEventDate) { return false; diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 3ea699798e..a8a2ec181b 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -17,7 +17,6 @@ limitations under the License. var React = require("react"); var ReactDOM = require("react-dom"); var GeminiScrollbar = require('react-gemini-scrollbar'); -import { StickyContainer } from 'react-sticky'; import Promise from 'bluebird'; var KeyCode = require('../../KeyCode'); @@ -78,52 +77,111 @@ if (DEBUG_SCROLL) { * scroll down further. If stickyBottom is disabled, we just save the scroll * offset as normal. */ -export default class ScrollPanel extends StickyContainer { +module.exports = React.createClass({ + displayName: 'ScrollPanel', - constructor() { - super(); - this.onResize = this.onResize.bind(this); - this.onScroll = this.onScroll.bind(this); - } + propTypes: { + /* stickyBottom: if set to true, then once the user hits the bottom of + * the list, any new children added to the list will cause the list to + * scroll down to show the new element, rather than preserving the + * existing view. + */ + stickyBottom: React.PropTypes.bool, - componentWillMount() { + /* startAtBottom: if set to true, the view is assumed to start + * scrolled to the bottom. + * XXX: It's likley this is unecessary and can be derived from + * stickyBottom, but I'm adding an extra parameter to ensure + * behaviour stays the same for other uses of ScrollPanel. + * If so, let's remove this parameter down the line. + */ + startAtBottom: React.PropTypes.bool, + + /* onFillRequest(backwards): a callback which is called on scroll when + * the user nears the start (backwards = true) or end (backwards = + * false) of the list. + * + * This should return a promise; no more calls will be made until the + * promise completes. + * + * The promise should resolve to true if there is more data to be + * retrieved in this direction (in which case onFillRequest may be + * called again immediately), or false if there is no more data in this + * directon (at this time) - which will stop the pagination cycle until + * the user scrolls again. + */ + onFillRequest: React.PropTypes.func, + + /* onUnfillRequest(backwards): a callback which is called on scroll when + * there are children elements that are far out of view and could be removed + * without causing pagination to occur. + * + * This function should accept a boolean, which is true to indicate the back/top + * of the panel and false otherwise, and a scroll token, which refers to the + * first element to remove if removing from the front/bottom, and last element + * to remove if removing from the back/top. + */ + onUnfillRequest: React.PropTypes.func, + + /* onScroll: a callback which is called whenever any scroll happens. + */ + onScroll: React.PropTypes.func, + + /* onResize: a callback which is called whenever the Gemini scroll + * panel is resized + */ + onResize: React.PropTypes.func, + + /* className: classnames to add to the top-level div + */ + className: React.PropTypes.string, + + /* style: styles to add to the top-level div + */ + style: React.PropTypes.object, + }, + + getDefaultProps: function() { + return { + stickyBottom: true, + startAtBottom: true, + onFillRequest: function(backwards) { return Promise.resolve(false); }, + onUnfillRequest: function(backwards, scrollToken) {}, + onScroll: function() {}, + }; + }, + + componentWillMount: function() { this._pendingFillRequests = {b: null, f: null}; this.resetScrollState(); - } + }, - componentDidMount() { + componentDidMount: function() { this.checkFillState(); - } + }, - componentDidUpdate() { + componentDidUpdate: function() { // after adding event tiles, we may need to tweak the scroll (either to // keep at the bottom of the timeline, or to maintain the view after // adding events to the top). // // This will also re-check the fill state, in case the paginate was inadequate this.checkScroll(); - } + }, - componentWillUnmount() { + componentWillUnmount: function() { // set a boolean to say we've been unmounted, which any pending // promises can use to throw away their results. // // (We could use isMounted(), but facebook have deprecated that.) this.unmounted = true; - } + }, - onScroll(ev) { + onScroll: function(ev) { var sn = this._getScrollNode(); debuglog("Scroll event: offset now:", sn.scrollTop, "_lastSetScroll:", this._lastSetScroll); - // Set the node and notify subscribers of the StickyContainer - // By extending StickyContainer, we can set the scroll node to be that of the - // ScrolPanel to allow any `` children to be sticky, namely DateSeparators. - this.node = sn; - // Update subscribers - arbitrarily nested `` children - this.notifySubscribers(ev); - // Sometimes we see attempts to write to scrollTop essentially being // ignored. (Or rather, it is successfully written, but on the next // scroll event, it's been reset again). @@ -159,27 +217,27 @@ export default class ScrollPanel extends StickyContainer { this.props.onScroll(ev); this.checkFillState(); - } + }, - onResize() { + onResize: function() { this.props.onResize(); this.checkScroll(); this.refs.geminiPanel.forceUpdate(); - } + }, // after an update to the contents of the panel, check that the scroll is // where it ought to be, and set off pagination requests if necessary. - checkScroll() { + checkScroll: function() { this._restoreSavedScrollState(); this.checkFillState(); - } + }, // return true if the content is fully scrolled down right now; else false. // // note that this is independent of the 'stuckAtBottom' state - it is simply // about whether the the content is scrolled down right now, irrespective of // whether it will stay that way when the children update. - isAtBottom() { + isAtBottom: function() { var sn = this._getScrollNode(); // there seems to be some bug with flexbox/gemini/chrome/richvdh's @@ -189,7 +247,7 @@ export default class ScrollPanel extends StickyContainer { // that we're at the bottom when we're still a few pixels off. return sn.scrollHeight - Math.ceil(sn.scrollTop) <= sn.clientHeight + 3; - } + }, // returns the vertical height in the given direction that can be removed from // the content box (which has a height of scrollHeight, see checkFillState) without @@ -222,17 +280,17 @@ export default class ScrollPanel extends StickyContainer { // |#########| - | // |#########| | // `---------' - - _getExcessHeight(backwards) { + _getExcessHeight: function(backwards) { var sn = this._getScrollNode(); if (backwards) { return sn.scrollTop - sn.clientHeight - UNPAGINATION_PADDING; } else { return sn.scrollHeight - (sn.scrollTop + 2*sn.clientHeight) - UNPAGINATION_PADDING; } - } + }, // check the scroll state and send out backfill requests if necessary. - checkFillState() { + checkFillState: function() { if (this.unmounted) { return; } @@ -271,10 +329,10 @@ export default class ScrollPanel extends StickyContainer { // need to forward-fill this._maybeFill(false); } - } + }, // check if unfilling is possible and send an unfill request if necessary - _checkUnfillState(backwards) { + _checkUnfillState: function(backwards) { let excessHeight = this._getExcessHeight(backwards); if (excessHeight <= 0) { return; @@ -315,10 +373,10 @@ export default class ScrollPanel extends StickyContainer { this.props.onUnfillRequest(backwards, markerScrollToken); }, UNFILL_REQUEST_DEBOUNCE_MS); } - } + }, // check if there is already a pending fill request. If not, set one off. - _maybeFill(backwards) { + _maybeFill: function(backwards) { var dir = backwards ? 'b' : 'f'; if (this._pendingFillRequests[dir]) { debuglog("ScrollPanel: Already a "+dir+" fill in progress - not starting another"); @@ -350,7 +408,7 @@ export default class ScrollPanel extends StickyContainer { this.checkFillState(); } }).done(); - } + }, /* get the current scroll state. This returns an object with the following * properties: @@ -366,9 +424,9 @@ export default class ScrollPanel extends StickyContainer { * the number of pixels the bottom of the tracked child is above the * bottom of the scroll panel. */ - getScrollState() { + getScrollState: function() { return this.scrollState; - } + }, /* reset the saved scroll state. * @@ -382,46 +440,46 @@ export default class ScrollPanel extends StickyContainer { * no use if no children exist yet, or if you are about to replace the * child list.) */ - resetScrollState() { + resetScrollState: function() { this.scrollState = {stuckAtBottom: this.props.startAtBottom}; - } + }, /** * jump to the top of the content. */ - scrollToTop() { + scrollToTop: function() { this._setScrollTop(0); this._saveScrollState(); - } + }, /** * jump to the bottom of the content. */ - scrollToBottom() { + scrollToBottom: function() { // the easiest way to make sure that the scroll state is correctly // saved is to do the scroll, then save the updated state. (Calculating // it ourselves is hard, and we can't rely on an onScroll callback // happening, since there may be no user-visible change here). this._setScrollTop(Number.MAX_VALUE); this._saveScrollState(); - } + }, /** * Page up/down. * * mult: -1 to page up, +1 to page down */ - scrollRelative(mult) { + scrollRelative: function(mult) { var scrollNode = this._getScrollNode(); var delta = mult * scrollNode.clientHeight * 0.5; this._setScrollTop(scrollNode.scrollTop + delta); this._saveScrollState(); - } + }, /** * Scroll up/down in response to a scroll key */ - handleScrollKey(ev) { + handleScrollKey: function(ev) { switch (ev.keyCode) { case KeyCode.PAGE_UP: if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { @@ -447,7 +505,7 @@ export default class ScrollPanel extends StickyContainer { } break; } - } + }, /* Scroll the panel to bring the DOM node with the scroll token * `scrollToken` into view. @@ -460,7 +518,7 @@ export default class ScrollPanel extends StickyContainer { * node (specifically, the bottom of it) will be positioned. If omitted, it * defaults to 0. */ - scrollToToken(scrollToken, pixelOffset, offsetBase) { + scrollToToken: function(scrollToken, pixelOffset, offsetBase) { pixelOffset = pixelOffset || 0; offsetBase = offsetBase || 0; @@ -482,11 +540,11 @@ export default class ScrollPanel extends StickyContainer { // ... then make it so. this._restoreSavedScrollState(); - } + }, // set the scrollTop attribute appropriately to position the given child at the // given offset in the window. A helper for _restoreSavedScrollState. - _scrollToToken(scrollToken, pixelOffset) { + _scrollToToken: function(scrollToken, pixelOffset) { /* find the dom node with the right scrolltoken */ var node; var messages = this.refs.itemlist.children; @@ -518,9 +576,9 @@ export default class ScrollPanel extends StickyContainer { this._setScrollTop(scrollNode.scrollTop + scrollDelta); } - } + }, - _saveScrollState() { + _saveScrollState: function() { if (this.props.stickyBottom && this.isAtBottom()) { this.scrollState = { stuckAtBottom: true }; debuglog("ScrollPanel: Saved scroll state", this.scrollState); @@ -558,9 +616,9 @@ export default class ScrollPanel extends StickyContainer { } else { debuglog("ScrollPanel: unable to save scroll state: found no children in the viewport"); } - } + }, - _restoreSavedScrollState() { + _restoreSavedScrollState: function() { var scrollState = this.scrollState; var scrollNode = this._getScrollNode(); @@ -570,9 +628,9 @@ export default class ScrollPanel extends StickyContainer { this._scrollToToken(scrollState.trackedScrollToken, scrollState.pixelOffset); } - } + }, - _setScrollTop(scrollTop) { + _setScrollTop: function(scrollTop) { var scrollNode = this._getScrollNode(); var prevScroll = scrollNode.scrollTop; @@ -594,12 +652,12 @@ export default class ScrollPanel extends StickyContainer { debuglog("ScrollPanel: set scrollTop:", scrollNode.scrollTop, "requested:", scrollTop, "_lastSetScroll:", this._lastSetScroll); - } + }, /* get the DOM node which has the scrollTop property we care about for our * message panel. */ - _getScrollNode() { + _getScrollNode: function() { if (this.unmounted) { // this shouldn't happen, but when it does, turn the NPE into // something more meaningful. @@ -607,91 +665,21 @@ export default class ScrollPanel extends StickyContainer { } return this.refs.geminiPanel.scrollbar.getViewElement(); - } + }, - render() { + render: function() { // TODO: the classnames on the div and ol could do with being updated to // reflect the fact that we don't necessarily contain a list of messages. // it's not obvious why we have a separate div and ol anyway. - return ( - -
-
    - {this.props.children} -
-
-
- ); - } -} - -ScrollPanel.propTypes = { - /* stickyBottom: if set to true, then once the user hits the bottom of - * the list, any new children added to the list will cause the list to - * scroll down to show the new element, rather than preserving the - * existing view. - */ - stickyBottom: React.PropTypes.bool, - - /* startAtBottom: if set to true, the view is assumed to start - * scrolled to the bottom. - * XXX: It's likley this is unecessary and can be derived from - * stickyBottom, but I'm adding an extra parameter to ensure - * behaviour stays the same for other uses of ScrollPanel. - * If so, let's remove this parameter down the line. - */ - startAtBottom: React.PropTypes.bool, - - /* onFillRequest(backwards): a callback which is called on scroll when - * the user nears the start (backwards = true) or end (backwards = - * false) of the list. - * - * This should return a promise; no more calls will be made until the - * promise completes. - * - * The promise should resolve to true if there is more data to be - * retrieved in this direction (in which case onFillRequest may be - * called again immediately), or false if there is no more data in this - * directon (at this time) - which will stop the pagination cycle until - * the user scrolls again. - */ - onFillRequest: React.PropTypes.func, - - /* onUnfillRequest(backwards): a callback which is called on scroll when - * there are children elements that are far out of view and could be removed - * without causing pagination to occur. - * - * This function should accept a boolean, which is true to indicate the back/top - * of the panel and false otherwise, and a scroll token, which refers to the - * first element to remove if removing from the front/bottom, and last element - * to remove if removing from the back/top. - */ - onUnfillRequest: React.PropTypes.func, - - /* onScroll: a callback which is called whenever any scroll happens. - */ - onScroll: React.PropTypes.func, - - /* onResize: a callback which is called whenever the Gemini scroll - * panel is resized - */ - onResize: React.PropTypes.func, - - /* className: classnames to add to the top-level div - */ - className: React.PropTypes.string, - - /* style: styles to add to the top-level div - */ - style: React.PropTypes.object, -}; - -ScrollPanel.defaultProps = { - stickyBottom: true, - startAtBottom: true, - onFillRequest: function(backwards) { return Promise.resolve(false); }, - onUnfillRequest: function(backwards, scrollToken) {}, - onScroll: function() {}, -}; + return ( +
+
    + {this.props.children} +
+
+
+ ); + }, +}); diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index ebd9784b6f..862c3f46d0 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -1147,6 +1147,7 @@ var TimelinePanel = React.createClass({ highlightedEventId={ this.props.highlightedEventId } readMarkerEventId={ this.state.readMarkerEventId } readMarkerVisible={ this.state.readMarkerVisible } + suppressFirstDateSeparator={ this.state.canBackPaginate } showUrlPreview={ this.props.showUrlPreview } showReadReceipts={ this.props.showReadReceipts } ourUserId={ MatrixClientPeg.get().credentials.userId } diff --git a/test/components/structures/TimelinePanel-test.js b/test/components/structures/TimelinePanel-test.js index c13d149ed0..98ec65b8e8 100644 --- a/test/components/structures/TimelinePanel-test.js +++ b/test/components/structures/TimelinePanel-test.js @@ -234,6 +234,7 @@ describe('TimelinePanel', function() { // 5 times, and we should have given up paginating expect(client.paginateEventTimeline.callCount).toEqual(5); expect(messagePanel.props.backPaginating).toBe(false); + expect(messagePanel.props.suppressFirstDateSeparator).toBe(false); // now, if we update the events, there shouldn't be any // more requests. @@ -338,6 +339,7 @@ describe('TimelinePanel', function() { awaitScroll().then(() => { // we should now have loaded the first few events expect(messagePanel.props.backPaginating).toBe(false); + expect(messagePanel.props.suppressFirstDateSeparator).toBe(true); // back-paginate until we hit the start return backPaginate(); @@ -345,6 +347,7 @@ describe('TimelinePanel', function() { // hopefully, we got to the start of the timeline expect(messagePanel.props.backPaginating).toBe(false); + expect(messagePanel.props.suppressFirstDateSeparator).toBe(false); var events = scryEventTiles(panel); expect(events[0].props.mxEvent).toBe(timeline.getEvents()[0]); From d71f15adf4d65faf0ba06b9ec72cccdde2ed785c Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 6 Sep 2017 22:51:10 +0100 Subject: [PATCH 21/43] Remove unused scrollStateMap from LoggedinView --- src/components/structures/LoggedInView.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js index 0790a5766e..147707b6fc 100644 --- a/src/components/structures/LoggedInView.js +++ b/src/components/structures/LoggedInView.js @@ -81,10 +81,6 @@ export default React.createClass({ // stash the MatrixClient in case we log out before we are unmounted this._matrixClient = this.props.matrixClient; - // _scrollStateMap is a map from room id to the scroll state returned by - // RoomView.getScrollState() - this._scrollStateMap = {}; - CallMediaHandler.loadDevices(); document.addEventListener('keydown', this._onKeyDown); @@ -116,10 +112,6 @@ export default React.createClass({ return Boolean(MatrixClientPeg.get()); }, - getScrollStateForRoom: function(roomId) { - return this._scrollStateMap[roomId]; - }, - canResetTimelineInRoom: function(roomId) { if (!this.refs.roomView) { return true; @@ -248,7 +240,6 @@ export default React.createClass({ opacity={this.props.middleOpacity} collapsedRhs={this.props.collapse_rhs} ConferenceHandler={this.props.ConferenceHandler} - scrollStateMap={this._scrollStateMap} />; if (!this.props.collapse_rhs) right_panel = ; break; From 408b8c18ea89d0c2fa714f4e34ec82e455273d42 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 7 Sep 2017 17:08:36 +0100 Subject: [PATCH 22/43] Introduce a RoomScrollStateStore to keep the place we're scrolled to in rooms. This mainly eleimates the extra, superfluous onRoomViewStoreUpdate callback that happened when the previous room saved back its scroll state. Moving the scroll state to a separate store means we can have this not emit events because nothing needs to know when the scroll state changes. --- src/components/structures/RoomView.js | 42 ++++++++++++++------------- src/stores/RoomScrollStateStore.js | 37 +++++++++++++++++++++++ src/stores/RoomViewStore.js | 30 ------------------- 3 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 src/stores/RoomScrollStateStore.js diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 87bed1ed08..02a333ee82 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -47,6 +47,7 @@ import KeyCode from '../../KeyCode'; import UserProvider from '../../autocomplete/UserProvider'; import RoomViewStore from '../../stores/RoomViewStore'; +import RoomScrollStateStore from '../../stores/RoomScrollStateStore'; let DEBUG = false; let debuglog = function() {}; @@ -163,7 +164,6 @@ module.exports = React.createClass({ roomLoadError: RoomViewStore.getRoomLoadError(), joining: RoomViewStore.isJoining(), initialEventId: RoomViewStore.getInitialEventId(), - initialEventPixelOffset: RoomViewStore.getInitialEventPixelOffset(), isInitialEventHighlighted: RoomViewStore.isInitialEventHighlighted(), forwardingEvent: RoomViewStore.getForwardingEvent(), shouldPeek: RoomViewStore.shouldPeek(), @@ -191,18 +191,32 @@ module.exports = React.createClass({ newState.room = MatrixClientPeg.get().getRoom(newState.roomId); } + if (this.state.roomId !== newState.roomId) { + // 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) { + RoomScrollStateStore.setScrollState(this.state.roomId, this._getScrollState()); + } + + // ...and get the scroll state for the new room + + // 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 = RoomScrollStateStore.getScrollState(newState.roomId); + if (roomScrollState) { + newState.initialEventId = roomScrollState.focussedEvent; + newState.initialEventPixelOffset = roomScrollState.pixelOffset; + } + } + } + // Clear the search results when clicking a search result (which changes the // currently scrolled to event, this.state.initialEventId). if (this.state.initialEventId !== newState.initialEventId) { 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, () => { // 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. @@ -340,7 +354,7 @@ module.exports = React.createClass({ this.unmounted = true; // update the scroll map before we get unmounted - this._updateScrollMap(this.state.roomId); + RoomScrollStateStore.setScrollState(this.state.roomId, this._getScrollState()); if (this.refs.roomView) { // disconnect the D&D event listeners from the room view. This @@ -617,18 +631,6 @@ 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, - scroll_state: this._getScrollState(), - }); - }, - onRoom: function(room) { if (!room || room.roomId !== this.state.roomId) { return; diff --git a/src/stores/RoomScrollStateStore.js b/src/stores/RoomScrollStateStore.js new file mode 100644 index 0000000000..a1d46a29b8 --- /dev/null +++ b/src/stores/RoomScrollStateStore.js @@ -0,0 +1,37 @@ +/* +Copyright 2017 New Vector 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. +*/ + +/** + * Stores where the user has scrolled to in each room + */ +class RoomScrollStateStore { + constructor() { + this._scrollStateMap = {}; + } + + getScrollState(roomId) { + return this._scrollStateMap[roomId]; + } + + setScrollState(roomId, scrollState) { + this._scrollStateMap[roomId] = scrollState; + } +} + +if (global.mx_RoomScrollStateStore === undefined) { + global.mx_RoomScrollStateStore = new RoomScrollStateStore(); +} +export default global.mx_RoomScrollStateStore; diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index bd9d3ea0fa..bd1fff600d 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -30,8 +30,6 @@ const INITIAL_STATE = { // 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, // Whether to highlight the initial event isInitialEventHighlighted: false, @@ -41,20 +39,6 @@ const INITIAL_STATE = { roomLoading: false, // Any error that has occurred during loading roomLoadError: null, - // A map from room id to scroll state. - // - // 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: {}, forwardingEvent: null, }; @@ -115,9 +99,6 @@ class RoomViewStore extends Store { case 'on_logged_out': this.reset(); break; - case 'update_scroll_state': - this._updateScrollState(payload); - break; case 'forward_event': this._setState({ forwardingEvent: payload.event, @@ -132,7 +113,6 @@ class RoomViewStore extends Store { roomId: payload.room_id, roomAlias: payload.room_alias, initialEventId: payload.event_id, - initialEventPixelOffset: undefined, isInitialEventHighlighted: payload.highlighted, forwardingEvent: null, roomLoading: false, @@ -145,16 +125,6 @@ class RoomViewStore extends Store { newState.joining = false; } - // 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; - } - } - if (this._state.forwardingEvent) { dis.dispatch({ action: 'send_event', From 7f44ac740346b06934850834214e6506b4a4e62a Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 7 Sep 2017 17:15:19 +0100 Subject: [PATCH 23/43] Remove now unused stuff from RoomViewStore --- src/stores/RoomViewStore.js | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index bd1fff600d..17fcc97160 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -211,15 +211,6 @@ class RoomViewStore extends Store { }); } - _updateScrollState(payload) { - // Clobber existing scroll state for the given room ID - const newScrollStateMap = this._state.scrollStateMap; - newScrollStateMap[payload.room_id] = payload.scroll_state; - this._setState({ - scrollStateMap: newScrollStateMap, - }); - } - reset() { this._state = Object.assign({}, INITIAL_STATE); } @@ -234,11 +225,6 @@ class RoomViewStore extends Store { 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; From 82d1afcc47e7515ba093c5be56ef68f357411540 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 7 Sep 2017 17:16:32 +0100 Subject: [PATCH 24/43] Correct comment --- 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 02a333ee82..69760499a1 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -201,7 +201,7 @@ module.exports = React.createClass({ // ...and get the scroll state for the new room // If an event ID wasn't specified, default to the one saved for this room - // via update_scroll_state. Assume initialEventPixelOffset should be set. + // in the scroll state store. Assume initialEventPixelOffset should be set. if (!newState.initialEventId) { const roomScrollState = RoomScrollStateStore.getScrollState(newState.roomId); if (roomScrollState) { From d714291aa139b5a7b65edd3d1615f19a8027ac0f Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 13:27:14 +0100 Subject: [PATCH 25/43] Re-add doc on scroll state map structure --- src/stores/RoomScrollStateStore.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/stores/RoomScrollStateStore.js b/src/stores/RoomScrollStateStore.js index a1d46a29b8..07848283d1 100644 --- a/src/stores/RoomScrollStateStore.js +++ b/src/stores/RoomScrollStateStore.js @@ -19,6 +19,19 @@ limitations under the License. */ class RoomScrollStateStore { constructor() { + // A map from room id to scroll state. + // + // 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. this._scrollStateMap = {}; } From 59c54d3756153e3378ba2198115e946eee599159 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 13:39:22 +0100 Subject: [PATCH 26/43] Remove redundant code --- src/components/structures/RoomView.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 69760499a1..2de8496b50 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -191,14 +191,8 @@ module.exports = React.createClass({ newState.room = MatrixClientPeg.get().getRoom(newState.roomId); } - if (this.state.roomId !== newState.roomId) { - // 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) { - RoomScrollStateStore.setScrollState(this.state.roomId, this._getScrollState()); - } - - // ...and get the scroll state for the new room + if (this.state.roomId === null && newState.roomId !== null) { + // Get the scroll state for the new room // If an event ID wasn't specified, default to the one saved for this room // in the scroll state store. Assume initialEventPixelOffset should be set. @@ -354,7 +348,9 @@ module.exports = React.createClass({ this.unmounted = true; // update the scroll map before we get unmounted - RoomScrollStateStore.setScrollState(this.state.roomId, this._getScrollState()); + if (this.state.roomId) { + RoomScrollStateStore.setScrollState(this.state.roomId, this._getScrollState()); + } if (this.refs.roomView) { // disconnect the D&D event listeners from the room view. This From 78a2e497053df599240fcadb7922f92df3498639 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 15:41:19 +0100 Subject: [PATCH 27/43] Don't always paginate when mounting a ScrollPanel Calling just checkFill on DidMount did not initially set the scrollTop which meant that one back pagination request is always performed regardless. This meant we would end up rending the first batch of events, then paginating and re-rendering again after the pagination got another batch, causing unnecessary render churn. --- src/components/structures/ScrollPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index a8a2ec181b..ae3ffe66e3 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -157,7 +157,7 @@ module.exports = React.createClass({ }, componentDidMount: function() { - this.checkFillState(); + this.checkScroll(); }, componentDidUpdate: function() { From 1be35a77ec996a3409e544d3e7a11ecde6652137 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 17:06:46 +0100 Subject: [PATCH 28/43] Don't wait for setState to run onHaveRoom onHaveRoom sets some more state (among other things) so putting it in the setState callback so it could observe the new state caused us to have to re-render again unnecessarily. Just give it the new state as a parameter. --- src/components/structures/RoomView.js | 29 +++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 2de8496b50..037cb736cd 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -211,16 +211,19 @@ module.exports = React.createClass({ newState.searchResults = null; } - 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. - if (initial) { - this._onHaveRoom(); - } - }); + this.setState(newState); + // At this point, newState.roomId could be null (e.g. the alias might not + // have been resolved yet) so anything called here must handle this case. + // We pass the new state into this function for it to read: it needs to + // observe the new state but we don't want to put it in the setState + // callback because this would prevent the setStates from being batched, + // ie. cause it to render RoomView twice rather than the once that is necessary. + if (initial) { + this._onHaveRoom(newState); + } }, - _onHaveRoom: function() { + _onHaveRoom: function(state) { // if this is an unknown room then we're in one of three states: // - This is a room we can peek into (search engine) (we can /peek) // - This is a room we can publicly join or were invited to. (we can /join) @@ -236,7 +239,7 @@ module.exports = React.createClass({ // about it). We don't peek in the historical case where we were joined but are // now not joined because the js-sdk peeking API will clobber our historical room, // making it impossible to indicate a newly joined room. - const room = this.state.room; + const room = state.room; if (room) { this.setState({ unsentMessageError: this._getUnsentMessageError(room), @@ -244,15 +247,15 @@ module.exports = React.createClass({ }); this._onRoomLoaded(room); } - if (!this.state.joining && this.state.roomId) { + if (!state.joining && state.roomId) { if (this.props.autoJoin) { this.onJoinButtonClicked(); - } else if (!room && this.state.shouldPeek) { - console.log("Attempting to peek into room %s", this.state.roomId); + } else if (!room && state.shouldPeek) { + console.log("Attempting to peek into room %s", state.roomId); this.setState({ peekLoading: true, }); - MatrixClientPeg.get().peekInRoom(this.state.roomId).then((room) => { + MatrixClientPeg.get().peekInRoom(state.roomId).then((room) => { this.setState({ room: room, peekLoading: false, From 03dcded72f98108a9f59fe8bb5e01b42299112b4 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 17:39:10 +0100 Subject: [PATCH 29/43] Blank line to make comment clearer --- 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 037cb736cd..6b76ad4ae1 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -214,6 +214,7 @@ module.exports = React.createClass({ this.setState(newState); // At this point, newState.roomId could be null (e.g. the alias might not // have been resolved yet) so anything called here must handle this case. + // We pass the new state into this function for it to read: it needs to // observe the new state but we don't want to put it in the setState // callback because this would prevent the setStates from being batched, From 81871c50bed120eb94d217e485473f428b055052 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 17:43:41 +0100 Subject: [PATCH 30/43] Add more doc on why module level variables do not work as singletons --- src/Skinner.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Skinner.js b/src/Skinner.js index f47572ba01..1fe12f85ab 100644 --- a/src/Skinner.js +++ b/src/Skinner.js @@ -84,6 +84,9 @@ class Skinner { // behaviour with multiple copies of files etc. is erratic at best. // XXX: We can still end up with the same file twice in the resulting // JS bundle which is nonideal. +// See https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/ +// or https://nodejs.org/api/modules.html#modules_module_caching_caveats +// ("Modules are cached based on their resolved filename") if (global.mxSkinner === undefined) { global.mxSkinner = new Skinner(); } From bf982004f6e06934df18ddc0fdcd51dbd863e7c2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 17:56:53 +0100 Subject: [PATCH 31/43] Give onHaveRoom the info it needs explicitly Rather than giving it a state object which is not actually the whole state but happens to be everything it actually wants (currently) --- src/components/structures/RoomView.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 6b76ad4ae1..56c0d1d281 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -220,11 +220,11 @@ module.exports = React.createClass({ // callback because this would prevent the setStates from being batched, // ie. cause it to render RoomView twice rather than the once that is necessary. if (initial) { - this._onHaveRoom(newState); + this._onHaveRoom(newState.room, newState.roomId, newState.joining, newState.shouldPeek); } }, - _onHaveRoom: function(state) { + _onHaveRoom: function(room, roomId, joining, shouldPeek) { // if this is an unknown room then we're in one of three states: // - This is a room we can peek into (search engine) (we can /peek) // - This is a room we can publicly join or were invited to. (we can /join) @@ -240,7 +240,6 @@ module.exports = React.createClass({ // about it). We don't peek in the historical case where we were joined but are // now not joined because the js-sdk peeking API will clobber our historical room, // making it impossible to indicate a newly joined room. - const room = state.room; if (room) { this.setState({ unsentMessageError: this._getUnsentMessageError(room), @@ -248,15 +247,15 @@ module.exports = React.createClass({ }); this._onRoomLoaded(room); } - if (!state.joining && state.roomId) { + if (!joining && roomId) { if (this.props.autoJoin) { this.onJoinButtonClicked(); - } else if (!room && state.shouldPeek) { - console.log("Attempting to peek into room %s", state.roomId); + } else if (!room && shouldPeek) { + console.log("Attempting to peek into room %s", roomId); this.setState({ peekLoading: true, }); - MatrixClientPeg.get().peekInRoom(state.roomId).then((room) => { + MatrixClientPeg.get().peekInRoom(roomId).then((room) => { this.setState({ room: room, peekLoading: false, From aee2f3cdefaf4a787f7bbdfedf226f3927a10301 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 18:11:13 +0100 Subject: [PATCH 32/43] Rename onHaveRoom And move some code out of it which didn't really have any reason to be hanging out there rather than just be where we set the room a few lines above. --- src/components/structures/RoomView.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 56c0d1d281..8a0eeb50b9 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -189,6 +189,11 @@ module.exports = React.createClass({ // the RoomView instance if (initial) { newState.room = MatrixClientPeg.get().getRoom(newState.roomId); + if (newState.room) { + newState.unsentMessageError = this._getUnsentMessageError(newState.room); + newState.showApps = this._shouldShowApps(newState.room); + this._onRoomLoaded(newState.room); + } } if (this.state.roomId === null && newState.roomId !== null) { @@ -220,11 +225,11 @@ module.exports = React.createClass({ // callback because this would prevent the setStates from being batched, // ie. cause it to render RoomView twice rather than the once that is necessary. if (initial) { - this._onHaveRoom(newState.room, newState.roomId, newState.joining, newState.shouldPeek); + this._setupRoom(newState.room, newState.roomId, newState.joining, newState.shouldPeek); } }, - _onHaveRoom: function(room, roomId, joining, shouldPeek) { + _setupRoom: function(room, roomId, joining, shouldPeek) { // if this is an unknown room then we're in one of three states: // - This is a room we can peek into (search engine) (we can /peek) // - This is a room we can publicly join or were invited to. (we can /join) @@ -240,13 +245,6 @@ module.exports = React.createClass({ // about it). We don't peek in the historical case where we were joined but are // now not joined because the js-sdk peeking API will clobber our historical room, // making it impossible to indicate a newly joined room. - if (room) { - this.setState({ - unsentMessageError: this._getUnsentMessageError(room), - showApps: this._shouldShowApps(room), - }); - this._onRoomLoaded(room); - } if (!joining && roomId) { if (this.props.autoJoin) { this.onJoinButtonClicked(); From 663dc3e5131bb2e38df2ba8eba8fefb6909f87f5 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 18:56:57 +0100 Subject: [PATCH 33/43] Don't re-render matrixchat unnecessarily ...on room switch. We were setting most of the state in viewRoom, but getting the current room ID from the RoomViewStore, but this meant we did one setState from the RoomViewStore updating, re-rendered and then setState again in viewRoom causing another render. This just sets the room ID in viewRoom. --- src/components/structures/MatrixChat.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index bbe345933e..c3fae0f1b3 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -38,7 +38,6 @@ import linkifyMatrix from "../../linkify-matrix"; import * as Lifecycle from '../../Lifecycle'; // LifecycleStore is not used but does listen to and dispatch actions require('../../stores/LifecycleStore'); -import RoomViewStore from '../../stores/RoomViewStore'; import PageTypes from '../../PageTypes'; import createRoom from "../../createRoom"; @@ -214,9 +213,6 @@ module.exports = React.createClass({ componentWillMount: function() { SdkConfig.put(this.props.config); - this._roomViewStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdated); - this._onRoomViewStoreUpdated(); - if (!UserSettingsStore.getLocalSetting('analyticsOptOut', false)) Analytics.enable(); // Used by _viewRoom before getting state from sync @@ -587,10 +583,6 @@ module.exports = React.createClass({ } }, - _onRoomViewStoreUpdated: function() { - this.setState({ currentRoomId: RoomViewStore.getRoomId() }); - }, - _setPage: function(pageType) { this.setState({ page_type: pageType, @@ -677,6 +669,7 @@ module.exports = React.createClass({ this.focusComposer = true; const newState = { + currentRoomId: roomInfo.room_id || null, page_type: PageTypes.RoomView, thirdPartyInvite: roomInfo.third_party_invite, roomOobData: roomInfo.oob_data, From 0e8bd856bc3527b46397b2173004f5cd0f9c24a6 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Fri, 8 Sep 2017 20:14:27 +0200 Subject: [PATCH 34/43] remove obsolete this._roomViewStoreToken.remove(); --- 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 c3fae0f1b3..c142d6958c 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -349,7 +349,6 @@ module.exports = React.createClass({ UDEHandler.stopListening(); window.removeEventListener("focus", this.onFocus); window.removeEventListener('resize', this.handleResize); - this._roomViewStoreToken.remove(); }, componentDidUpdate: function() { From ec3ff529e7ce4985f1b553c48d7175c7d1097b5a Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 23:05:27 +0100 Subject: [PATCH 35/43] Fast path for emojifying strings Emojione's regex for detecting emoji is *enourmous* and we were running it on every display name, room name, message etc every time those components mounted. Add a much simpler regex to rule out the majority of strings that contain no emoji and fast-path them. Makes room switching about 10% faster (in my tests with all the profiling turned on). --- src/HtmlUtils.js | 15 +++++++++++++++ src/components/views/elements/EmojiText.js | 13 ++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 87e714083b..a046a94363 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -31,13 +31,28 @@ emojione.imagePathPNG = 'emojione/png/'; // Use SVGs for emojis emojione.imageType = 'svg'; +const SIMPLE_EMOJI_PATTERN = /([\ud800-\udbff])([\udc00-\udfff])/; const EMOJI_REGEX = new RegExp(emojione.unicodeRegexp+"+", "gi"); const COLOR_REGEX = /^#[0-9a-fA-F]{6}$/; +/* + * Return true if the given string contains emoji + * Uses a much, much simpler regex than emojione's so will give false + * positives, but useful for fast-path testing strings to see if they + * need emojification. + * unicodeToImage uses this function. + */ +export function containsEmoji(str) { + return SIMPLE_EMOJI_PATTERN.test(str); +} + /* modified from https://github.com/Ranks/emojione/blob/master/lib/js/emojione.js * because we want to include emoji shortnames in title text */ export function unicodeToImage(str) { + // fast path + if (!containsEmoji(str)) return str; + let replaceWith, unicode, alt, short, fname; const mappedUnicode = emojione.mapUnicodeToShort(); diff --git a/src/components/views/elements/EmojiText.js b/src/components/views/elements/EmojiText.js index cb6cd2ef5e..a48e51f44f 100644 --- a/src/components/views/elements/EmojiText.js +++ b/src/components/views/elements/EmojiText.js @@ -15,12 +15,19 @@ */ import React from 'react'; -import {emojifyText} from '../../../HtmlUtils'; +import {emojifyText, containsEmoji} from '../../../HtmlUtils'; export default function EmojiText(props) { const {element, children, ...restProps} = props; - restProps.dangerouslySetInnerHTML = emojifyText(children); - return React.createElement(element, restProps); + + // fast path: simple regex to detect strings that don't contain + // emoji and just return them + if (containsEmoji(children)) { + restProps.dangerouslySetInnerHTML = emojifyText(children); + return React.createElement(element, restProps); + } else { + return React.createElement(element, restProps, children); + } } EmojiText.propTypes = { From ea5726aa4e101afa65d2e8a87813d1ef80fd418d Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 23:14:06 +0100 Subject: [PATCH 36/43] Copyright --- src/HtmlUtils.js | 1 + src/components/views/elements/EmojiText.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index a046a94363..05be98f5fd 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 New Vector 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/elements/EmojiText.js b/src/components/views/elements/EmojiText.js index a48e51f44f..faab0241ae 100644 --- a/src/components/views/elements/EmojiText.js +++ b/src/components/views/elements/EmojiText.js @@ -1,5 +1,6 @@ /* Copyright 2016 Aviral Dasgupta + Copyright 2017 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From fe79010e4e32604ff3685fa6f42289d0c83abd03 Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 8 Sep 2017 23:36:22 +0100 Subject: [PATCH 37/43] Only add the code copy button for HTML messages Trivial fast-path optimisation: plain text messages cannot possibly contain pre blocks so there's no point in trying to parse them in order to add code copy buttons. --- src/HtmlUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 87e714083b..ccc7c1a630 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -393,7 +393,7 @@ export function bodyToHtml(content, highlights, opts) { } safeBody = sanitizeHtml(body, sanitizeHtmlParams); safeBody = unicodeToImage(safeBody); - safeBody = addCodeCopyButton(safeBody); + if (isHtml) safeBody = addCodeCopyButton(safeBody); } finally { delete sanitizeHtmlParams.textFilter; From 876257f4e219acc06bd5097dd4bd71eb5403ebd2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Sun, 10 Sep 2017 14:23:33 +0100 Subject: [PATCH 38/43] Consolidate the code copy button Adding the code code button was done by manipulating the HTML of the event body to add a span tag, then adding the onclick handler after the thing was mounted. Apart from splitting the code between two places, adding the span tag was, according to Chrome's profiler, taking up quite a lot of CPU cycles (apparently as soon as you set the innerHTML on a div). Instead, just build the whole lot together after the component mounts. --- src/HtmlUtils.js | 18 ------------------ src/components/views/messages/TextualBody.js | 15 +++++++++------ 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index ccc7c1a630..2b0fd686c0 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -393,7 +393,6 @@ export function bodyToHtml(content, highlights, opts) { } safeBody = sanitizeHtml(body, sanitizeHtmlParams); safeBody = unicodeToImage(safeBody); - if (isHtml) safeBody = addCodeCopyButton(safeBody); } finally { delete sanitizeHtmlParams.textFilter; @@ -412,23 +411,6 @@ export function bodyToHtml(content, highlights, opts) { return ; } -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")); - codeBlocks.forEach(p => { - const button = document.createElement("span"); - button.className = "mx_EventTile_copyButton"; - p.appendChild(button); - }); - return el.innerHTML; -} - export function emojifyText(text) { return { __html: unicodeToImage(escape(text)), diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 58273bee67..3937780c2a 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -113,14 +113,17 @@ module.exports = React.createClass({ } }, 10); } - // add event handlers to the 'copy code' buttons - const buttons = ReactDOM.findDOMNode(this).getElementsByClassName("mx_EventTile_copyButton"); - for (let i = 0; i < buttons.length; i++) { - buttons[i].onclick = (e) => { - const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; + + // Add 'copy' buttons to pre blocks + ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre').forEach((p) => { + const button = document.createElement("span"); + button.className = "mx_EventTile_copyButton"; + button.onclick = (e) => { + const copyCode = button.parentNode.getElementsByTagName("code")[0]; this.copyToClipboard(copyCode.textContent); }; - } + p.appendChild(button); + }); } }, From 05a986334d482ecd37af40c4769700fe54fdcb46 Mon Sep 17 00:00:00 2001 From: David Baker Date: Sun, 10 Sep 2017 15:58:17 +0100 Subject: [PATCH 39/43] Separate function to add code copy button For neatness and also so it can show up separately in the profiler. --- src/components/views/messages/TextualBody.js | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 3937780c2a..a58422e840 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -114,16 +114,7 @@ module.exports = React.createClass({ }, 10); } - // Add 'copy' buttons to pre blocks - ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre').forEach((p) => { - const button = document.createElement("span"); - button.className = "mx_EventTile_copyButton"; - button.onclick = (e) => { - const copyCode = button.parentNode.getElementsByTagName("code")[0]; - this.copyToClipboard(copyCode.textContent); - }; - p.appendChild(button); - }); + this._addCodeCopyButton(); } }, @@ -260,6 +251,19 @@ module.exports = React.createClass({ } }, + _addCodeCopyButton() { + // Add 'copy' buttons to pre blocks + ReactDOM.findDOMNode(this).querySelectorAll('.mx_EventTile_body pre').forEach((p) => { + const button = document.createElement("span"); + button.className = "mx_EventTile_copyButton"; + button.onclick = (e) => { + const copyCode = button.parentNode.getElementsByTagName("code")[0]; + this.copyToClipboard(copyCode.textContent); + }; + p.appendChild(button); + }); + }, + onCancelClick: function(event) { this.setState({ widgetHidden: true }); // FIXME: persist this somewhere smarter than local storage From be8f0991a69dabfe156e1c03ce31a79c5fca5427 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 11 Sep 2017 16:59:09 +0100 Subject: [PATCH 40/43] Avoid re-rendering RoomList on room switch Introduce a class that consumes updates from the RoomViewStore and announces to listeners if the active room ID is now or is no longer the room ID they specified. Naming suggestions welcome: it's currently called ActiveRoomObserver. Avoids passing the selectedRoomId down from MatrixChat all the way through the LeftPanel / RoomList / RoomSubList to the RoomTiles. Also introduce a CallPreview class that listens directly for RoomViewStore changes as the call preview in the left panel needs to know when the room changes, so this allows this component to update without having to update the entire left panel. --- src/ActiveRoomObserver.js | 77 +++++++++++++++++++ src/components/views/rooms/RoomList.js | 1 - src/components/views/rooms/RoomTile.js | 17 ++++- src/components/views/voip/CallPreview.js | 97 ++++++++++++++++++++++++ 4 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 src/ActiveRoomObserver.js create mode 100644 src/components/views/voip/CallPreview.js diff --git a/src/ActiveRoomObserver.js b/src/ActiveRoomObserver.js new file mode 100644 index 0000000000..d6fbb460b5 --- /dev/null +++ b/src/ActiveRoomObserver.js @@ -0,0 +1,77 @@ +/* +Copyright 2017 New Vector 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 RoomViewStore from './stores/RoomViewStore'; + +/** + * Consumes changes from the RoomViewStore and notifies specific things + * about when the active room changes. Unlike listening for RoomViewStore + * changes, you can subscribe to only changes relevant to a particular + * room. + * + * TODO: If we introduce an observer for something else, factor out + * the adding / removing of listeners & emitting into a common class. + */ +class ActiveRoomObserver { + constructor() { + this._listeners = {}; + + this._activeRoomId = RoomViewStore.getRoomId(); + // TODO: We could self-destruct when the last listener goes away, or at least + // stop listening. + this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this)); + } + + addListener(roomId, listener) { + if (!this._listeners[roomId]) this._listeners[roomId] = []; + this._listeners[roomId].push(listener); + } + + removeListener(roomId, listener) { + if (this._listeners[roomId]) { + const i = this._listeners[roomId].indexOf(listener); + if (i > -1) { + this._listeners[roomId].splice(i, 1); + } + } else { + console.warn("Unregistering unrecognised listener (roomId=" + roomId + ")"); + } + } + + _emit(roomId) { + if (!this._listeners[roomId]) return; + + for (const l of this._listeners[roomId]) { + l.call(); + } + } + + _onRoomViewStoreUpdate() { + // emit for the old room ID + if (this._activeRoomId) this._emit(this._activeRoomId); + + // update our cache + this._activeRoomId = RoomViewStore.getRoomId(); + + // and emit for the new one + if (this._activeRoomId) this._emit(this._activeRoomId); + } +} + +if (global.mx_ActiveRoomObserver === undefined) { + global.mx_ActiveRoomObserver = new ActiveRoomObserver(); +} +export default global.mx_ActiveRoomObserver; diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 27001ac954..b7b2e5ecea 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -63,7 +63,6 @@ module.exports = React.createClass({ propTypes: { ConferenceHandler: React.PropTypes.any, collapsed: React.PropTypes.bool.isRequired, - currentRoom: React.PropTypes.string, searchFilter: React.PropTypes.string, }, diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js index 97568a52a1..a6065d8e92 100644 --- a/src/components/views/rooms/RoomTile.js +++ b/src/components/views/rooms/RoomTile.js @@ -1,5 +1,6 @@ /* Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -27,6 +28,8 @@ var RoomNotifs = require('../../../RoomNotifs'); var FormattingUtils = require('../../../utils/FormattingUtils'); import AccessibleButton from '../elements/AccessibleButton'; var UserSettingsStore = require('../../../UserSettingsStore'); +import ActiveRoomObserver from '../../../ActiveRoomObserver'; +import RoomViewStore from '../../../stores/RoomViewStore'; module.exports = React.createClass({ displayName: 'RoomTile', @@ -39,7 +42,6 @@ module.exports = React.createClass({ room: React.PropTypes.object.isRequired, collapsed: React.PropTypes.bool.isRequired, - selected: React.PropTypes.bool.isRequired, unread: React.PropTypes.bool.isRequired, highlight: React.PropTypes.bool.isRequired, isInvite: React.PropTypes.bool.isRequired, @@ -58,6 +60,7 @@ module.exports = React.createClass({ badgeHover : false, menuDisplayed: false, notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId), + selected: this.props.room.roomId === RoomViewStore.getRoomId(), }); }, @@ -87,8 +90,15 @@ module.exports = React.createClass({ } }, + _onActiveRoomChange: function() { + this.setState({ + selected: this.props.room.roomId === RoomViewStore.getRoomId(), + }); + }, + componentWillMount: function() { MatrixClientPeg.get().on("accountData", this.onAccountData); + ActiveRoomObserver.addListener(this.props.room.roomId, this._onActiveRoomChange); }, componentWillUnmount: function() { @@ -96,6 +106,7 @@ module.exports = React.createClass({ if (cli) { MatrixClientPeg.get().removeListener("accountData", this.onAccountData); } + ActiveRoomObserver.removeListener(this.props.room.roomId, this._onActiveRoomChange); }, onClick: function(ev) { @@ -174,7 +185,7 @@ module.exports = React.createClass({ var classes = classNames({ 'mx_RoomTile': true, - 'mx_RoomTile_selected': this.props.selected, + 'mx_RoomTile_selected': this.state.selected, 'mx_RoomTile_unread': this.props.unread, 'mx_RoomTile_unreadNotify': notifBadges, 'mx_RoomTile_highlight': mentionBadges, @@ -221,7 +232,7 @@ module.exports = React.createClass({ 'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed, }); - if (this.props.selected) { + if (this.state.selected) { let nameSelected = {name}; label =
{ nameSelected }
; diff --git a/src/components/views/voip/CallPreview.js b/src/components/views/voip/CallPreview.js new file mode 100644 index 0000000000..132e29bd34 --- /dev/null +++ b/src/components/views/voip/CallPreview.js @@ -0,0 +1,97 @@ +/* +Copyright 2017 New Vector 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 RoomViewStore from '../../../stores/RoomViewStore'; +import CallHandler from '../../../CallHandler'; +import dis from '../../../dispatcher'; +import sdk from '../../../index'; + +module.exports = React.createClass({ + displayName: 'CallPreview', + + propTypes: { + // A Conference Handler implementation + // Must have a function signature: + // getConferenceCallForRoom(roomId: string): MatrixCall + ConferenceHandler: React.PropTypes.object, + }, + + getInitialState: function() { + return { + roomId: RoomViewStore.getRoomId(), + activeCall: CallHandler.getAnyActiveCall(), + }; + }, + + componentWillMount: function() { + this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate); + this.dispatcherRef = dis.register(this._onAction); + }, + + componentWillUnmount: function() { + if (this._roomStoreToken) { + this._roomStoreToken.remove(); + } + dis.unregister(this.dispatcherRef); + }, + + _onRoomViewStoreUpdate: function(payload) { + if (RoomViewStore.getRoomId() === this.state.roomId) return; + this.setState({ + roomId: RoomViewStore.getRoomId(), + }); + }, + + _onAction: function(payload) { + switch (payload.action) { + // listen for call state changes to prod the render method, which + // may hide the global CallView if the call it is tracking is dead + case 'call_state': + this.setState({ + activeCall: CallHandler.getAnyActiveCall(), + }); + break; + } + }, + + _onCallViewClick: function() { + const call = CallHandler.getAnyActiveCall(); + if (call) { + dis.dispatch({ + action: 'view_room', + room_id: call.groupRoomId || call.roomId, + }); + } + }, + + render: function() { + const callForRoom = CallHandler.getCallForRoom(this.state.roomId); + const showCall = (this.state.activeCall && this.state.activeCall.call_state === 'connected' && !callForRoom); + + if (showCall) { + const CallView = sdk.getComponent('voip.CallView'); + return ( + + ); + } + return null; + }, +}); + From 531fc3ac54363c5a1efebc5d850613f8639f277b Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 11 Sep 2017 17:57:52 +0100 Subject: [PATCH 41/43] Fix 'Failed to load timeline position' regression Ignore the update that comes in from the RoomViewStore when the current room changes or we save our scoll state against the new room rather than the old one. Fixes https://github.com/vector-im/riot-web/issues/5010 --- src/components/structures/RoomView.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 8a0eeb50b9..6cb8dc3e7b 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -157,6 +157,19 @@ module.exports = React.createClass({ if (this.unmounted) { return; } + + if (!initial && this.state.roomId !== RoomViewStore.getRoomId()) { + // RoomView explicitly does not support changing what room + // is being viewed: instead it should just be re-mounted when + // switching rooms. Therefore, if the room ID changes, we + // ignore this. We either need to do this or add code to handle + // saving the scroll position (otherwise we end up saving the + // scroll position against the wrong room). Given that doing the + // setState here would cause a bunch of unnecessary work, we + // just ignore the change. + return; + } + const newState = { roomId: RoomViewStore.getRoomId(), roomAlias: RoomViewStore.getRoomAlias(), From 6cb98d719631fd18ef571895008f2771895dc7fb Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 11 Sep 2017 18:39:30 +0100 Subject: [PATCH 42/43] Hopefully make comment clearer --- src/components/structures/RoomView.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 6cb8dc3e7b..2a6cf0aee4 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -164,9 +164,12 @@ module.exports = React.createClass({ // switching rooms. Therefore, if the room ID changes, we // ignore this. We either need to do this or add code to handle // saving the scroll position (otherwise we end up saving the - // scroll position against the wrong room). Given that doing the - // setState here would cause a bunch of unnecessary work, we - // just ignore the change. + // scroll position against the wrong room). + + // Given that doing the setState here would cause a bunch of + // unnecessary work, we just ignore the change since we know + // that if the current room ID has changed from what we thought + // it was, it means we're about to be unmounted. return; } From 92ae0db1bd8e77990b0a642dc81ef215b5a6e4a2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@googlemail.com> Date: Tue, 12 Sep 2017 09:35:47 +0100 Subject: [PATCH 43/43] fix placeholder causing app to break when using zh --- src/i18n/strings/zh_Hans.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index f8ee16f67e..c5a94ec918 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -679,7 +679,7 @@ "demote": "降级", "Deops user with given id": "Deops user", "Join as voice or video.": "通过 语言 或者 视频加入.", - "%(senderName)s made future room history visible to": "%(senderName) 设定历史浏览功能为", + "%(senderName)s made future room history visible to": "%(senderName)s 设定历史浏览功能为", "AM": "上午", "PM": "下午", "NOTE: Apps are not end-to-end encrypted": "提示:APP不支持端对端加密",