diff --git a/.gitignore b/.gitignore
index c28df64c..060ca6e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@
/key.pem
/lib
/node_modules
+/electron_app/node_modules
+/electron_app/dist
/packages/
/webapp
/.npmrc
@@ -12,3 +14,6 @@
npm-debug.log
electron/dist
electron/pub
+/.idea
+/config.json
+/src/component-index.js
diff --git a/.modernizr.json b/.modernizr.json
index 29e620a5..06be8b4f 100644
--- a/.modernizr.json
+++ b/.modernizr.json
@@ -9,6 +9,8 @@
"test/css/flexbox",
"test/es5/specification",
"test/css/objectfit",
- "test/storage/localstorage"
+ "test/storage/localstorage",
+ "test/workers/webworkers",
+ "test/indexeddb"
]
-}
\ No newline at end of file
+}
diff --git a/.travis.yml b/.travis.yml
index 9720d887..e020ba7d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,22 @@
language: node_js
node_js:
- - 6 # node v6, to match jenkins
+ # make sure we work with a range of node versions.
+ # As of the time of writing:
+ # - 4.x is still in LTS (until April 2018), but some of our deps (notably
+ # extract-zip) don't work with it
+ # - 5.x has been EOLed for nearly a year.
+ # - 6.x is the current 'LTS' version
+ # - 7.x is the current 'current' version (until October 2017)
+ #
+ # see: https://github.com/nodejs/LTS/
+ #
+ # anything before 6.3 ships with npm 3.9 or earlier, which had problems
+ # with symlinks in node_modules (see
+ # https://github.com/npm/npm/releases/tag/v3.10.0 'FIXES AND REFACTORING').
+ - 6.3
+ - 6
+ - 7
install:
- - npm install
- - (cd node_modules/matrix-js-sdk && npm install)
- - (cd node_modules/matrix-react-sdk && npm install)
+ # clone the deps with depth 1: we know we will only ever need that one
+ # commit.
+ - scripts/fetch-develop.deps.sh --depth 1 && npm install
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea63ee66..cdba0551 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,433 @@
+Changes in [0.11.4](https://github.com/vector-im/riot-web/releases/tag/v0.11.4) (2017-06-22)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.3...v0.11.4)
+
+ * Update matrix-js-sdk and react-sdk to fix a regression where the
+ background indexedb worker was disabled, failures to open indexeddb
+ causing the app to fail to start, a race when starting that could break
+ switching to rooms, and the inability to to invite user with mixed case
+ usernames.
+
+Changes in [0.11.3](https://github.com/vector-im/riot-web/releases/tag/v0.11.3) (2017-06-20)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.2...v0.11.3)
+
+ * Update to matrix-react-sdk 0.9.6 to fix infinite spinner bugs
+ and some parts of the app that had missed translation.
+
+Changes in [0.11.2](https://github.com/vector-im/riot-web/releases/tag/v0.11.2) (2017-06-19)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.2-rc.2...v0.11.2)
+
+ * Add more languages and translations
+ * Add a 'register' button
+
+Changes in [0.11.2-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.11.2-rc.2) (2017-06-16)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.2-rc.1...v0.11.2-rc.2)
+
+ * Update react-sdk to pull in fixes for URL previews, CAS
+ login, h2 in markdown and CAPTCHA forms.
+ * Enable Korean translation
+ * Update from Weblate.
+ [\#4323](https://github.com/vector-im/riot-web/pull/4323)
+ * Fix h2 in markdown being weird
+ [\#4332](https://github.com/vector-im/riot-web/pull/4332)
+
+Changes in [0.11.2-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.11.2-rc.1) (2017-06-15)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.1...v0.11.2-rc.1)
+
+ * Attempts to deflakify the joining test
+ [\#4313](https://github.com/vector-im/riot-web/pull/4313)
+ * Add a test for the login flow when there is a teamserver
+ [\#4315](https://github.com/vector-im/riot-web/pull/4315)
+ * Remove onload simulator from loading test
+ [\#4314](https://github.com/vector-im/riot-web/pull/4314)
+ * Update from Weblate.
+ [\#4305](https://github.com/vector-im/riot-web/pull/4305)
+ * Test that we handle stored mx_last_room_id correctly
+ [\#4292](https://github.com/vector-im/riot-web/pull/4292)
+ * Ask for email address after setting password for the first time
+ [\#4301](https://github.com/vector-im/riot-web/pull/4301)
+ * i18n for setting email after password flow
+ [\#4299](https://github.com/vector-im/riot-web/pull/4299)
+ * Update from Weblate.
+ [\#4290](https://github.com/vector-im/riot-web/pull/4290)
+ * Don't show the tooltips when filtering rooms
+ [\#4282](https://github.com/vector-im/riot-web/pull/4282)
+ * Update from Weblate.
+ [\#4272](https://github.com/vector-im/riot-web/pull/4272)
+ * Add missing VOIP Dropdown width
+ [\#4266](https://github.com/vector-im/riot-web/pull/4266)
+ * Update import and directory path in the Translations dev guide
+ [\#4261](https://github.com/vector-im/riot-web/pull/4261)
+ * Use Thai string for Thai in Language-Chooser
+ [\#4260](https://github.com/vector-im/riot-web/pull/4260)
+
+Changes in [0.11.1](https://github.com/vector-im/riot-web/releases/tag/v0.11.1) (2017-06-14)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.0...v0.11.1)
+
+ * Update to react-sdk 0.9.4 to prompt to set an
+ email address when setting a password and make
+ DM guessing smarter.
+
+Changes in [0.11.0](https://github.com/vector-im/riot-web/releases/tag/v0.11.0) (2017-06-12)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.0-rc.2...v0.11.0)
+
+ * More translations & minor fixes
+
+Changes in [0.11.0-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.11.0-rc.2) (2017-06-09)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.11.0-rc.1...v0.11.0-rc.2)
+
+ * Update to matrix-react-sdk rc.2 which fixes the flux
+ dependency version and an issue with the conference
+ call bar translation.
+
+
+Changes in [0.11.0-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.11.0-rc.1) (2017-06-09)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.10.2...v0.11.0-rc.1)
+
+ * Update from Weblate.
+ [\#4258](https://github.com/vector-im/riot-web/pull/4258)
+ * Update from Weblate.
+ [\#4254](https://github.com/vector-im/riot-web/pull/4254)
+ * Update from Weblate.
+ [\#4253](https://github.com/vector-im/riot-web/pull/4253)
+ * Expect to see HTTP /join/#some:alias when we the view knows it
+ [\#4252](https://github.com/vector-im/riot-web/pull/4252)
+ * Update from Weblate.
+ [\#4250](https://github.com/vector-im/riot-web/pull/4250)
+ * add explicit import to utf8 polyfill and rip out unused imports
+ [\#4169](https://github.com/vector-im/riot-web/pull/4169)
+ * Added styling for copy to clipboard button
+ [\#4204](https://github.com/vector-im/riot-web/pull/4204)
+ * Update from Weblate.
+ [\#4231](https://github.com/vector-im/riot-web/pull/4231)
+ * Update from Weblate.
+ [\#4218](https://github.com/vector-im/riot-web/pull/4218)
+ * Update CSS for ChatInviteDialog
+ [\#4226](https://github.com/vector-im/riot-web/pull/4226)
+ * change electron -> electron_app which was previously missed
+ [\#4212](https://github.com/vector-im/riot-web/pull/4212)
+ * New guest access
+ [\#4039](https://github.com/vector-im/riot-web/pull/4039)
+ * Align message timestamp centrally about the avatar mid-point
+ [\#4219](https://github.com/vector-im/riot-web/pull/4219)
+ * Remove '/' from homepage URL
+ [\#4221](https://github.com/vector-im/riot-web/pull/4221)
+ * Chop off 'origin/'
+ [\#4220](https://github.com/vector-im/riot-web/pull/4220)
+ * Update from Weblate.
+ [\#4214](https://github.com/vector-im/riot-web/pull/4214)
+ * adjust alignment of message menu button in compact layout
+ [\#4211](https://github.com/vector-im/riot-web/pull/4211)
+ * Update from Weblate.
+ [\#4207](https://github.com/vector-im/riot-web/pull/4207)
+ * Fix Tests in ILAG
+ [\#4209](https://github.com/vector-im/riot-web/pull/4209)
+ * Update from Weblate.
+ [\#4197](https://github.com/vector-im/riot-web/pull/4197)
+ * Fix tests for new-guest-access
+ [\#4201](https://github.com/vector-im/riot-web/pull/4201)
+ * i18n for SetPasswordDialog
+ [\#4198](https://github.com/vector-im/riot-web/pull/4198)
+ * Update from Weblate.
+ [\#4193](https://github.com/vector-im/riot-web/pull/4193)
+ * to make the windows volume mixer not explode as it can't resize icons.
+ [\#4183](https://github.com/vector-im/riot-web/pull/4183)
+ * provide react devtools in electron dev runs
+ [\#4186](https://github.com/vector-im/riot-web/pull/4186)
+ * Fix DeprecationWarning
+ [\#4184](https://github.com/vector-im/riot-web/pull/4184)
+ * room link should be a matrix.to one
+ [\#4178](https://github.com/vector-im/riot-web/pull/4178)
+ * Update home.html
+ [\#4163](https://github.com/vector-im/riot-web/pull/4163)
+ * Add missing translation for room directory
+ [\#4160](https://github.com/vector-im/riot-web/pull/4160)
+ * i18n welcome
+ [\#4129](https://github.com/vector-im/riot-web/pull/4129)
+ * Tom welcome page
+ [\#4038](https://github.com/vector-im/riot-web/pull/4038)
+ * Fix some tests that expect Directory (they should expect HomePage)
+ [\#4076](https://github.com/vector-im/riot-web/pull/4076)
+ * Add "Login" button to RHS when user is a guest
+ [\#4037](https://github.com/vector-im/riot-web/pull/4037)
+ * Rejig the PaswordNagBar
+ [\#4026](https://github.com/vector-im/riot-web/pull/4026)
+ * Allow team server config to be missing
+ [\#4024](https://github.com/vector-im/riot-web/pull/4024)
+ * Remove GuestWarningBar
+ [\#4020](https://github.com/vector-im/riot-web/pull/4020)
+ * Make left panel better for new users (mk III)
+ [\#4023](https://github.com/vector-im/riot-web/pull/4023)
+ * Implement default welcome page and allow custom URL /w config
+ [\#4015](https://github.com/vector-im/riot-web/pull/4015)
+ * Add warm-fuzzy for successful password entry
+ [\#3989](https://github.com/vector-im/riot-web/pull/3989)
+ * autoFocus new password input in SetPasswordDialog
+ [\#3982](https://github.com/vector-im/riot-web/pull/3982)
+ * Implement dialog to set password
+ [\#3921](https://github.com/vector-im/riot-web/pull/3921)
+ * Replace NeedToRegister with SetMxId dialog
+ [\#3924](https://github.com/vector-im/riot-web/pull/3924)
+ * Add welcomeUserId to sample config
+ [\#3906](https://github.com/vector-im/riot-web/pull/3906)
+ * CSS for mxIdDialog redesign
+ [\#3885](https://github.com/vector-im/riot-web/pull/3885)
+ * Implement PasswordNagBar
+ [\#3817](https://github.com/vector-im/riot-web/pull/3817)
+ * CSS for new SetMxIdDialog
+ [\#3762](https://github.com/vector-im/riot-web/pull/3762)
+
+Changes in [0.10.2](https://github.com/vector-im/riot-web/releases/tag/v0.10.2) (2017-06-06)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.10.1...v0.10.2)
+
+ * Hotfix for bugs where navigating straight to a URL like /#/login and
+ and /#/forgot_password
+
+
+Changes in [0.10.1](https://github.com/vector-im/riot-web/releases/tag/v0.10.1) (2017-06-02)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.10.0...v0.10.1)
+
+ * Update to matrix-react-sdk 0.9.1 to fix i18n error which broke start chat in some circumstances
+
+Changes in [0.10.0](https://github.com/vector-im/riot-web/releases/tag/v0.10.0) (2017-06-02)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.10.0-rc.2...v0.10.0)
+
+ * Update from Weblate.
+ [\#4152](https://github.com/vector-im/riot-web/pull/4152)
+
+Changes in [0.10.0-rc.2](https://github.com/vector-im/riot-web/releases/tag/v0.10.0-rc.2) (2017-06-02)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.10.0-rc.1...v0.10.0-rc.2)
+
+ * Update from Weblate.
+ [\#4150](https://github.com/vector-im/riot-web/pull/4150)
+ * styling for webrtc settings
+ [\#4019](https://github.com/vector-im/riot-web/pull/4019)
+ * Update from Weblate.
+ [\#4140](https://github.com/vector-im/riot-web/pull/4140)
+ * add styles for compact layout
+ [\#4132](https://github.com/vector-im/riot-web/pull/4132)
+ * Various tweaks to fetch-develop-deps
+ [\#4147](https://github.com/vector-im/riot-web/pull/4147)
+ * Don't try to build with node 6.0
+ [\#4145](https://github.com/vector-im/riot-web/pull/4145)
+ * Support 12hr time on DateSeparator
+ [\#4143](https://github.com/vector-im/riot-web/pull/4143)
+ * Update from Weblate.
+ [\#4137](https://github.com/vector-im/riot-web/pull/4137)
+ * Update from Weblate.
+ [\#4105](https://github.com/vector-im/riot-web/pull/4105)
+ * Update from Weblate.
+ [\#4094](https://github.com/vector-im/riot-web/pull/4094)
+ * Update from Weblate.
+ [\#4091](https://github.com/vector-im/riot-web/pull/4091)
+ * Update from Weblate.
+ [\#4089](https://github.com/vector-im/riot-web/pull/4089)
+ * Update from Weblate.
+ [\#4083](https://github.com/vector-im/riot-web/pull/4083)
+
+Changes in [0.10.0-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.10.0-rc.1) (2017-06-01)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.10...v0.10.0-rc.1)
+
+ * basic electron profile support
+ [\#4030](https://github.com/vector-im/riot-web/pull/4030)
+ * Finish translations for vector-im/riot-web
+ [\#4122](https://github.com/vector-im/riot-web/pull/4122)
+ * Translate src/vector
+ [\#4119](https://github.com/vector-im/riot-web/pull/4119)
+ * electron flashFrame was way too annoying
+ [\#4128](https://github.com/vector-im/riot-web/pull/4128)
+ * auto-launch support [Electron]
+ [\#4012](https://github.com/vector-im/riot-web/pull/4012)
+ * Show 12hr time on hover too
+ [\#4092](https://github.com/vector-im/riot-web/pull/4092)
+ * Translate src/notifications
+ [\#4087](https://github.com/vector-im/riot-web/pull/4087)
+ * Translate src/components/structures
+ [\#4084](https://github.com/vector-im/riot-web/pull/4084)
+ * Smaller font size on timestamp to better fit in the available space
+ [\#4085](https://github.com/vector-im/riot-web/pull/4085)
+ * Make travis run the build with several versions of node
+ [\#4079](https://github.com/vector-im/riot-web/pull/4079)
+ * Piwik Analytics
+ [\#4056](https://github.com/vector-im/riot-web/pull/4056)
+ * Update from Weblate.
+ [\#4077](https://github.com/vector-im/riot-web/pull/4077)
+ * managed to eat the eventStatus check, can't redact a local-echo etc
+ [\#4078](https://github.com/vector-im/riot-web/pull/4078)
+ * show redact in context menu only if has PL to/sent message
+ [\#3925](https://github.com/vector-im/riot-web/pull/3925)
+ * Update from Weblate.
+ [\#4064](https://github.com/vector-im/riot-web/pull/4064)
+ * Change redact -> remove to improve clarity
+ [\#3722](https://github.com/vector-im/riot-web/pull/3722)
+ * Update from Weblate.
+ [\#4058](https://github.com/vector-im/riot-web/pull/4058)
+ * Message Forwarding
+ [\#3688](https://github.com/vector-im/riot-web/pull/3688)
+ * Update from Weblate.
+ [\#4057](https://github.com/vector-im/riot-web/pull/4057)
+ * Fixed an input field's background color in dark theme
+ [\#4053](https://github.com/vector-im/riot-web/pull/4053)
+ * Update from Weblate.
+ [\#4051](https://github.com/vector-im/riot-web/pull/4051)
+ * Update from Weblate.
+ [\#4049](https://github.com/vector-im/riot-web/pull/4049)
+ * Update from Weblate.
+ [\#4048](https://github.com/vector-im/riot-web/pull/4048)
+ * Update from Weblate.
+ [\#4040](https://github.com/vector-im/riot-web/pull/4040)
+ * Update translating.md: Minor suggestions
+ [\#4041](https://github.com/vector-im/riot-web/pull/4041)
+ * tidy electron files, they weren't pwetty
+ [\#3993](https://github.com/vector-im/riot-web/pull/3993)
+ * Prevent Power Save when in call (Electron)
+ [\#3992](https://github.com/vector-im/riot-web/pull/3992)
+ * Translations!
+ [\#4035](https://github.com/vector-im/riot-web/pull/4035)
+ * Kieran gould/12hourtimestamp
+ [\#3961](https://github.com/vector-im/riot-web/pull/3961)
+ * Don't include src in the test resolve root
+ [\#4033](https://github.com/vector-im/riot-web/pull/4033)
+ * add moar context menus [Electron]
+ [\#4021](https://github.com/vector-im/riot-web/pull/4021)
+ * Add `Chat` to Linux app categories
+ [\#4022](https://github.com/vector-im/riot-web/pull/4022)
+ * add menu category for linux build of app
+ [\#3975](https://github.com/vector-im/riot-web/pull/3975)
+ * Electron Tray Improvements
+ [\#3909](https://github.com/vector-im/riot-web/pull/3909)
+ * More riot-web test deflakification
+ [\#3966](https://github.com/vector-im/riot-web/pull/3966)
+ * Script to fetch corresponding branches of dependent projects
+ [\#3945](https://github.com/vector-im/riot-web/pull/3945)
+ * Add type="text/css" to SVG logos
+ [\#3964](https://github.com/vector-im/riot-web/pull/3964)
+ * Fix some setState-after-unmount in roomdirectory
+ [\#3958](https://github.com/vector-im/riot-web/pull/3958)
+ * Attempt to deflakify joining test
+ [\#3956](https://github.com/vector-im/riot-web/pull/3956)
+
+Changes in [0.9.10](https://github.com/vector-im/riot-web/releases/tag/v0.9.10) (2017-05-22)
+============================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.10-rc.1...v0.9.10)
+
+ * No changes
+
+
+Changes in [0.9.10-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.9.10-rc.1) (2017-05-19)
+======================================================================================================
+[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9...v0.9.10-rc.1)
+
+ * CSS for left_aligned Dropdowns, and adjustments for Country dd in Login
+ [\#3959](https://github.com/vector-im/riot-web/pull/3959)
+ * Add square flag pngs /w genflags.sh script
+ [\#3953](https://github.com/vector-im/riot-web/pull/3953)
+ * Add config for riot-bot on desktop app build
+ [\#3954](https://github.com/vector-im/riot-web/pull/3954)
+ * Desktop: 'copy link address'
+ [\#3952](https://github.com/vector-im/riot-web/pull/3952)
+ * Reduce rageshake log size to 1MB
+ [\#3943](https://github.com/vector-im/riot-web/pull/3943)
+ * CSS for putting country dd on same line as phone input
+ [\#3942](https://github.com/vector-im/riot-web/pull/3942)
+ * fix #3894
+ [\#3919](https://github.com/vector-im/riot-web/pull/3919)
+ * change vector->riot on the surface
+ [\#3894](https://github.com/vector-im/riot-web/pull/3894)
+ * move manifest.json outward so it is scoped properly
+ [\#3888](https://github.com/vector-im/riot-web/pull/3888)
+ * add to manifest
+ [\#3799](https://github.com/vector-im/riot-web/pull/3799)
+ * Automatically update component-index
+ [\#3886](https://github.com/vector-im/riot-web/pull/3886)
+ * move electron -> electron_app because npm smart
+ [\#3877](https://github.com/vector-im/riot-web/pull/3877)
+ * Fix bug report endpoint in config.sample.json.
+ [\#3863](https://github.com/vector-im/riot-web/pull/3863)
+ * Update 2 missed icons to the new icon
+ [\#3851](https://github.com/vector-im/riot-web/pull/3851)
+ * Make left panel better for new users (mk II)
+ [\#3804](https://github.com/vector-im/riot-web/pull/3804)
+ * match primary package.json
+ [\#3839](https://github.com/vector-im/riot-web/pull/3839)
+ * Re-add productName
+ [\#3829](https://github.com/vector-im/riot-web/pull/3829)
+ * Remove leading v in /version file, for SemVer and to match Electron ver
+ [\#3683](https://github.com/vector-im/riot-web/pull/3683)
+ * Fix scope of callback
+ [\#3790](https://github.com/vector-im/riot-web/pull/3790)
+ * Remember and Recall window layout/position state
+ [\#3622](https://github.com/vector-im/riot-web/pull/3622)
+ * Remove babelcheck
+ [\#3808](https://github.com/vector-im/riot-web/pull/3808)
+ * Include MXID and device id in rageshakes
+ [\#3809](https://github.com/vector-im/riot-web/pull/3809)
+ * import Modal
+ [\#3791](https://github.com/vector-im/riot-web/pull/3791)
+ * Pin filesize ver to fix break upstream
+ [\#3775](https://github.com/vector-im/riot-web/pull/3775)
+ * Improve Room Directory Look & Feel
+ [\#3751](https://github.com/vector-im/riot-web/pull/3751)
+ * Fix emote RRs alignment
+ [\#3742](https://github.com/vector-im/riot-web/pull/3742)
+ * Remove unused `placeholder` prop on RoomDropTarget
+ [\#3741](https://github.com/vector-im/riot-web/pull/3741)
+ * Modify CSS for matrix-org/matrix-react-sdk#833
+ [\#3732](https://github.com/vector-im/riot-web/pull/3732)
+ * Warn when exiting due to single-instance
+ [\#3727](https://github.com/vector-im/riot-web/pull/3727)
+ * Electron forgets it was maximized when you click on a notification
+ [\#3709](https://github.com/vector-im/riot-web/pull/3709)
+ * CSS to make h1 and h2 the same size as h1.
+ [\#3719](https://github.com/vector-im/riot-web/pull/3719)
+ * Prevent long room names/topics from pushing UI of the screen
+ [\#3721](https://github.com/vector-im/riot-web/pull/3721)
+ * Disable dropdown highlight on focus
+ [\#3717](https://github.com/vector-im/riot-web/pull/3717)
+ * Escape HTML Tags from Linux Notifications (electron)
+ [\#3564](https://github.com/vector-im/riot-web/pull/3564)
+ * styling for spoilerized access token view in Settings
+ [\#3651](https://github.com/vector-im/riot-web/pull/3651)
+ * Fix Webpack conf
+ [\#3690](https://github.com/vector-im/riot-web/pull/3690)
+ * Add config.json to .gitignore
+ [\#3599](https://github.com/vector-im/riot-web/pull/3599)
+ * add command line arg (--hidden) for electron app
+ [\#3641](https://github.com/vector-im/riot-web/pull/3641)
+ * fix ImageView Download functionality
+ [\#3640](https://github.com/vector-im/riot-web/pull/3640)
+ * Add cross-env into the mix
+ [\#3693](https://github.com/vector-im/riot-web/pull/3693)
+ * Remember acceptance for unsupported browsers.
+ [\#3694](https://github.com/vector-im/riot-web/pull/3694)
+ * Cosmetics to go with matrix-org/matrix-react-sdk#811
+ [\#3692](https://github.com/vector-im/riot-web/pull/3692)
+ * Cancel quicksearch on ESC
+ [\#3680](https://github.com/vector-im/riot-web/pull/3680)
+ * Optimise RoomList and implement quick-search functionality on it.
+ [\#3654](https://github.com/vector-im/riot-web/pull/3654)
+ * Progress updates for rageshake uploads
+ [\#3648](https://github.com/vector-im/riot-web/pull/3648)
+ * Factor out rageshake upload to a separate file
+ [\#3645](https://github.com/vector-im/riot-web/pull/3645)
+ * rageshake: fix race when collecting logs
+ [\#3644](https://github.com/vector-im/riot-web/pull/3644)
+ * Fix a flaky test
+ [\#3649](https://github.com/vector-im/riot-web/pull/3649)
+
Changes in [0.9.9](https://github.com/vector-im/riot-web/releases/tag/v0.9.9) (2017-04-25)
==========================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.9.9-rc.2...v0.9.9)
diff --git a/README.md b/README.md
index 2d7ab81b..89f2148f 100644
--- a/README.md
+++ b/README.md
@@ -55,32 +55,41 @@ Building From Source
Riot is a modular webapp built with modern ES6 and requires a npm build system
to build.
-1. Install or update `node.js` so that your `npm` is at least at version `2.0.0`
-1. Clone the repo: `git clone https://github.com/vector-im/riot-web.git`
-1. Switch to the riot-web directory: `cd riot-web`
-1. Install the prerequisites: `npm install`
-1. If you are using the `develop` branch of vector-web, you will probably need
- to rebuild some of the dependencies, due to
- https://github.com/npm/npm/issues/3055:
-
+1. Install or update `node.js` so that your `node` is at least v6.3.0 (and `npm`
+ is at least v3.10.x).
+1. Clone the repo: `git clone https://github.com/vector-im/riot-web.git`.
+1. Switch to the riot-web directory: `cd riot-web`.
+1. If you're using the `develop` branch, install the develop versions of the
+ dependencies, as the released ones will be too old:
```
- (cd node_modules/matrix-js-sdk && npm install)
- (cd node_modules/matrix-react-sdk && npm install)
+ scripts/fetch-develop-deps.sh
```
Whenever you git pull on riot-web you will also probably need to force an update
- to these dependencies - the easiest way is probably:
+ to these dependencies - the simplest way is to re-run the script, but you can also
+ manually update and rebuild them:
```
- rm -rf node_modules/matrjx-{js,react}-sdk && npm i
- (cd node_modules/matrix-js-sdk && npm install)
- (cd node_modules/matrix-react-sdk && npm install)
+ cd matrix-js-sdk
+ git pull
+ npm install # re-run to pull in any new dependencies
+ # Depending on your version of npm, npm run build may happen as part of
+ # the npm install above (https://docs.npmjs.com/misc/scripts#prepublish-and-prepare)
+ # If in doubt, run it anyway:
+ npm run build
+ cd ../matrix-react-sdk
+ git pull
+ npm install
+ npm run build
```
However, we recommend setting up a proper development environment (see "Setting
up a development environment" below) if you want to run your own copy of the
`develop` branch, as it makes it much easier to keep these dependencies
up-to-date. Or just use https://riot.im/develop - the continuous integration
release of the develop branch.
+ (Note that we don't reference the develop versions in git directly due to
+ https://github.com/npm/npm/issues/3055.)
+1. Install the prerequisites: `npm install`.
1. Configure the app by copying `config.sample.json` to `config.json` and
- modifying it (see below for details)
+ modifying it (see below for details).
1. `npm run dist` to build a tarball to deploy. Untaring this file will give
a version-specific directory containing all the files that need to go on your
web server.
@@ -125,7 +134,7 @@ Running as a Desktop app
Riot can also be run as a desktop app, wrapped in electron. You can download a
pre-built version from https://riot.im/desktop.html or, if you prefer,
-built it yourself.
+build it yourself. Requires Electron >=1.6.0
To run as a desktop app:
@@ -135,7 +144,7 @@ To run as a desktop app:
```
npm install electron
- node_modules/.bin/electron .
+ npm run electron
```
To build packages, use electron-builder. This is configured to output:
@@ -273,6 +282,19 @@ If any of these steps error with, `file table overflow`, you are probably on a m
which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again.
You'll need to do this in each new terminal you open before building Riot.
+How to add a new translation?
+=============================
+
+[](https://translate.riot.im/engage/riot-web/?utm_source=widget)
+
+
+Head to the [translating doc](docs/translating.md)
+
+Adding Strings to the translations (Developer Guide)
+====================================================
+
+Head to the [translating dev doc](docs/translating-dev.md)
+
Triaging issues
===============
@@ -292,7 +314,7 @@ bug or feature:
* feature
bug severity:
-
+
* cosmetic - feature works functionally but UI/UX is broken
* critical - whole app doesn't work
* major - entire feature doesn't work
diff --git a/config.sample.json b/config.sample.json
index 94df4943..a4477ea1 100644
--- a/config.sample.json
+++ b/config.sample.json
@@ -4,12 +4,17 @@
"brand": "Riot",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
- "bug_report_endpoint_url": "https://vector.im/bugs",
+ "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
"enableLabs": true,
"default_federate": true,
"roomDirectory": {
"servers": [
"matrix.org"
]
+ },
+ "welcomeUserId": "@riot-bot:matrix.org",
+ "piwik": {
+ "url": "https://piwik.riot.im/",
+ "siteId": 1
}
}
diff --git a/docs/translating-dev.md b/docs/translating-dev.md
new file mode 100644
index 00000000..55ba34be
--- /dev/null
+++ b/docs/translating-dev.md
@@ -0,0 +1,26 @@
+# How to translate riot-web (Dev Guide)
+
+## Requirements
+
+- A working [Development Setup](../../#setting-up-a-dev-environment)
+- Be able to understand English
+- Be able to understand the language you want to translate riot-web into
+
+## Adding new strings
+
+1. Check if the import ``import { _t } from 'matrix-react-sdk/lib/languageHandler';`` is present. If not add it to the other import statements.
+2. Add ``_t()`` to your string. (Don't forget curly braces when you assign an expression to JSX attributes in the render method)
+3. Add the String to the ``en_EN.json`` file in ``src/i18n/strings`` (respect which repository you are on).
+
+## Adding variables inside a string.
+
+1. Extend your ``_t()`` call. Instead of ``_t(STRING)`` use ``_t(STRING, {})``
+2. Decide how to name it. Please think about if the person who has to translate it can understand what it does.
+3. Add it to the array in ``_t`` for example ``_t(STRING, {variable: this.variable})``
+4. Add the variable inside the string. The syntax for variables is ``%(variable)s``. Please note the s at the end. The name of the variable has to match the previous used name.
+
+## Things to know/Style Guides
+
+- Do not use it inside ``getDefaultProps`` at the point where ``getDefaultProps`` is initialized the translations aren't loaded yet and it causes missing translations.
+- If using translated strings as constants, translated strings can't be in constants loaded at class-load time since the translations won't be loaded.
+- If a string is presented in the UI with punctuation like a full stop, include this in the translation strings, since punctuation varies between languages too.
diff --git a/docs/translating.md b/docs/translating.md
new file mode 100644
index 00000000..3fd0731d
--- /dev/null
+++ b/docs/translating.md
@@ -0,0 +1,64 @@
+# How to translate riot-web
+
+## Requirements
+
+- Web Browser
+- Be able to understand English
+- Be able to understand the language you want to translate riot-web into
+
+## Step 0: Join #riotweb-translations:matrix.org
+
+1. Come and join https://matrix.to/#/#riotweb-translations:matrix.org
+2. Read scrollback and/or ask if anyone else is working on your language, and co-ordinate if needed. In general little-or-no coordination is needed though :)
+
+## Step 1: Preparing your Weblate Profile
+
+1. Head to https://translate.riot.im and register either via Github or email
+2. After registering check if you got an email to verify your account and click the link (if there is none head to step 1.4)
+3. Log into weblate
+4. Head to https://translate.riot.im/accounts/profile/ and select the languages you know and maybe another language you know too.
+6. Head to https://translate.riot.im/accounts/profile/#subscriptions and select Riot Web as Project
+
+## How to check if your language already is being translated
+
+Go to https://translate.riot.im/projects/riot-web/ and visit the 2 sub-projects.
+If your language is listed go to Step 2a and if not go to Step 2b
+
+## Step 2a: Helping on existing languages.
+
+1. Head to one of the projects listed https://translate.riot.im/projects/riot-web/
+2. Click on the ``translate`` button on the right side of your language
+3. Fill in the translations in the writeable field. You will see the original English string and the string of your second language above.
+
+Head to the explanations under Steb 2b
+
+## Step 2b: Adding a new language
+
+1. Go to one of the projects listed https://translate.riot.im/projects/riot-web/
+2. Click the ``Start new language`` button at the bottom
+3. Select a language
+4. Start translating like in 2a.3
+5. Repeat these steps for the other projects which are listed at the link of step 2b.1
+
+### What means the green button under the text field?
+
+The green button let you save our translations directly. Please only use it if you are 100% sure about that translation. If you do not know a translation please DO NOT click that button. Use the arrows above the translations field and click to the right.
+
+### What means the yellow button under the text field?
+
+The yellow button has to be used if you are unsure about the translation but you have a rough idea. It adds a new suggestion to the string which can than be reviewed by others.
+
+### What are "%(something)s"?
+
+These things are variables that are expanded when displayed by Riot. They can be room names, usernames or similar. If you find one, you can move to the right place for your language, but not delete it as the variable will be missing if you do.
+
+A special case is `%(urlStart)s` and `%(urlEnd)s` which are used to mark the beginning of a hyperlink (i.e. `` and ``. You must keep these markers surrounding the equivalent string in your language that needs to be hyperlinked.
+
+### "I want to come back to this string. How?"
+
+You can use inside the translation field "Review needed" checkbox. It will be shown as Strings that need to be reviewed.
+
+
+### Further reading
+
+The official Weblate doc provides some more in-deepth explanation on how to do translations and talks about do and don'ts. You can find it at: https://docs.weblate.org/en/latest/user/translating.html
diff --git a/electron/img/riot.ico b/electron/img/riot.ico
deleted file mode 100644
index 8b681ffb..00000000
Binary files a/electron/img/riot.ico and /dev/null differ
diff --git a/electron/img/riot.png b/electron/img/riot.png
deleted file mode 100644
index fe13aa99..00000000
Binary files a/electron/img/riot.png and /dev/null differ
diff --git a/electron/riot.im/config.json b/electron/riot.im/config.json
deleted file mode 100644
index c5bc65e1..00000000
--- a/electron/riot.im/config.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "update_base_url": "https://riot.im/download/desktop/update/",
- "default_hs_url": "https://matrix.org",
- "default_is_url": "https://vector.im",
- "brand": "Riot",
- "integrations_ui_url": "https://scalar.vector.im/",
- "integrations_rest_url": "https://scalar.vector.im/api",
- "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
- "enableLabs": true,
- "roomDirectory": {
- "servers": [
- "matrix.org"
- ],
- "serverConfig": {
- "matrix.org": {
- "networks": [
- "_matrix",
- "gitter",
- "irc:freenode",
- "irc:mozilla",
- "irc:snoonet",
- "irc:oftc"
- ]
- }
- },
- "networks": {
- "gitter": {
- "protocol": "gitter",
- "portalRoomPattern": "#gitter_.*:matrix.org",
- "name": "Gitter",
- "icon": "https://gitter.im/favicon.ico",
- "example": "org/community",
- "nativePattern": "[^\\s]+/[^\\s]+$"
- },
- "irc:freenode": {
- "protocol": "irc",
- "domain": "chat.freenode.net",
- "portalRoomPattern": "#freenode_.*:matrix.org",
- "name": "Freenode",
- "icon": "https://matrix.org/_matrix/media/v1/download/matrix.org/DHLHpDDgWNNejFmrewvwEAHX",
- "example": "#channel",
- "nativePattern": "^#[^\\s]+$"
- },
- "irc:mozilla": {
- "protocol": "irc",
- "domain": "chat.freenode.net",
- "portalRoomPattern": "#mozilla_.*:matrix.org",
- "name": "Mozilla",
- "icon": "https://matrix.org/_matrix/media/v1/download/matrix.org/DHLHpDDgWNNejFmrewvwEAHX",
- "example": "#channel",
- "nativePattern": "^#[^\\s]+$"
- },
- "irc:snoonet": {
- "protocol": "irc",
- "domain": "ipv6-irc.snoonet.org",
- "portalRoomPattern": "#_snoonet_.*:matrix.org",
- "name": "Snoonet",
- "icon": "https://matrix.org/_matrix/media/v1/download/matrix.org/DHLHpDDgWNNejFmrewvwEAHX",
- "example": "#channel",
- "nativePattern": "^#[^\\s]+$"
- },
- "irc:oftc": {
- "protocol": "irc",
- "domain": "irc.oftc.net",
- "portalRoomPattern": "#_oftc_.*:matrix.org",
- "name": "OFTC",
- "icon": "https://matrix.org/_matrix/media/v1/download/matrix.org/DHLHpDDgWNNejFmrewvwEAHX",
- "example": "#channel",
- "nativePattern": "^#[^\\s]+$"
- }
- }
- }
-}
diff --git a/electron/src/tray.js b/electron/src/tray.js
deleted file mode 100644
index 2ccdf40c..00000000
--- a/electron/src/tray.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-Copyright 2017 Karl Glatz
-Copyright 2017 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-const path = require('path');
-const electron = require('electron');
-
-const app = electron.app;
-const Tray = electron.Tray;
-const MenuItem = electron.MenuItem;
-
-let trayIcon = null;
-
-exports.hasTray = function hasTray() {
- return (trayIcon !== null);
-}
-
-exports.create = function (win, config) {
- // no trays on darwin
- if (process.platform === 'darwin' || trayIcon) {
- return;
- }
-
- const toggleWin = function () {
- if (win.isVisible() && !win.isMinimized()) {
- win.hide();
- } else {
- if (win.isMinimized()) win.restore();
- if (!win.isVisible()) win.show();
- win.focus();
- }
- };
-
- const contextMenu = electron.Menu.buildFromTemplate([
- {
- label: 'Show/Hide ' + config.brand,
- click: toggleWin
- },
- {
- type: 'separator'
- },
- {
- label: 'Quit',
- click: function () {
- app.quit();
- }
- }
- ]);
-
- trayIcon = new Tray(config.icon_path);
- trayIcon.setToolTip(config.brand);
- trayIcon.setContextMenu(contextMenu);
- trayIcon.on('click', toggleWin);
-};
diff --git a/electron/src/vectormenu.js b/electron/src/vectormenu.js
deleted file mode 100644
index 70ed3ac3..00000000
--- a/electron/src/vectormenu.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-Copyright 2016 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-const electron = require('electron');
-
-// Menu template from http://electron.atom.io/docs/api/menu/, edited
-const template = [
- {
- label: 'Edit',
- submenu: [
- {
- role: 'undo'
- },
- {
- role: 'redo'
- },
- {
- type: 'separator'
- },
- {
- role: 'cut'
- },
- {
- role: 'copy'
- },
- {
- role: 'paste'
- },
- {
- role: 'pasteandmatchstyle'
- },
- {
- role: 'delete'
- },
- {
- role: 'selectall'
- }
- ]
- },
- {
- label: 'View',
- submenu: [
- {
- type: 'separator'
- },
- {
- role: 'resetzoom'
- },
- {
- role: 'zoomin'
- },
- {
- role: 'zoomout'
- },
- {
- type: 'separator'
- },
- {
- role: 'togglefullscreen'
- },
- {
- role: 'toggledevtools'
- }
- ]
- },
- {
- role: 'window',
- submenu: [
- {
- role: 'minimize'
- },
- {
- role: 'close'
- }
- ]
- },
- {
- role: 'help',
- submenu: [
- {
- label: 'riot.im',
- click () { electron.shell.openExternal('https://riot.im/') }
- }
- ]
- }
-];
-
-// macOS has specific menu conventions...
-if (process.platform === 'darwin') {
- // first macOS menu is the name of the app
- const name = electron.app.getName()
- template.unshift({
- label: name,
- submenu: [
- {
- role: 'about'
- },
- {
- type: 'separator'
- },
- {
- role: 'services',
- submenu: []
- },
- {
- type: 'separator'
- },
- {
- role: 'hide'
- },
- {
- role: 'hideothers'
- },
- {
- role: 'unhide'
- },
- {
- type: 'separator'
- },
- {
- role: 'quit'
- }
- ]
- })
- // Edit menu.
- // This has a 'speech' section on macOS
- template[1].submenu.push(
- {
- type: 'separator'
- },
- {
- label: 'Speech',
- submenu: [
- {
- role: 'startspeaking'
- },
- {
- role: 'stopspeaking'
- }
- ]
- }
- )
- // Window menu.
- // This also has specific functionality on macOS
- template[3].submenu = [
- {
- label: 'Close',
- accelerator: 'CmdOrCtrl+W',
- role: 'close'
- },
- {
- label: 'Minimize',
- accelerator: 'CmdOrCtrl+M',
- role: 'minimize'
- },
- {
- label: 'Zoom',
- role: 'zoom'
- },
- {
- type: 'separator'
- },
- {
- label: 'Bring All to Front',
- role: 'front'
- }
- ]
-} else {
- template.unshift({
- label: 'File',
- submenu: [
- // For some reason, 'about' does not seem to work on windows.
- /*{
- role: 'about'
- },*/
- {
- role: 'quit'
- }
- ]
- });
-}
-
-module.exports = electron.Menu.buildFromTemplate(template)
-
diff --git a/electron/build/icon.icns b/electron_app/build/icon.icns
similarity index 100%
rename from electron/build/icon.icns
rename to electron_app/build/icon.icns
diff --git a/electron/build/icon.ico b/electron_app/build/icon.ico
similarity index 100%
rename from electron/build/icon.ico
rename to electron_app/build/icon.ico
diff --git a/electron/build/icons/128x128.png b/electron_app/build/icons/128x128.png
similarity index 100%
rename from electron/build/icons/128x128.png
rename to electron_app/build/icons/128x128.png
diff --git a/electron/build/icons/16x16.png b/electron_app/build/icons/16x16.png
similarity index 100%
rename from electron/build/icons/16x16.png
rename to electron_app/build/icons/16x16.png
diff --git a/electron/build/icons/24x24.png b/electron_app/build/icons/24x24.png
similarity index 100%
rename from electron/build/icons/24x24.png
rename to electron_app/build/icons/24x24.png
diff --git a/electron/build/icons/256x256.png b/electron_app/build/icons/256x256.png
similarity index 100%
rename from electron/build/icons/256x256.png
rename to electron_app/build/icons/256x256.png
diff --git a/electron/build/icons/48x48.png b/electron_app/build/icons/48x48.png
similarity index 100%
rename from electron/build/icons/48x48.png
rename to electron_app/build/icons/48x48.png
diff --git a/electron/build/icons/512x512.png b/electron_app/build/icons/512x512.png
similarity index 100%
rename from electron/build/icons/512x512.png
rename to electron_app/build/icons/512x512.png
diff --git a/electron/build/icons/64x64.png b/electron_app/build/icons/64x64.png
similarity index 100%
rename from electron/build/icons/64x64.png
rename to electron_app/build/icons/64x64.png
diff --git a/electron/build/icons/96x96.png b/electron_app/build/icons/96x96.png
similarity index 100%
rename from electron/build/icons/96x96.png
rename to electron_app/build/icons/96x96.png
diff --git a/electron/build/install-spinner.gif b/electron_app/build/install-spinner.gif
similarity index 100%
rename from electron/build/install-spinner.gif
rename to electron_app/build/install-spinner.gif
diff --git a/electron_app/img/riot.ico b/electron_app/img/riot.ico
new file mode 100644
index 00000000..8f8ff94e
Binary files /dev/null and b/electron_app/img/riot.ico differ
diff --git a/electron_app/img/riot.png b/electron_app/img/riot.png
new file mode 100644
index 00000000..85e9f8ca
Binary files /dev/null and b/electron_app/img/riot.png differ
diff --git a/electron_app/package.json b/electron_app/package.json
new file mode 100644
index 00000000..2c6e62f2
--- /dev/null
+++ b/electron_app/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "riot-web",
+ "productName": "Riot",
+ "main": "src/electron-main.js",
+ "version": "0.11.4",
+ "description": "A feature-rich client for Matrix.org",
+ "author": "Vector Creations Ltd.",
+ "dependencies": {
+ "auto-launch": "^5.0.1",
+ "electron-window-state": "^4.1.0",
+ "minimist": "^1.2.0",
+ "png-to-ico": "^1.0.2"
+ }
+}
diff --git a/electron/riot.im/README b/electron_app/riot.im/README
similarity index 100%
rename from electron/riot.im/README
rename to electron_app/riot.im/README
diff --git a/electron_app/riot.im/config.json b/electron_app/riot.im/config.json
new file mode 100644
index 00000000..1303985e
--- /dev/null
+++ b/electron_app/riot.im/config.json
@@ -0,0 +1,20 @@
+{
+ "update_base_url": "https://riot.im/download/desktop/update/",
+ "default_hs_url": "https://matrix.org",
+ "default_is_url": "https://vector.im",
+ "brand": "Riot",
+ "integrations_ui_url": "https://scalar.vector.im/",
+ "integrations_rest_url": "https://scalar.vector.im/api",
+ "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
+ "welcomeUserId": "@riot-bot:matrix.org",
+ "enableLabs": true,
+ "roomDirectory": {
+ "servers": [
+ "matrix.org"
+ ]
+ },
+ "piwik": {
+ "url": "https://piwik.riot.im/",
+ "siteId": 1
+ }
+}
diff --git a/electron/src/electron-main.js b/electron_app/src/electron-main.js
similarity index 52%
rename from electron/src/electron-main.js
rename to electron_app/src/electron-main.js
index 33b44ce9..3491ce0f 100644
--- a/electron/src/electron-main.js
+++ b/electron_app/src/electron-main.js
@@ -1,8 +1,7 @@
-// @flow
-
/*
Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd
+Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -20,15 +19,22 @@ limitations under the License.
// Squirrel on windows starts the app with various flags
// as hooks to tell us when we've been installed/uninstalled
// etc.
-const check_squirrel_hooks = require('./squirrelhooks');
-if (check_squirrel_hooks()) return;
+const checkSquirrelHooks = require('./squirrelhooks');
+if (checkSquirrelHooks()) return;
+const argv = require('minimist')(process.argv);
const electron = require('electron');
-const url = require('url');
+const AutoLaunch = require('auto-launch');
const tray = require('./tray');
+const vectorMenu = require('./vectormenu');
+const webContentsHandler = require('./webcontents-handler');
-const VectorMenu = require('./vectormenu');
+const windowStateKeeper = require('electron-window-state');
+
+if (argv.profile) {
+ electron.app.setPath('userData', `${electron.app.getPath('userData')}-${argv.profile}`);
+}
let vectorConfig = {};
try {
@@ -40,54 +46,12 @@ try {
// Continue with the defaults (ie. an empty config)
}
-const PERMITTED_URL_SCHEMES = [
- 'http:',
- 'https:',
- 'mailto:',
-];
-
const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000;
const INITIAL_UPDATE_DELAY_MS = 30 * 1000;
let mainWindow = null;
let appQuitting = false;
-function safeOpenURL(target) {
- // openExternal passes the target to open/start/xdg-open,
- // so put fairly stringent limits on what can be opened
- // (for instance, open /bin/sh does indeed open a terminal
- // with a shell, albeit with no arguments)
- const parsed_url = url.parse(target);
- if (PERMITTED_URL_SCHEMES.indexOf(parsed_url.protocol) > -1) {
- // explicitly use the URL re-assembled by the url library,
- // so we know the url parser has understood all the parts
- // of the input string
- const new_target = url.format(parsed_url);
- electron.shell.openExternal(new_target);
- }
-}
-
-function onWindowOrNavigate(ev, target) {
- // always prevent the default: if something goes wrong,
- // we don't want to end up opening it in the electron
- // app, as we could end up opening any sort of random
- // url in a window that has node scripting access.
- ev.preventDefault();
- safeOpenURL(target);
-}
-
-function onLinkContextMenu(ev, params) {
- const popup_menu = new electron.Menu();
- popup_menu.append(new electron.MenuItem({
- label: params.linkURL,
- click() {
- safeOpenURL(params.linkURL);
- },
- }));
- popup_menu.popup();
- ev.preventDefault();
-}
-
function installUpdate() {
// for some reason, quitAndInstall does not fire the
// before-quit event, so we need to set the flag here.
@@ -99,13 +63,13 @@ function pollForUpdates() {
try {
electron.autoUpdater.checkForUpdates();
} catch (e) {
- console.log("Couldn't check for update", e);
+ console.log('Couldn\'t check for update', e);
}
}
-function startAutoUpdate(update_base_url) {
- if (update_base_url.slice(-1) !== '/') {
- update_base_url = update_base_url + '/';
+function startAutoUpdate(updateBaseUrl) {
+ if (updateBaseUrl.slice(-1) !== '/') {
+ updateBaseUrl = updateBaseUrl + '/';
}
try {
// For reasons best known to Squirrel, the way it checks for updates
@@ -113,7 +77,7 @@ function startAutoUpdate(update_base_url) {
// hits a URL that either gives it a 200 with some json or
// 204 No Content. On windows it takes a base path and looks for
// files under that path.
- if (process.platform == 'darwin') {
+ if (process.platform === 'darwin') {
// include the current version in the URL we hit. Electron doesn't add
// it anywhere (apart from the User-Agent) so it's up to us. We could
// (and previously did) just use the User-Agent, but this doesn't
@@ -121,16 +85,15 @@ function startAutoUpdate(update_base_url) {
// and also acts as a convenient cache-buster to ensure that when the
// app updates it always gets a fresh value to avoid update-looping.
electron.autoUpdater.setFeedURL(
- update_base_url +
- 'macos/?localVersion=' + encodeURIComponent(electron.app.getVersion())
- );
- } else if (process.platform == 'win32') {
- electron.autoUpdater.setFeedURL(update_base_url + 'win32/' + process.arch + '/');
+ `${updateBaseUrl}macos/?localVersion=${encodeURIComponent(electron.app.getVersion())}`);
+
+ } else if (process.platform === 'win32') {
+ electron.autoUpdater.setFeedURL(`${updateBaseUrl}win32/${process.arch}/`);
} else {
// Squirrel / electron only supports auto-update on these two platforms.
// I'm not even going to try to guess which feed style they'd use if they
// implemented it on Linux, or if it would be different again.
- console.log("Auto update not supported on this platform");
+ console.log('Auto update not supported on this platform');
}
// We check for updates ourselves rather than using 'updater' because we need to
// do it in the main process (and we don't really need to check every 10 minutes:
@@ -143,7 +106,7 @@ function startAutoUpdate(update_base_url) {
setInterval(pollForUpdates, UPDATE_POLL_INTERVAL_MS);
} catch (err) {
// will fail if running in debug mode
- console.log("Couldn't enable update checking", err);
+ console.log('Couldn\'t enable update checking', err);
}
}
@@ -153,12 +116,49 @@ function startAutoUpdate(update_base_url) {
// no other way to catch this error).
// Assuming we generally run from the console when developing,
// this is far preferable.
-process.on('uncaughtException', function (error) {
- console.log("Unhandled exception", error);
+process.on('uncaughtException', function(error) {
+ console.log('Unhandled exception', error);
});
electron.ipcMain.on('install_update', installUpdate);
+let focusHandlerAttached = false;
+electron.ipcMain.on('setBadgeCount', function(ev, count) {
+ electron.app.setBadgeCount(count);
+ if (count === 0) {
+ mainWindow.flashFrame(false);
+ }
+});
+
+electron.ipcMain.on('loudNotification', function() {
+ if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) {
+ mainWindow.flashFrame(true);
+ mainWindow.once('focus', () => {
+ mainWindow.flashFrame(false);
+ focusHandlerAttached = false;
+ });
+ focusHandlerAttached = true;
+ }
+});
+
+let powerSaveBlockerId;
+electron.ipcMain.on('app_onAction', function(ev, payload) {
+ switch (payload.action) {
+ case 'call_state':
+ if (powerSaveBlockerId && powerSaveBlockerId.isStarted(powerSaveBlockerId)) {
+ if (payload.state === 'ended') {
+ electron.powerSaveBlocker.stop(powerSaveBlockerId);
+ }
+ } else {
+ if (payload.state === 'connected') {
+ powerSaveBlockerId = electron.powerSaveBlocker.start('prevent-display-sleep');
+ }
+ }
+ break;
+ }
+});
+
+
electron.app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirectory) => {
@@ -171,44 +171,115 @@ const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirector
});
if (shouldQuit) {
- electron.app.quit()
+ console.log('Other instance detected: exiting');
+ electron.app.exit();
}
+
+const launcher = new AutoLaunch({
+ name: vectorConfig.brand || 'Riot',
+ isHidden: true,
+ mac: {
+ useLaunchAgent: true,
+ },
+});
+
+const settings = {
+ 'auto-launch': {
+ get: launcher.isEnabled,
+ set: function(bool) {
+ if (bool) {
+ return launcher.enable();
+ } else {
+ return launcher.disable();
+ }
+ },
+ },
+};
+
+electron.ipcMain.on('settings_get', async function(ev) {
+ const data = {};
+
+ try {
+ await Promise.all(Object.keys(settings).map(async function (setting) {
+ data[setting] = await settings[setting].get();
+ }));
+
+ ev.sender.send('settings', data);
+ } catch(e) { console.error(e); }
+});
+
+electron.ipcMain.on('settings_set', function(ev, key, value) {
+ console.log(key, value);
+ if (settings[key] && settings[key].set) {
+ settings[key].set(value);
+ }
+});
+
electron.app.on('ready', () => {
- if (vectorConfig.update_base_url) {
- console.log("Starting auto update with base URL: " + vectorConfig.update_base_url);
- startAutoUpdate(vectorConfig.update_base_url);
- } else {
- console.log("No update_base_url is defined: auto update is disabled");
+
+ if (argv.devtools) {
+ try {
+ const { default: installExtension, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer');
+ installExtension(REACT_DEVELOPER_TOOLS)
+ .then((name) => console.log(`Added Extension: ${name}`))
+ .catch((err) => console.log('An error occurred: ', err));
+ installExtension(REACT_PERF)
+ .then((name) => console.log(`Added Extension: ${name}`))
+ .catch((err) => console.log('An error occurred: ', err));
+ } catch(e) {console.log(e);}
}
- const icon_path = `${__dirname}/../img/riot.` + (
- process.platform == 'win32' ? 'ico' : 'png'
- );
+
+ if (vectorConfig.update_base_url) {
+ console.log(`Starting auto update with base URL: ${vectorConfig.update_base_url}`);
+ startAutoUpdate(vectorConfig.update_base_url);
+ } else {
+ console.log('No update_base_url is defined: auto update is disabled');
+ }
+
+ const iconPath = `${__dirname}/../img/riot.${process.platform === 'win32' ? 'ico' : 'png'}`;
+
+ // Load the previous window state with fallback to defaults
+ const mainWindowState = windowStateKeeper({
+ defaultWidth: 1024,
+ defaultHeight: 768,
+ });
mainWindow = new electron.BrowserWindow({
- icon: icon_path,
- width: 1024, height: 768,
+ icon: iconPath,
show: false,
autoHideMenuBar: true,
+
+ x: mainWindowState.x,
+ y: mainWindowState.y,
+ width: mainWindowState.width,
+ height: mainWindowState.height,
});
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
- electron.Menu.setApplicationMenu(VectorMenu);
+ electron.Menu.setApplicationMenu(vectorMenu);
+
+ // explicitly hide because setApplicationMenu on Linux otherwise shows...
+ // https://github.com/electron/electron/issues/9621
+ mainWindow.hide();
// Create trayIcon icon
tray.create(mainWindow, {
- icon_path: icon_path,
- brand: vectorConfig.brand || 'Riot'
+ icon_path: iconPath,
+ brand: vectorConfig.brand || 'Riot',
});
- mainWindow.once('ready-to-show', () => {
- mainWindow.show();
- });
+ if (!argv.hidden) {
+ mainWindow.once('ready-to-show', () => {
+ mainWindow.show();
+ });
+ }
+
mainWindow.on('closed', () => {
mainWindow = null;
});
mainWindow.on('close', (e) => {
- if (!appQuitting && (tray.hasTray() || process.platform == 'darwin')) {
+ if (!appQuitting && (tray.hasTray() || process.platform === 'darwin')) {
// On Mac, closing the window just hides it
// (this is generally how single-window Mac apps
// behave, eg. Mail.app)
@@ -218,14 +289,8 @@ electron.app.on('ready', () => {
}
});
- mainWindow.webContents.on('new-window', onWindowOrNavigate);
- mainWindow.webContents.on('will-navigate', onWindowOrNavigate);
-
- mainWindow.webContents.on('context-menu', function(ev, params) {
- if (params.linkURL) {
- onLinkContextMenu(ev, params);
- }
- });
+ webContentsHandler(mainWindow.webContents);
+ mainWindowState.manage(mainWindow);
});
electron.app.on('window-all-closed', () => {
diff --git a/electron/src/squirrelhooks.js b/electron_app/src/squirrelhooks.js
similarity index 77%
rename from electron/src/squirrelhooks.js
rename to electron_app/src/squirrelhooks.js
index 15ed670f..728c9cfb 100644
--- a/electron/src/squirrelhooks.js
+++ b/electron_app/src/squirrelhooks.js
@@ -16,30 +16,30 @@ limitations under the License.
const path = require('path');
const spawn = require('child_process').spawn;
-const app = require('electron').app;
+const {app} = require('electron');
-function run_update_exe(args, done) {
+function runUpdateExe(args, done) {
// Invokes Squirrel's Update.exe which will do things for us like create shortcuts
// Note that there's an Update.exe in the app-x.x.x directory and one in the parent
// directory: we need to run the one in the parent directory, because it discovers
// information about the app by inspecting the directory it's run from.
const updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');
- console.log('Spawning `%s` with args `%s`', updateExe, args);
+ console.log(`Spawning '${updateExe}' with args '${args}'`);
spawn(updateExe, args, {
- detached: true
+ detached: true,
}).on('close', done);
-};
+}
-function check_squirrel_hooks() {
- if (process.platform != 'win32') return false;
+function checkSquirrelHooks() {
+ if (process.platform !== 'win32') return false;
const cmd = process.argv[1];
const target = path.basename(process.execPath);
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
- run_update_exe(['--createShortcut=' + target + ''], app.quit);
+ runUpdateExe(['--createShortcut=' + target + ''], app.quit);
return true;
} else if (cmd === '--squirrel-uninstall') {
- run_update_exe(['--removeShortcut=' + target + ''], app.quit);
+ runUpdateExe(['--removeShortcut=' + target + ''], app.quit);
return true;
} else if (cmd === '--squirrel-obsolete') {
app.quit();
@@ -48,4 +48,4 @@ function check_squirrel_hooks() {
return false;
}
-module.exports = check_squirrel_hooks;
+module.exports = checkSquirrelHooks;
diff --git a/electron_app/src/tray.js b/electron_app/src/tray.js
new file mode 100644
index 00000000..039e7133
--- /dev/null
+++ b/electron_app/src/tray.js
@@ -0,0 +1,94 @@
+/*
+Copyright 2017 Karl Glatz
+Copyright 2017 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+const {app, Tray, Menu, nativeImage} = require('electron');
+const pngToIco = require('png-to-ico');
+const path = require('path');
+const fs = require('fs');
+
+let trayIcon = null;
+
+exports.hasTray = function hasTray() {
+ return (trayIcon !== null);
+};
+
+exports.create = function(win, config) {
+ // no trays on darwin
+ if (process.platform === 'darwin' || trayIcon) return;
+
+ const toggleWin = function() {
+ if (win.isVisible() && !win.isMinimized()) {
+ win.hide();
+ } else {
+ if (win.isMinimized()) win.restore();
+ if (!win.isVisible()) win.show();
+ win.focus();
+ }
+ };
+
+ const contextMenu = Menu.buildFromTemplate([
+ {
+ label: `Show/Hide ${config.brand}`,
+ click: toggleWin,
+ },
+ { type: 'separator' },
+ {
+ label: 'Quit',
+ click: function() {
+ app.quit();
+ },
+ },
+ ]);
+
+ trayIcon = new Tray(config.icon_path);
+ trayIcon.setToolTip(config.brand);
+ trayIcon.setContextMenu(contextMenu);
+ trayIcon.on('click', toggleWin);
+
+ let lastFavicon = null;
+ win.webContents.on('page-favicon-updated', async function(ev, favicons) {
+ let newFavicon = config.icon_path;
+ if (favicons && favicons.length > 0 && favicons[0].startsWith('data:')) {
+ newFavicon = favicons[0];
+ }
+
+ // No need to change, shortcut
+ if (newFavicon === lastFavicon) return;
+ lastFavicon = newFavicon;
+
+ // if its not default we have to construct into nativeImage
+ if (newFavicon !== config.icon_path) {
+ newFavicon = nativeImage.createFromDataURL(favicons[0]);
+
+ if (process.platform === 'win32') {
+ try {
+ const icoPath = path.join(app.getPath('temp'), 'win32_riot_icon.ico')
+ const icoBuf = await pngToIco(newFavicon.toPNG());
+ fs.writeFileSync(icoPath, icoBuf);
+ newFavicon = icoPath;
+ } catch (e) {console.error(e);}
+ }
+ }
+
+ trayIcon.setImage(newFavicon);
+ win.setIcon(newFavicon);
+ });
+
+ win.webContents.on('page-title-updated', function(ev, title) {
+ trayIcon.setToolTip(title);
+ });
+};
diff --git a/electron_app/src/vectormenu.js b/electron_app/src/vectormenu.js
new file mode 100644
index 00000000..ab30b376
--- /dev/null
+++ b/electron_app/src/vectormenu.js
@@ -0,0 +1,137 @@
+/*
+Copyright 2016 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+const {app, shell, Menu} = require('electron');
+
+// Menu template from http://electron.atom.io/docs/api/menu/, edited
+const template = [
+ {
+ label: 'Edit',
+ submenu: [
+ { role: 'undo' },
+ { role: 'redo' },
+ { type: 'separator' },
+ { role: 'cut' },
+ { role: 'copy' },
+ { role: 'paste' },
+ { role: 'pasteandmatchstyle' },
+ { role: 'delete' },
+ { role: 'selectall' },
+ ],
+ },
+ {
+ label: 'View',
+ submenu: [
+ { type: 'separator' },
+ { role: 'resetzoom' },
+ { role: 'zoomin' },
+ { role: 'zoomout' },
+ { type: 'separator' },
+ { role: 'togglefullscreen' },
+ { role: 'toggledevtools' },
+ ],
+ },
+ {
+ role: 'window',
+ submenu: [
+ { role: 'minimize' },
+ { role: 'close' },
+ ],
+ },
+ {
+ role: 'help',
+ submenu: [
+ {
+ label: 'riot.im',
+ click() { shell.openExternal('https://riot.im/'); },
+ },
+ ],
+ },
+];
+
+// macOS has specific menu conventions...
+if (process.platform === 'darwin') {
+ // first macOS menu is the name of the app
+ const name = app.getName();
+ template.unshift({
+ label: name,
+ submenu: [
+ { role: 'about' },
+ { type: 'separator' },
+ {
+ role: 'services',
+ submenu: [],
+ },
+ { type: 'separator' },
+ { role: 'hide' },
+ { role: 'hideothers' },
+ { role: 'unhide' },
+ { type: 'separator' },
+ { role: 'quit' },
+ ],
+ });
+ // Edit menu.
+ // This has a 'speech' section on macOS
+ template[1].submenu.push(
+ { type: 'separator' },
+ {
+ label: 'Speech',
+ submenu: [
+ { role: 'startspeaking' },
+ { role: 'stopspeaking' },
+ ],
+ });
+
+ // Window menu.
+ // This also has specific functionality on macOS
+ template[3].submenu = [
+ {
+ label: 'Close',
+ accelerator: 'CmdOrCtrl+W',
+ role: 'close',
+ },
+ {
+ label: 'Minimize',
+ accelerator: 'CmdOrCtrl+M',
+ role: 'minimize',
+ },
+ {
+ label: 'Zoom',
+ role: 'zoom',
+ },
+ {
+ type: 'separator',
+ },
+ {
+ label: 'Bring All to Front',
+ role: 'front',
+ },
+ ];
+} else {
+ template.unshift({
+ label: 'File',
+ submenu: [
+ // For some reason, 'about' does not seem to work on windows.
+ /*{
+ role: 'about'
+ },*/
+ { role: 'quit' },
+ ],
+ });
+}
+
+module.exports = Menu.buildFromTemplate(template);
+
diff --git a/electron_app/src/webcontents-handler.js b/electron_app/src/webcontents-handler.js
new file mode 100644
index 00000000..37416ebe
--- /dev/null
+++ b/electron_app/src/webcontents-handler.js
@@ -0,0 +1,122 @@
+const {clipboard, nativeImage, Menu, MenuItem, shell} = require('electron');
+const url = require('url');
+
+const PERMITTED_URL_SCHEMES = [
+ 'http:',
+ 'https:',
+ 'mailto:',
+];
+
+function safeOpenURL(target) {
+ // openExternal passes the target to open/start/xdg-open,
+ // so put fairly stringent limits on what can be opened
+ // (for instance, open /bin/sh does indeed open a terminal
+ // with a shell, albeit with no arguments)
+ const parsedUrl = url.parse(target);
+ if (PERMITTED_URL_SCHEMES.indexOf(parsedUrl.protocol) > -1) {
+ // explicitly use the URL re-assembled by the url library,
+ // so we know the url parser has understood all the parts
+ // of the input string
+ const newTarget = url.format(parsedUrl);
+ shell.openExternal(newTarget);
+ }
+}
+
+function onWindowOrNavigate(ev, target) {
+ // always prevent the default: if something goes wrong,
+ // we don't want to end up opening it in the electron
+ // app, as we could end up opening any sort of random
+ // url in a window that has node scripting access.
+ ev.preventDefault();
+ safeOpenURL(target);
+}
+
+function onLinkContextMenu(ev, params) {
+ const url = params.linkURL || params.srcURL;
+
+ const popupMenu = new Menu();
+ popupMenu.append(new MenuItem({
+ label: url,
+ click() {
+ safeOpenURL(url);
+ },
+ }));
+
+ if (params.mediaType && params.mediaType === 'image' && !url.startsWith('file://')) {
+ popupMenu.append(new MenuItem({
+ label: 'Copy Image',
+ click() {
+ if (url.startsWith('data:')) {
+ clipboard.writeImage(nativeImage.createFromDataURL(url));
+ } else {
+ ev.sender.copyImageAt(params.x, params.y);
+ }
+ },
+ }));
+ }
+
+ popupMenu.append(new MenuItem({
+ label: 'Copy Link Address',
+ click() {
+ clipboard.writeText(url);
+ },
+ }));
+ popupMenu.popup();
+ ev.preventDefault();
+}
+
+function _CutCopyPasteSelectContextMenus(params) {
+ return [{
+ role: 'cut',
+ enabled: params.editFlags.canCut,
+ }, {
+ role: 'copy',
+ enabled: params.editFlags.canCopy,
+ }, {
+ role: 'paste',
+ enabled: params.editFlags.canPaste,
+ }, {
+ role: 'pasteandmatchstyle',
+ enabled: params.editFlags.canPaste,
+ }, {
+ role: 'selectall',
+ enabled: params.editFlags.canSelectAll,
+ }];
+}
+
+function onSelectedContextMenu(ev, params) {
+ const items = _CutCopyPasteSelectContextMenus(params);
+ const popupMenu = Menu.buildFromTemplate(items);
+
+ popupMenu.popup();
+ ev.preventDefault();
+}
+
+function onEditableContextMenu(ev, params) {
+ const items = [
+ { role: 'undo' },
+ { role: 'redo', enabled: params.editFlags.canRedo },
+ { type: 'separator' },
+ ].concat(_CutCopyPasteSelectContextMenus(params));
+
+ const popupMenu = Menu.buildFromTemplate(items);
+
+ popupMenu.popup();
+ ev.preventDefault();
+}
+
+
+module.exports = (webContents) => {
+ webContents.on('new-window', onWindowOrNavigate);
+ webContents.on('will-navigate', onWindowOrNavigate);
+
+ webContents.on('context-menu', function(ev, params) {
+ if (params.linkURL || params.srcURL) {
+ onLinkContextMenu(ev, params);
+ } else if (params.selectionText) {
+ onSelectedContextMenu(ev, params);
+ } else if (params.isEditable) {
+ onEditableContextMenu(ev, params);
+ }
+ });
+};
diff --git a/karma.conf.js b/karma.conf.js
index b0a48c92..1e043663 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -47,7 +47,6 @@ webpack_config.module.noParse.push(/sinon\/pkg\/sinon\.js$/);
webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js';
webpack_config.resolve.root = [
- path.resolve('./src'),
path.resolve('./test'),
];
diff --git a/package.json b/package.json
index 340ee805..f5129006 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "riot-web",
"productName": "Riot",
- "main": "electron/src/electron-main.js",
- "version": "0.9.9",
+ "main": "electron_app/src/electron-main.js",
+ "version": "0.11.4",
"description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.",
"repository": {
@@ -27,23 +27,26 @@
"matrix-react-parent": "matrix-react-sdk",
"scripts": {
"reskindex": "reskindex -h src/header",
+ "reskindex:watch": "reskindex -h src/header -w",
"build:res": "node scripts/copy-res.js",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
- "build:compile": "babel --source-maps -d lib src",
- "build:bundle": "NODE_ENV=production webpack -p --progress",
+ "build:compile": "npm run reskindex && babel --source-maps -d lib src",
+ "build:bundle": "cross-env NODE_ENV=production webpack -p --progress",
"build:bundle:dev": "webpack --optimize-occurence-order --progress",
- "build:electron": "npm run clean && npm run build && build -wml --ia32 --x64",
- "build": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle",
- "build:dev": "node scripts/babelcheck.js && npm run build:res && npm run build:bundle:dev",
+ "build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64",
+ "build": "npm run reskindex && npm run build:res && npm run build:bundle",
+ "build:dev": "npm run reskindex && npm run build:res && npm run build:bundle:dev",
"dist": "scripts/package.sh",
+ "install:electron": "install-app-deps",
+ "electron": "npm run install:electron && electron .",
"start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
- "start:js:prod": "NODE_ENV=production webpack-dev-server -w --progress",
- "start": "node scripts/babelcheck.js && parallelshell \"npm run start:res\" \"npm run start:js\"",
- "start:prod": "parallelshell \"npm run start:res\" \"npm run start:js:prod\"",
+ "start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress",
+ "start": "parallelshell \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js\"",
+ "start:prod": "parallelshell \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js:prod\"",
"lint": "eslint src/",
"lintall": "eslint src/ test/",
- "clean": "rimraf lib webapp electron/dist",
+ "clean": "rimraf lib webapp electron_app/dist",
"prepublish": "npm run build:compile",
"test": "karma start --single-run=true --autoWatch=false --browsers PhantomJS --colors=false",
"test-multi": "karma start"
@@ -56,15 +59,16 @@
"draft-js": "^0.8.1",
"extract-text-webpack-plugin": "^0.9.1",
"favico.js": "^0.3.10",
- "filesize": "^3.1.2",
- "flux": "~2.0.3",
+ "filesize": "3.5.6",
+ "flux": "2.1.1",
"gemini-scrollbar": "matrix-org/gemini-scrollbar#b302279",
"gfm.css": "^1.1.1",
"highlight.js": "^9.0.0",
"linkifyjs": "^2.1.3",
- "matrix-js-sdk": "0.7.7",
- "matrix-react-sdk": "0.8.8",
+ "matrix-js-sdk": "0.7.13",
+ "matrix-react-sdk": "0.9.7",
"modernizr": "^3.1.0",
+ "pako": "^1.0.5",
"q": "^1.4.1",
"react": "^15.4.0",
"react-dnd": "^2.1.4",
@@ -72,8 +76,10 @@
"react-dom": "^15.4.0",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef",
"sanitize-html": "^1.11.1",
+ "text-encoding-utf-8": "^1.0.1",
"ua-parser-js": "^0.7.10",
- "url": "^0.11.0"
+ "url": "^0.11.0",
+ "velocity-vector": "vector-im/velocity#059e3b2"
},
"devDependencies": {
"autoprefixer": "^6.6.0",
@@ -93,12 +99,15 @@
"babel-preset-stage-2": "^6.17.0",
"chokidar": "^1.6.1",
"cpx": "^1.3.2",
+ "cross-env": "^4.0.0",
"css-raw-loader": "^0.1.1",
"electron-builder": "^11.2.4",
"electron-builder-squirrel-windows": "^11.2.1",
+ "electron-devtools-installer": "^2.2.0",
"emojione": "^2.2.7",
"eslint": "^3.14.0",
"eslint-config-google": "^0.7.1",
+ "eslint-plugin-babel": "^4.1.1",
"eslint-plugin-flowtype": "^2.30.0",
"eslint-plugin-react": "^6.9.0",
"expect": "^1.16.0",
@@ -138,30 +147,34 @@
"build": {
"appId": "im.riot.app",
"category": "Network",
- "electronVersion": "1.6.2",
+ "electronVersion": "1.6.8",
"//asar=false": "https://github.com/electron-userland/electron-builder/issues/675",
"asar": false,
"dereference": true,
"//files": "We bundle everything, so we only need to include webapp/",
"files": [
- "electron/src/**",
- "electron/img/**",
- "webapp/**",
- "package.json"
+ "node_modules/**",
+ "src/**",
+ "img/**"
+ ],
+ "extraResources": [
+ "webapp/**/*"
],
"linux": {
"target": "deb",
+ "category": "Network;InstantMessaging;Chat",
"maintainer": "support@riot.im",
"desktop": {
- "StartupWMClass": "riot-web"
+ "StartupWMClass": "riot"
}
},
"win": {
"target": "squirrel"
+ },
+ "directories": {
+ "buildResources": "electron_app/build",
+ "output": "electron_app/dist",
+ "app": "electron_app"
}
- },
- "directories": {
- "buildResources": "electron/build",
- "output": "electron/dist"
}
}
diff --git a/release.sh b/release.sh
index e8c68b90..8ae307f7 100755
--- a/release.sh
+++ b/release.sh
@@ -1,12 +1,41 @@
-#!/bin/sh
+#!/bin/bash
#
# Script to perform a release of vector-web.
#
-# Requires github-changelog-generator; to install, do
+# Requires github-changelog-generator; to install, do
# pip install git+https://github.com/matrix-org/github-changelog-generator.git
set -e
cd `dirname $0`
+for i in matrix-js-sdk matrix-react-sdk
+do
+ depver=`cat package.json | jq -r .dependencies.\"$i\"`
+ latestver=`npm show $i version`
+ if [ "$depver" != "$latestver" ]
+ then
+ echo "The latest version of $i is $latestver but package.json depends on $depver"
+ echo -n "Type 'Yes' to continue anyway: "
+ read resp
+ if [ "$resp" != "Yes" ]
+ then
+ echo "OK, never mind."
+ exit 1
+ fi
+ fi
+done
+
+# bump Electron's package.json first
+release="${1#v}"
+tag="v${release}"
+echo "electron npm version"
+
+cd electron_app
+npm version --no-git-tag-version "$release"
+git commit package.json -m "$tag"
+
+
+cd ..
+
exec ./node_modules/matrix-js-sdk/release.sh -z "$@"
diff --git a/res/flags/AD.png b/res/flags/AD.png
new file mode 100644
index 00000000..d5d59645
Binary files /dev/null and b/res/flags/AD.png differ
diff --git a/res/flags/AE.png b/res/flags/AE.png
new file mode 100644
index 00000000..05c7418a
Binary files /dev/null and b/res/flags/AE.png differ
diff --git a/res/flags/AF.png b/res/flags/AF.png
new file mode 100644
index 00000000..bc7cef09
Binary files /dev/null and b/res/flags/AF.png differ
diff --git a/res/flags/AG.png b/res/flags/AG.png
new file mode 100644
index 00000000..d48facad
Binary files /dev/null and b/res/flags/AG.png differ
diff --git a/res/flags/AI.png b/res/flags/AI.png
new file mode 100644
index 00000000..8fd27cd3
Binary files /dev/null and b/res/flags/AI.png differ
diff --git a/res/flags/AL.png b/res/flags/AL.png
new file mode 100644
index 00000000..883835ff
Binary files /dev/null and b/res/flags/AL.png differ
diff --git a/res/flags/AM.png b/res/flags/AM.png
new file mode 100644
index 00000000..b1bb36b9
Binary files /dev/null and b/res/flags/AM.png differ
diff --git a/res/flags/AO.png b/res/flags/AO.png
new file mode 100644
index 00000000..ae68b12c
Binary files /dev/null and b/res/flags/AO.png differ
diff --git a/res/flags/AQ.png b/res/flags/AQ.png
new file mode 100644
index 00000000..146e9c0a
Binary files /dev/null and b/res/flags/AQ.png differ
diff --git a/res/flags/AR.png b/res/flags/AR.png
new file mode 100644
index 00000000..8142adfc
Binary files /dev/null and b/res/flags/AR.png differ
diff --git a/res/flags/AS.png b/res/flags/AS.png
new file mode 100644
index 00000000..cc5bf30d
Binary files /dev/null and b/res/flags/AS.png differ
diff --git a/res/flags/AT.png b/res/flags/AT.png
new file mode 100644
index 00000000..e32414bd
Binary files /dev/null and b/res/flags/AT.png differ
diff --git a/res/flags/AU.png b/res/flags/AU.png
new file mode 100644
index 00000000..8d1e1437
Binary files /dev/null and b/res/flags/AU.png differ
diff --git a/res/flags/AW.png b/res/flags/AW.png
new file mode 100644
index 00000000..6ec17884
Binary files /dev/null and b/res/flags/AW.png differ
diff --git a/res/flags/AX.png b/res/flags/AX.png
new file mode 100644
index 00000000..ba269c04
Binary files /dev/null and b/res/flags/AX.png differ
diff --git a/res/flags/AZ.png b/res/flags/AZ.png
new file mode 100644
index 00000000..2bf3c746
Binary files /dev/null and b/res/flags/AZ.png differ
diff --git a/res/flags/BA.png b/res/flags/BA.png
new file mode 100644
index 00000000..3e3ec3fc
Binary files /dev/null and b/res/flags/BA.png differ
diff --git a/res/flags/BB.png b/res/flags/BB.png
new file mode 100644
index 00000000..694050ca
Binary files /dev/null and b/res/flags/BB.png differ
diff --git a/res/flags/BD.png b/res/flags/BD.png
new file mode 100644
index 00000000..6de2cde8
Binary files /dev/null and b/res/flags/BD.png differ
diff --git a/res/flags/BE.png b/res/flags/BE.png
new file mode 100644
index 00000000..742ba923
Binary files /dev/null and b/res/flags/BE.png differ
diff --git a/res/flags/BF.png b/res/flags/BF.png
new file mode 100644
index 00000000..17f9f67d
Binary files /dev/null and b/res/flags/BF.png differ
diff --git a/res/flags/BG.png b/res/flags/BG.png
new file mode 100644
index 00000000..b01d3ff5
Binary files /dev/null and b/res/flags/BG.png differ
diff --git a/res/flags/BH.png b/res/flags/BH.png
new file mode 100644
index 00000000..d0f82e82
Binary files /dev/null and b/res/flags/BH.png differ
diff --git a/res/flags/BI.png b/res/flags/BI.png
new file mode 100644
index 00000000..21865ac7
Binary files /dev/null and b/res/flags/BI.png differ
diff --git a/res/flags/BJ.png b/res/flags/BJ.png
new file mode 100644
index 00000000..a7c60914
Binary files /dev/null and b/res/flags/BJ.png differ
diff --git a/res/flags/BL.png b/res/flags/BL.png
new file mode 100644
index 00000000..6d50a0f5
Binary files /dev/null and b/res/flags/BL.png differ
diff --git a/res/flags/BM.png b/res/flags/BM.png
new file mode 100644
index 00000000..310a25ea
Binary files /dev/null and b/res/flags/BM.png differ
diff --git a/res/flags/BN.png b/res/flags/BN.png
new file mode 100644
index 00000000..bc4da8d9
Binary files /dev/null and b/res/flags/BN.png differ
diff --git a/res/flags/BO.png b/res/flags/BO.png
new file mode 100644
index 00000000..144b8d32
Binary files /dev/null and b/res/flags/BO.png differ
diff --git a/res/flags/BQ.png b/res/flags/BQ.png
new file mode 100644
index 00000000..08979437
Binary files /dev/null and b/res/flags/BQ.png differ
diff --git a/res/flags/BR.png b/res/flags/BR.png
new file mode 100644
index 00000000..02784925
Binary files /dev/null and b/res/flags/BR.png differ
diff --git a/res/flags/BS.png b/res/flags/BS.png
new file mode 100644
index 00000000..2b05a8fc
Binary files /dev/null and b/res/flags/BS.png differ
diff --git a/res/flags/BT.png b/res/flags/BT.png
new file mode 100644
index 00000000..1f031df0
Binary files /dev/null and b/res/flags/BT.png differ
diff --git a/res/flags/BV.png b/res/flags/BV.png
new file mode 100644
index 00000000..aafb0f17
Binary files /dev/null and b/res/flags/BV.png differ
diff --git a/res/flags/BW.png b/res/flags/BW.png
new file mode 100644
index 00000000..30840167
Binary files /dev/null and b/res/flags/BW.png differ
diff --git a/res/flags/BY.png b/res/flags/BY.png
new file mode 100644
index 00000000..ce9de9c9
Binary files /dev/null and b/res/flags/BY.png differ
diff --git a/res/flags/BZ.png b/res/flags/BZ.png
new file mode 100644
index 00000000..33620c3f
Binary files /dev/null and b/res/flags/BZ.png differ
diff --git a/res/flags/CA.png b/res/flags/CA.png
new file mode 100644
index 00000000..4bbf8b11
Binary files /dev/null and b/res/flags/CA.png differ
diff --git a/res/flags/CC.png b/res/flags/CC.png
new file mode 100644
index 00000000..fd40fc8a
Binary files /dev/null and b/res/flags/CC.png differ
diff --git a/res/flags/CD.png b/res/flags/CD.png
new file mode 100644
index 00000000..230aacd4
Binary files /dev/null and b/res/flags/CD.png differ
diff --git a/res/flags/CF.png b/res/flags/CF.png
new file mode 100644
index 00000000..c58ed4f7
Binary files /dev/null and b/res/flags/CF.png differ
diff --git a/res/flags/CG.png b/res/flags/CG.png
new file mode 100644
index 00000000..6c2441e3
Binary files /dev/null and b/res/flags/CG.png differ
diff --git a/res/flags/CH.png b/res/flags/CH.png
new file mode 100644
index 00000000..9fd87167
Binary files /dev/null and b/res/flags/CH.png differ
diff --git a/res/flags/CI.png b/res/flags/CI.png
new file mode 100644
index 00000000..9741b9b1
Binary files /dev/null and b/res/flags/CI.png differ
diff --git a/res/flags/CK.png b/res/flags/CK.png
new file mode 100644
index 00000000..6cca3596
Binary files /dev/null and b/res/flags/CK.png differ
diff --git a/res/flags/CL.png b/res/flags/CL.png
new file mode 100644
index 00000000..13b993d1
Binary files /dev/null and b/res/flags/CL.png differ
diff --git a/res/flags/CM.png b/res/flags/CM.png
new file mode 100644
index 00000000..bca5730f
Binary files /dev/null and b/res/flags/CM.png differ
diff --git a/res/flags/CN.png b/res/flags/CN.png
new file mode 100644
index 00000000..e086855c
Binary files /dev/null and b/res/flags/CN.png differ
diff --git a/res/flags/CO.png b/res/flags/CO.png
new file mode 100644
index 00000000..65c0aba4
Binary files /dev/null and b/res/flags/CO.png differ
diff --git a/res/flags/CR.png b/res/flags/CR.png
new file mode 100644
index 00000000..b351c67a
Binary files /dev/null and b/res/flags/CR.png differ
diff --git a/res/flags/CU.png b/res/flags/CU.png
new file mode 100644
index 00000000..e7a25c60
Binary files /dev/null and b/res/flags/CU.png differ
diff --git a/res/flags/CV.png b/res/flags/CV.png
new file mode 100644
index 00000000..f249bbaa
Binary files /dev/null and b/res/flags/CV.png differ
diff --git a/res/flags/CW.png b/res/flags/CW.png
new file mode 100644
index 00000000..e02cacd3
Binary files /dev/null and b/res/flags/CW.png differ
diff --git a/res/flags/CX.png b/res/flags/CX.png
new file mode 100644
index 00000000..3ea21422
Binary files /dev/null and b/res/flags/CX.png differ
diff --git a/res/flags/CY.png b/res/flags/CY.png
new file mode 100644
index 00000000..3182f48b
Binary files /dev/null and b/res/flags/CY.png differ
diff --git a/res/flags/CZ.png b/res/flags/CZ.png
new file mode 100644
index 00000000..54623346
Binary files /dev/null and b/res/flags/CZ.png differ
diff --git a/res/flags/DE.png b/res/flags/DE.png
new file mode 100644
index 00000000..93e26916
Binary files /dev/null and b/res/flags/DE.png differ
diff --git a/res/flags/DJ.png b/res/flags/DJ.png
new file mode 100644
index 00000000..243bb739
Binary files /dev/null and b/res/flags/DJ.png differ
diff --git a/res/flags/DK.png b/res/flags/DK.png
new file mode 100644
index 00000000..fc74cc39
Binary files /dev/null and b/res/flags/DK.png differ
diff --git a/res/flags/DM.png b/res/flags/DM.png
new file mode 100644
index 00000000..c3a0e9d1
Binary files /dev/null and b/res/flags/DM.png differ
diff --git a/res/flags/DO.png b/res/flags/DO.png
new file mode 100644
index 00000000..5c4a004f
Binary files /dev/null and b/res/flags/DO.png differ
diff --git a/res/flags/DZ.png b/res/flags/DZ.png
new file mode 100644
index 00000000..1589d0cc
Binary files /dev/null and b/res/flags/DZ.png differ
diff --git a/res/flags/EC.png b/res/flags/EC.png
new file mode 100644
index 00000000..4c53dead
Binary files /dev/null and b/res/flags/EC.png differ
diff --git a/res/flags/EE.png b/res/flags/EE.png
new file mode 100644
index 00000000..3668de79
Binary files /dev/null and b/res/flags/EE.png differ
diff --git a/res/flags/EG.png b/res/flags/EG.png
new file mode 100644
index 00000000..66ec709d
Binary files /dev/null and b/res/flags/EG.png differ
diff --git a/res/flags/EH.png b/res/flags/EH.png
new file mode 100644
index 00000000..148be93c
Binary files /dev/null and b/res/flags/EH.png differ
diff --git a/res/flags/ER.png b/res/flags/ER.png
new file mode 100644
index 00000000..7cb84415
Binary files /dev/null and b/res/flags/ER.png differ
diff --git a/res/flags/ES.png b/res/flags/ES.png
new file mode 100644
index 00000000..aae73b6f
Binary files /dev/null and b/res/flags/ES.png differ
diff --git a/res/flags/ET.png b/res/flags/ET.png
new file mode 100644
index 00000000..7b420f02
Binary files /dev/null and b/res/flags/ET.png differ
diff --git a/res/flags/FI.png b/res/flags/FI.png
new file mode 100644
index 00000000..42f64bf3
Binary files /dev/null and b/res/flags/FI.png differ
diff --git a/res/flags/FJ.png b/res/flags/FJ.png
new file mode 100644
index 00000000..cecc683c
Binary files /dev/null and b/res/flags/FJ.png differ
diff --git a/res/flags/FK.png b/res/flags/FK.png
new file mode 100644
index 00000000..6074fea0
Binary files /dev/null and b/res/flags/FK.png differ
diff --git a/res/flags/FM.png b/res/flags/FM.png
new file mode 100644
index 00000000..45fdb664
Binary files /dev/null and b/res/flags/FM.png differ
diff --git a/res/flags/FO.png b/res/flags/FO.png
new file mode 100644
index 00000000..d8fd75c6
Binary files /dev/null and b/res/flags/FO.png differ
diff --git a/res/flags/FR.png b/res/flags/FR.png
new file mode 100644
index 00000000..6d50a0f5
Binary files /dev/null and b/res/flags/FR.png differ
diff --git a/res/flags/GA.png b/res/flags/GA.png
new file mode 100644
index 00000000..3808a61f
Binary files /dev/null and b/res/flags/GA.png differ
diff --git a/res/flags/GB.png b/res/flags/GB.png
new file mode 100644
index 00000000..589be700
Binary files /dev/null and b/res/flags/GB.png differ
diff --git a/res/flags/GD.png b/res/flags/GD.png
new file mode 100644
index 00000000..babe1e4c
Binary files /dev/null and b/res/flags/GD.png differ
diff --git a/res/flags/GE.png b/res/flags/GE.png
new file mode 100644
index 00000000..d34cddec
Binary files /dev/null and b/res/flags/GE.png differ
diff --git a/res/flags/GF.png b/res/flags/GF.png
new file mode 100644
index 00000000..98828a59
Binary files /dev/null and b/res/flags/GF.png differ
diff --git a/res/flags/GG.png b/res/flags/GG.png
new file mode 100644
index 00000000..aec8969b
Binary files /dev/null and b/res/flags/GG.png differ
diff --git a/res/flags/GH.png b/res/flags/GH.png
new file mode 100644
index 00000000..70b1a623
Binary files /dev/null and b/res/flags/GH.png differ
diff --git a/res/flags/GI.png b/res/flags/GI.png
new file mode 100644
index 00000000..9aa58327
Binary files /dev/null and b/res/flags/GI.png differ
diff --git a/res/flags/GL.png b/res/flags/GL.png
new file mode 100644
index 00000000..cf1645c2
Binary files /dev/null and b/res/flags/GL.png differ
diff --git a/res/flags/GM.png b/res/flags/GM.png
new file mode 100644
index 00000000..ec374fb3
Binary files /dev/null and b/res/flags/GM.png differ
diff --git a/res/flags/GN.png b/res/flags/GN.png
new file mode 100644
index 00000000..46874b4d
Binary files /dev/null and b/res/flags/GN.png differ
diff --git a/res/flags/GP.png b/res/flags/GP.png
new file mode 100644
index 00000000..81b7abdf
Binary files /dev/null and b/res/flags/GP.png differ
diff --git a/res/flags/GQ.png b/res/flags/GQ.png
new file mode 100644
index 00000000..7fd1015e
Binary files /dev/null and b/res/flags/GQ.png differ
diff --git a/res/flags/GR.png b/res/flags/GR.png
new file mode 100644
index 00000000..101de51e
Binary files /dev/null and b/res/flags/GR.png differ
diff --git a/res/flags/GS.png b/res/flags/GS.png
new file mode 100644
index 00000000..772c2cbe
Binary files /dev/null and b/res/flags/GS.png differ
diff --git a/res/flags/GT.png b/res/flags/GT.png
new file mode 100644
index 00000000..d5bd8c1e
Binary files /dev/null and b/res/flags/GT.png differ
diff --git a/res/flags/GU.png b/res/flags/GU.png
new file mode 100644
index 00000000..8923085d
Binary files /dev/null and b/res/flags/GU.png differ
diff --git a/res/flags/GW.png b/res/flags/GW.png
new file mode 100644
index 00000000..20c268ce
Binary files /dev/null and b/res/flags/GW.png differ
diff --git a/res/flags/GY.png b/res/flags/GY.png
new file mode 100644
index 00000000..86f56635
Binary files /dev/null and b/res/flags/GY.png differ
diff --git a/res/flags/HK.png b/res/flags/HK.png
new file mode 100644
index 00000000..907dc596
Binary files /dev/null and b/res/flags/HK.png differ
diff --git a/res/flags/HM.png b/res/flags/HM.png
new file mode 100644
index 00000000..8d1e1437
Binary files /dev/null and b/res/flags/HM.png differ
diff --git a/res/flags/HN.png b/res/flags/HN.png
new file mode 100644
index 00000000..4cf8c311
Binary files /dev/null and b/res/flags/HN.png differ
diff --git a/res/flags/HR.png b/res/flags/HR.png
new file mode 100644
index 00000000..413ceb15
Binary files /dev/null and b/res/flags/HR.png differ
diff --git a/res/flags/HT.png b/res/flags/HT.png
new file mode 100644
index 00000000..097abeb4
Binary files /dev/null and b/res/flags/HT.png differ
diff --git a/res/flags/HU.png b/res/flags/HU.png
new file mode 100644
index 00000000..23499bf6
Binary files /dev/null and b/res/flags/HU.png differ
diff --git a/res/flags/ID.png b/res/flags/ID.png
new file mode 100644
index 00000000..80200657
Binary files /dev/null and b/res/flags/ID.png differ
diff --git a/res/flags/IE.png b/res/flags/IE.png
new file mode 100644
index 00000000..63f22201
Binary files /dev/null and b/res/flags/IE.png differ
diff --git a/res/flags/IL.png b/res/flags/IL.png
new file mode 100644
index 00000000..02688263
Binary files /dev/null and b/res/flags/IL.png differ
diff --git a/res/flags/IM.png b/res/flags/IM.png
new file mode 100644
index 00000000..c777acc4
Binary files /dev/null and b/res/flags/IM.png differ
diff --git a/res/flags/IN.png b/res/flags/IN.png
new file mode 100644
index 00000000..85fa9bfe
Binary files /dev/null and b/res/flags/IN.png differ
diff --git a/res/flags/IO.png b/res/flags/IO.png
new file mode 100644
index 00000000..1675d8e7
Binary files /dev/null and b/res/flags/IO.png differ
diff --git a/res/flags/IQ.png b/res/flags/IQ.png
new file mode 100644
index 00000000..f2c21f72
Binary files /dev/null and b/res/flags/IQ.png differ
diff --git a/res/flags/IR.png b/res/flags/IR.png
new file mode 100644
index 00000000..0b8e6750
Binary files /dev/null and b/res/flags/IR.png differ
diff --git a/res/flags/IS.png b/res/flags/IS.png
new file mode 100644
index 00000000..5ee3e63c
Binary files /dev/null and b/res/flags/IS.png differ
diff --git a/res/flags/IT.png b/res/flags/IT.png
new file mode 100644
index 00000000..53b967be
Binary files /dev/null and b/res/flags/IT.png differ
diff --git a/res/flags/JE.png b/res/flags/JE.png
new file mode 100644
index 00000000..a1437aba
Binary files /dev/null and b/res/flags/JE.png differ
diff --git a/res/flags/JM.png b/res/flags/JM.png
new file mode 100644
index 00000000..0d462fa3
Binary files /dev/null and b/res/flags/JM.png differ
diff --git a/res/flags/JO.png b/res/flags/JO.png
new file mode 100644
index 00000000..8934db7e
Binary files /dev/null and b/res/flags/JO.png differ
diff --git a/res/flags/JP.png b/res/flags/JP.png
new file mode 100644
index 00000000..6f92d523
Binary files /dev/null and b/res/flags/JP.png differ
diff --git a/res/flags/KE.png b/res/flags/KE.png
new file mode 100644
index 00000000..866b3f15
Binary files /dev/null and b/res/flags/KE.png differ
diff --git a/res/flags/KG.png b/res/flags/KG.png
new file mode 100644
index 00000000..56b433c7
Binary files /dev/null and b/res/flags/KG.png differ
diff --git a/res/flags/KH.png b/res/flags/KH.png
new file mode 100644
index 00000000..e1ddd5f8
Binary files /dev/null and b/res/flags/KH.png differ
diff --git a/res/flags/KI.png b/res/flags/KI.png
new file mode 100644
index 00000000..8b7c54bc
Binary files /dev/null and b/res/flags/KI.png differ
diff --git a/res/flags/KM.png b/res/flags/KM.png
new file mode 100644
index 00000000..227a3b33
Binary files /dev/null and b/res/flags/KM.png differ
diff --git a/res/flags/KN.png b/res/flags/KN.png
new file mode 100644
index 00000000..bc6189be
Binary files /dev/null and b/res/flags/KN.png differ
diff --git a/res/flags/KP.png b/res/flags/KP.png
new file mode 100644
index 00000000..c92248b9
Binary files /dev/null and b/res/flags/KP.png differ
diff --git a/res/flags/KR.png b/res/flags/KR.png
new file mode 100644
index 00000000..ab1cb949
Binary files /dev/null and b/res/flags/KR.png differ
diff --git a/res/flags/KW.png b/res/flags/KW.png
new file mode 100644
index 00000000..0b41c7a5
Binary files /dev/null and b/res/flags/KW.png differ
diff --git a/res/flags/KY.png b/res/flags/KY.png
new file mode 100644
index 00000000..7af5290d
Binary files /dev/null and b/res/flags/KY.png differ
diff --git a/res/flags/KZ.png b/res/flags/KZ.png
new file mode 100644
index 00000000..e10a1255
Binary files /dev/null and b/res/flags/KZ.png differ
diff --git a/res/flags/LA.png b/res/flags/LA.png
new file mode 100644
index 00000000..6ad67d42
Binary files /dev/null and b/res/flags/LA.png differ
diff --git a/res/flags/LB.png b/res/flags/LB.png
new file mode 100644
index 00000000..865df57a
Binary files /dev/null and b/res/flags/LB.png differ
diff --git a/res/flags/LC.png b/res/flags/LC.png
new file mode 100644
index 00000000..e83a2d08
Binary files /dev/null and b/res/flags/LC.png differ
diff --git a/res/flags/LI.png b/res/flags/LI.png
new file mode 100644
index 00000000..57034d36
Binary files /dev/null and b/res/flags/LI.png differ
diff --git a/res/flags/LK.png b/res/flags/LK.png
new file mode 100644
index 00000000..6e7ad582
Binary files /dev/null and b/res/flags/LK.png differ
diff --git a/res/flags/LR.png b/res/flags/LR.png
new file mode 100644
index 00000000..46c3b84a
Binary files /dev/null and b/res/flags/LR.png differ
diff --git a/res/flags/LS.png b/res/flags/LS.png
new file mode 100644
index 00000000..79b505d4
Binary files /dev/null and b/res/flags/LS.png differ
diff --git a/res/flags/LT.png b/res/flags/LT.png
new file mode 100644
index 00000000..7740cdc0
Binary files /dev/null and b/res/flags/LT.png differ
diff --git a/res/flags/LU.png b/res/flags/LU.png
new file mode 100644
index 00000000..8f383e67
Binary files /dev/null and b/res/flags/LU.png differ
diff --git a/res/flags/LV.png b/res/flags/LV.png
new file mode 100644
index 00000000..a0f36d89
Binary files /dev/null and b/res/flags/LV.png differ
diff --git a/res/flags/LY.png b/res/flags/LY.png
new file mode 100644
index 00000000..2884c4c0
Binary files /dev/null and b/res/flags/LY.png differ
diff --git a/res/flags/MA.png b/res/flags/MA.png
new file mode 100644
index 00000000..1f76cfc9
Binary files /dev/null and b/res/flags/MA.png differ
diff --git a/res/flags/MC.png b/res/flags/MC.png
new file mode 100644
index 00000000..06fc2ad1
Binary files /dev/null and b/res/flags/MC.png differ
diff --git a/res/flags/MD.png b/res/flags/MD.png
new file mode 100644
index 00000000..8e54c2b8
Binary files /dev/null and b/res/flags/MD.png differ
diff --git a/res/flags/ME.png b/res/flags/ME.png
new file mode 100644
index 00000000..97424d4e
Binary files /dev/null and b/res/flags/ME.png differ
diff --git a/res/flags/MF.png b/res/flags/MF.png
new file mode 100644
index 00000000..6d50a0f5
Binary files /dev/null and b/res/flags/MF.png differ
diff --git a/res/flags/MG.png b/res/flags/MG.png
new file mode 100644
index 00000000..28bfccc9
Binary files /dev/null and b/res/flags/MG.png differ
diff --git a/res/flags/MH.png b/res/flags/MH.png
new file mode 100644
index 00000000..e482a659
Binary files /dev/null and b/res/flags/MH.png differ
diff --git a/res/flags/MK.png b/res/flags/MK.png
new file mode 100644
index 00000000..84e2e65e
Binary files /dev/null and b/res/flags/MK.png differ
diff --git a/res/flags/ML.png b/res/flags/ML.png
new file mode 100644
index 00000000..38fec347
Binary files /dev/null and b/res/flags/ML.png differ
diff --git a/res/flags/MM.png b/res/flags/MM.png
new file mode 100644
index 00000000..70a03c6b
Binary files /dev/null and b/res/flags/MM.png differ
diff --git a/res/flags/MN.png b/res/flags/MN.png
new file mode 100644
index 00000000..1e1bbe60
Binary files /dev/null and b/res/flags/MN.png differ
diff --git a/res/flags/MO.png b/res/flags/MO.png
new file mode 100644
index 00000000..3833d683
Binary files /dev/null and b/res/flags/MO.png differ
diff --git a/res/flags/MP.png b/res/flags/MP.png
new file mode 100644
index 00000000..63119096
Binary files /dev/null and b/res/flags/MP.png differ
diff --git a/res/flags/MQ.png b/res/flags/MQ.png
new file mode 100644
index 00000000..9cab441a
Binary files /dev/null and b/res/flags/MQ.png differ
diff --git a/res/flags/MR.png b/res/flags/MR.png
new file mode 100644
index 00000000..c144de17
Binary files /dev/null and b/res/flags/MR.png differ
diff --git a/res/flags/MS.png b/res/flags/MS.png
new file mode 100644
index 00000000..12217070
Binary files /dev/null and b/res/flags/MS.png differ
diff --git a/res/flags/MT.png b/res/flags/MT.png
new file mode 100644
index 00000000..7963aa61
Binary files /dev/null and b/res/flags/MT.png differ
diff --git a/res/flags/MU.png b/res/flags/MU.png
new file mode 100644
index 00000000..d5d4d400
Binary files /dev/null and b/res/flags/MU.png differ
diff --git a/res/flags/MV.png b/res/flags/MV.png
new file mode 100644
index 00000000..0f2ecb43
Binary files /dev/null and b/res/flags/MV.png differ
diff --git a/res/flags/MW.png b/res/flags/MW.png
new file mode 100644
index 00000000..d0a5d24f
Binary files /dev/null and b/res/flags/MW.png differ
diff --git a/res/flags/MX.png b/res/flags/MX.png
new file mode 100644
index 00000000..096cb111
Binary files /dev/null and b/res/flags/MX.png differ
diff --git a/res/flags/MY.png b/res/flags/MY.png
new file mode 100644
index 00000000..17f18ac5
Binary files /dev/null and b/res/flags/MY.png differ
diff --git a/res/flags/MZ.png b/res/flags/MZ.png
new file mode 100644
index 00000000..66be6563
Binary files /dev/null and b/res/flags/MZ.png differ
diff --git a/res/flags/NA.png b/res/flags/NA.png
new file mode 100644
index 00000000..7ecfd317
Binary files /dev/null and b/res/flags/NA.png differ
diff --git a/res/flags/NC.png b/res/flags/NC.png
new file mode 100644
index 00000000..11126ade
Binary files /dev/null and b/res/flags/NC.png differ
diff --git a/res/flags/NE.png b/res/flags/NE.png
new file mode 100644
index 00000000..d584fa84
Binary files /dev/null and b/res/flags/NE.png differ
diff --git a/res/flags/NF.png b/res/flags/NF.png
new file mode 100644
index 00000000..c0540425
Binary files /dev/null and b/res/flags/NF.png differ
diff --git a/res/flags/NG.png b/res/flags/NG.png
new file mode 100644
index 00000000..73aee15b
Binary files /dev/null and b/res/flags/NG.png differ
diff --git a/res/flags/NI.png b/res/flags/NI.png
new file mode 100644
index 00000000..fd044933
Binary files /dev/null and b/res/flags/NI.png differ
diff --git a/res/flags/NL.png b/res/flags/NL.png
new file mode 100644
index 00000000..08979437
Binary files /dev/null and b/res/flags/NL.png differ
diff --git a/res/flags/NO.png b/res/flags/NO.png
new file mode 100644
index 00000000..aafb0f17
Binary files /dev/null and b/res/flags/NO.png differ
diff --git a/res/flags/NP.png b/res/flags/NP.png
new file mode 100644
index 00000000..744458e1
Binary files /dev/null and b/res/flags/NP.png differ
diff --git a/res/flags/NR.png b/res/flags/NR.png
new file mode 100644
index 00000000..58c2afb2
Binary files /dev/null and b/res/flags/NR.png differ
diff --git a/res/flags/NU.png b/res/flags/NU.png
new file mode 100644
index 00000000..007c99ec
Binary files /dev/null and b/res/flags/NU.png differ
diff --git a/res/flags/NZ.png b/res/flags/NZ.png
new file mode 100644
index 00000000..839368dd
Binary files /dev/null and b/res/flags/NZ.png differ
diff --git a/res/flags/OM.png b/res/flags/OM.png
new file mode 100644
index 00000000..63a89336
Binary files /dev/null and b/res/flags/OM.png differ
diff --git a/res/flags/PA.png b/res/flags/PA.png
new file mode 100644
index 00000000..3515d95d
Binary files /dev/null and b/res/flags/PA.png differ
diff --git a/res/flags/PE.png b/res/flags/PE.png
new file mode 100644
index 00000000..58f70b8d
Binary files /dev/null and b/res/flags/PE.png differ
diff --git a/res/flags/PF.png b/res/flags/PF.png
new file mode 100644
index 00000000..2f33f257
Binary files /dev/null and b/res/flags/PF.png differ
diff --git a/res/flags/PG.png b/res/flags/PG.png
new file mode 100644
index 00000000..c796f587
Binary files /dev/null and b/res/flags/PG.png differ
diff --git a/res/flags/PH.png b/res/flags/PH.png
new file mode 100644
index 00000000..0d98de03
Binary files /dev/null and b/res/flags/PH.png differ
diff --git a/res/flags/PK.png b/res/flags/PK.png
new file mode 100644
index 00000000..87f4e2f4
Binary files /dev/null and b/res/flags/PK.png differ
diff --git a/res/flags/PL.png b/res/flags/PL.png
new file mode 100644
index 00000000..273869df
Binary files /dev/null and b/res/flags/PL.png differ
diff --git a/res/flags/PM.png b/res/flags/PM.png
new file mode 100644
index 00000000..b74c396d
Binary files /dev/null and b/res/flags/PM.png differ
diff --git a/res/flags/PN.png b/res/flags/PN.png
new file mode 100644
index 00000000..e34c62d5
Binary files /dev/null and b/res/flags/PN.png differ
diff --git a/res/flags/PR.png b/res/flags/PR.png
new file mode 100644
index 00000000..8efdb912
Binary files /dev/null and b/res/flags/PR.png differ
diff --git a/res/flags/PS.png b/res/flags/PS.png
new file mode 100644
index 00000000..7a0cceec
Binary files /dev/null and b/res/flags/PS.png differ
diff --git a/res/flags/PT.png b/res/flags/PT.png
new file mode 100644
index 00000000..49e29082
Binary files /dev/null and b/res/flags/PT.png differ
diff --git a/res/flags/PW.png b/res/flags/PW.png
new file mode 100644
index 00000000..6cb2e1e7
Binary files /dev/null and b/res/flags/PW.png differ
diff --git a/res/flags/PY.png b/res/flags/PY.png
new file mode 100644
index 00000000..a61c42c4
Binary files /dev/null and b/res/flags/PY.png differ
diff --git a/res/flags/QA.png b/res/flags/QA.png
new file mode 100644
index 00000000..bb091cc8
Binary files /dev/null and b/res/flags/QA.png differ
diff --git a/res/flags/RE.png b/res/flags/RE.png
new file mode 100644
index 00000000..6d50a0f5
Binary files /dev/null and b/res/flags/RE.png differ
diff --git a/res/flags/RO.png b/res/flags/RO.png
new file mode 100644
index 00000000..4495d29e
Binary files /dev/null and b/res/flags/RO.png differ
diff --git a/res/flags/RS.png b/res/flags/RS.png
new file mode 100644
index 00000000..ebb0f28a
Binary files /dev/null and b/res/flags/RS.png differ
diff --git a/res/flags/RU.png b/res/flags/RU.png
new file mode 100644
index 00000000..64532ffa
Binary files /dev/null and b/res/flags/RU.png differ
diff --git a/res/flags/RW.png b/res/flags/RW.png
new file mode 100644
index 00000000..64b3cfff
Binary files /dev/null and b/res/flags/RW.png differ
diff --git a/res/flags/SA.png b/res/flags/SA.png
new file mode 100644
index 00000000..250de6f6
Binary files /dev/null and b/res/flags/SA.png differ
diff --git a/res/flags/SB.png b/res/flags/SB.png
new file mode 100644
index 00000000..5833c130
Binary files /dev/null and b/res/flags/SB.png differ
diff --git a/res/flags/SC.png b/res/flags/SC.png
new file mode 100644
index 00000000..ce5248f4
Binary files /dev/null and b/res/flags/SC.png differ
diff --git a/res/flags/SD.png b/res/flags/SD.png
new file mode 100644
index 00000000..d8711a83
Binary files /dev/null and b/res/flags/SD.png differ
diff --git a/res/flags/SE.png b/res/flags/SE.png
new file mode 100644
index 00000000..81880931
Binary files /dev/null and b/res/flags/SE.png differ
diff --git a/res/flags/SG.png b/res/flags/SG.png
new file mode 100644
index 00000000..6f00e579
Binary files /dev/null and b/res/flags/SG.png differ
diff --git a/res/flags/SH.png b/res/flags/SH.png
new file mode 100644
index 00000000..055dde68
Binary files /dev/null and b/res/flags/SH.png differ
diff --git a/res/flags/SI.png b/res/flags/SI.png
new file mode 100644
index 00000000..96359834
Binary files /dev/null and b/res/flags/SI.png differ
diff --git a/res/flags/SJ.png b/res/flags/SJ.png
new file mode 100644
index 00000000..aafb0f17
Binary files /dev/null and b/res/flags/SJ.png differ
diff --git a/res/flags/SK.png b/res/flags/SK.png
new file mode 100644
index 00000000..84c7021f
Binary files /dev/null and b/res/flags/SK.png differ
diff --git a/res/flags/SL.png b/res/flags/SL.png
new file mode 100644
index 00000000..c5ed1991
Binary files /dev/null and b/res/flags/SL.png differ
diff --git a/res/flags/SM.png b/res/flags/SM.png
new file mode 100644
index 00000000..1af1ca28
Binary files /dev/null and b/res/flags/SM.png differ
diff --git a/res/flags/SN.png b/res/flags/SN.png
new file mode 100644
index 00000000..d0b18435
Binary files /dev/null and b/res/flags/SN.png differ
diff --git a/res/flags/SO.png b/res/flags/SO.png
new file mode 100644
index 00000000..64e2970b
Binary files /dev/null and b/res/flags/SO.png differ
diff --git a/res/flags/SR.png b/res/flags/SR.png
new file mode 100644
index 00000000..b072dda8
Binary files /dev/null and b/res/flags/SR.png differ
diff --git a/res/flags/SS.png b/res/flags/SS.png
new file mode 100644
index 00000000..83933d45
Binary files /dev/null and b/res/flags/SS.png differ
diff --git a/res/flags/ST.png b/res/flags/ST.png
new file mode 100644
index 00000000..c102721a
Binary files /dev/null and b/res/flags/ST.png differ
diff --git a/res/flags/SV.png b/res/flags/SV.png
new file mode 100644
index 00000000..80de92e5
Binary files /dev/null and b/res/flags/SV.png differ
diff --git a/res/flags/SX.png b/res/flags/SX.png
new file mode 100644
index 00000000..dd52215c
Binary files /dev/null and b/res/flags/SX.png differ
diff --git a/res/flags/SY.png b/res/flags/SY.png
new file mode 100644
index 00000000..78f45b7c
Binary files /dev/null and b/res/flags/SY.png differ
diff --git a/res/flags/SZ.png b/res/flags/SZ.png
new file mode 100644
index 00000000..2182f4ff
Binary files /dev/null and b/res/flags/SZ.png differ
diff --git a/res/flags/TC.png b/res/flags/TC.png
new file mode 100644
index 00000000..3e3e19d4
Binary files /dev/null and b/res/flags/TC.png differ
diff --git a/res/flags/TD.png b/res/flags/TD.png
new file mode 100644
index 00000000..753bec22
Binary files /dev/null and b/res/flags/TD.png differ
diff --git a/res/flags/TF.png b/res/flags/TF.png
new file mode 100644
index 00000000..6d50a0f5
Binary files /dev/null and b/res/flags/TF.png differ
diff --git a/res/flags/TG.png b/res/flags/TG.png
new file mode 100644
index 00000000..8501ada6
Binary files /dev/null and b/res/flags/TG.png differ
diff --git a/res/flags/TH.png b/res/flags/TH.png
new file mode 100644
index 00000000..0c884c32
Binary files /dev/null and b/res/flags/TH.png differ
diff --git a/res/flags/TJ.png b/res/flags/TJ.png
new file mode 100644
index 00000000..3c9026fa
Binary files /dev/null and b/res/flags/TJ.png differ
diff --git a/res/flags/TK.png b/res/flags/TK.png
new file mode 100644
index 00000000..fd605749
Binary files /dev/null and b/res/flags/TK.png differ
diff --git a/res/flags/TL.png b/res/flags/TL.png
new file mode 100644
index 00000000..b4c834b1
Binary files /dev/null and b/res/flags/TL.png differ
diff --git a/res/flags/TM.png b/res/flags/TM.png
new file mode 100644
index 00000000..d18cb939
Binary files /dev/null and b/res/flags/TM.png differ
diff --git a/res/flags/TN.png b/res/flags/TN.png
new file mode 100644
index 00000000..21c4b98b
Binary files /dev/null and b/res/flags/TN.png differ
diff --git a/res/flags/TO.png b/res/flags/TO.png
new file mode 100644
index 00000000..c828206e
Binary files /dev/null and b/res/flags/TO.png differ
diff --git a/res/flags/TR.png b/res/flags/TR.png
new file mode 100644
index 00000000..f2a5bd22
Binary files /dev/null and b/res/flags/TR.png differ
diff --git a/res/flags/TT.png b/res/flags/TT.png
new file mode 100644
index 00000000..66d69833
Binary files /dev/null and b/res/flags/TT.png differ
diff --git a/res/flags/TV.png b/res/flags/TV.png
new file mode 100644
index 00000000..7a127f51
Binary files /dev/null and b/res/flags/TV.png differ
diff --git a/res/flags/TW.png b/res/flags/TW.png
new file mode 100644
index 00000000..2353ba1b
Binary files /dev/null and b/res/flags/TW.png differ
diff --git a/res/flags/TZ.png b/res/flags/TZ.png
new file mode 100644
index 00000000..7949f65d
Binary files /dev/null and b/res/flags/TZ.png differ
diff --git a/res/flags/UA.png b/res/flags/UA.png
new file mode 100644
index 00000000..687e3052
Binary files /dev/null and b/res/flags/UA.png differ
diff --git a/res/flags/UG.png b/res/flags/UG.png
new file mode 100644
index 00000000..0a21ad15
Binary files /dev/null and b/res/flags/UG.png differ
diff --git a/res/flags/US.png b/res/flags/US.png
new file mode 100644
index 00000000..c3a245b7
Binary files /dev/null and b/res/flags/US.png differ
diff --git a/res/flags/UY.png b/res/flags/UY.png
new file mode 100644
index 00000000..21a347c6
Binary files /dev/null and b/res/flags/UY.png differ
diff --git a/res/flags/UZ.png b/res/flags/UZ.png
new file mode 100644
index 00000000..643b6ae0
Binary files /dev/null and b/res/flags/UZ.png differ
diff --git a/res/flags/VA.png b/res/flags/VA.png
new file mode 100644
index 00000000..63a13c0e
Binary files /dev/null and b/res/flags/VA.png differ
diff --git a/res/flags/VC.png b/res/flags/VC.png
new file mode 100644
index 00000000..da991a93
Binary files /dev/null and b/res/flags/VC.png differ
diff --git a/res/flags/VE.png b/res/flags/VE.png
new file mode 100644
index 00000000..e75e17c9
Binary files /dev/null and b/res/flags/VE.png differ
diff --git a/res/flags/VG.png b/res/flags/VG.png
new file mode 100644
index 00000000..46f93cad
Binary files /dev/null and b/res/flags/VG.png differ
diff --git a/res/flags/VI.png b/res/flags/VI.png
new file mode 100644
index 00000000..8c849a73
Binary files /dev/null and b/res/flags/VI.png differ
diff --git a/res/flags/VN.png b/res/flags/VN.png
new file mode 100644
index 00000000..6ea2122f
Binary files /dev/null and b/res/flags/VN.png differ
diff --git a/res/flags/VU.png b/res/flags/VU.png
new file mode 100644
index 00000000..bad3ba4d
Binary files /dev/null and b/res/flags/VU.png differ
diff --git a/res/flags/WF.png b/res/flags/WF.png
new file mode 100644
index 00000000..d94359dc
Binary files /dev/null and b/res/flags/WF.png differ
diff --git a/res/flags/WS.png b/res/flags/WS.png
new file mode 100644
index 00000000..f8b80e5b
Binary files /dev/null and b/res/flags/WS.png differ
diff --git a/res/flags/YE.png b/res/flags/YE.png
new file mode 100644
index 00000000..8b9bbd89
Binary files /dev/null and b/res/flags/YE.png differ
diff --git a/res/flags/YT.png b/res/flags/YT.png
new file mode 100644
index 00000000..32887936
Binary files /dev/null and b/res/flags/YT.png differ
diff --git a/res/flags/ZA.png b/res/flags/ZA.png
new file mode 100644
index 00000000..7f0a52d3
Binary files /dev/null and b/res/flags/ZA.png differ
diff --git a/res/flags/ZM.png b/res/flags/ZM.png
new file mode 100644
index 00000000..87adc3af
Binary files /dev/null and b/res/flags/ZM.png differ
diff --git a/res/flags/ZW.png b/res/flags/ZW.png
new file mode 100644
index 00000000..742c9f7e
Binary files /dev/null and b/res/flags/ZW.png differ
diff --git a/res/home.html b/res/home.html
new file mode 100644
index 00000000..3ba2e964
--- /dev/null
+++ b/res/home.html
@@ -0,0 +1,292 @@
+
+
+
+
+
+
+
_t("Welcome to Riot.im")
+
_t("Decentralised, encrypted chat & collaboration powered by [matrix]")
+
+
+
+
+
+
_t("Search the room directory")
+
+
+
+
+ _t("Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!")
+
+
+
+
+
+
_t("Chat with Riot Bot")
+
+
+
+
+ _t("Get started with some tips from Riot Bot!")
+
+
);
diff --git a/src/components/structures/CompatibilityPage.js b/src/components/structures/CompatibilityPage.js
index bae33803..88b01cb2 100644
--- a/src/components/structures/CompatibilityPage.js
+++ b/src/components/structures/CompatibilityPage.js
@@ -17,6 +17,7 @@ limitations under the License.
'use strict';
var React = require('react');
+import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
module.exports = React.createClass({
displayName: 'CompatibilityPage',
@@ -39,23 +40,37 @@ module.exports = React.createClass({
return (
-
Sorry, your browser is not able to run Riot.
+
{ _tJsx("Sorry, your browser is not able to run Riot.", /(.*?)<\/b>/, (sub) => {sub}) }
- Riot uses many advanced browser features, some of which are not
- available or experimental in your current browser.
+ { _t("Riot uses many advanced browser features, some of which are not available or experimental in your current browser.") }
- With your current browser, the look and feel of the application may
- be completely incorrect, and some or all features may not function.
- If you want to try it anyway you can continue, but you are on your own
- in terms of any issues you may encounter!
+ { _t("With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!") }
diff --git a/src/components/structures/HomePage.js b/src/components/structures/HomePage.js
index 8d44c90a..2311cc1f 100644
--- a/src/components/structures/HomePage.js
+++ b/src/components/structures/HomePage.js
@@ -18,23 +18,82 @@ limitations under the License.
'use strict';
import React from 'react';
-import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
-import sdk from 'matrix-react-sdk';
+import GeminiScrollbar from 'react-gemini-scrollbar';
+import request from 'browser-request';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+import sanitizeHtml from 'sanitize-html';
module.exports = React.createClass({
displayName: 'HomePage',
propTypes: {
- teamServerUrl: React.PropTypes.string.isRequired,
- teamToken: React.PropTypes.string.isRequired,
- collapsedRhs: React.PropTypes.bool,
+ // URL base of the team server. Optional.
+ teamServerUrl: React.PropTypes.string,
+ // Team token. Optional. If set, used to get the static homepage of the team
+ // associated. If unset, homePageUrl will be used.
+ teamToken: React.PropTypes.string,
+ // URL to use as the iFrame src. Defaults to /home.html.
+ homePageUrl: React.PropTypes.string,
+ },
+
+ getInitialState: function() {
+ return {
+ iframeSrc: '',
+ page: '',
+ };
+ },
+
+ translate: function(s) {
+ s = sanitizeHtml(_t(s));
+ // ugly fix for https://github.com/vector-im/riot-web/issues/4243
+ s = s.replace(/Riot\.im/, 'Riot.im');
+ s = s.replace(/\[matrix\]/, '');
+ return s;
+ },
+
+ componentWillMount: function() {
+ if (this.props.teamToken && this.props.teamServerUrl) {
+ this.setState({
+ iframeSrc: `${this.props.teamServerUrl}/static/${this.props.teamToken}/home.html`
+ });
+ }
+ else {
+ // we use request() to inline the homepage into the react component
+ // so that it can inherit CSS and theming easily rather than mess around
+ // with iframes and trying to synchronise document.stylesheets.
+
+ let src = this.props.homePageUrl || 'home.html';
+
+ request(
+ { method: "GET", url: src },
+ (err, response, body) => {
+ if (err || response.status < 200 || response.status >= 300) {
+ console.log(err);
+ this.setState({ page: "Couldn't load home page" });
+ }
+
+ body = body.replace(/_t\(['"]([\s\S]*?)['"]\)/mg, (match, g1)=>this.translate(g1));
+ this.setState({ page: body });
+ }
+ );
+ }
},
render: function() {
- return (
-
-
- );
+ if (this.state.iframeSrc) {
+ return (
+
+
+
+ );
+ }
+ else {
+ return (
+
+
+
+
+ );
+ }
}
});
diff --git a/src/components/structures/LeftPanel.js b/src/components/structures/LeftPanel.js
index a9df37a8..77338404 100644
--- a/src/components/structures/LeftPanel.js
+++ b/src/components/structures/LeftPanel.js
@@ -21,16 +21,18 @@ var DragDropContext = require('react-dnd').DragDropContext;
var HTML5Backend = require('react-dnd-html5-backend');
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
+import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
var VectorConferenceHandler = require('../../VectorConferenceHandler');
var CallHandler = require("matrix-react-sdk/lib/CallHandler");
+import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
+
var LeftPanel = React.createClass({
displayName: 'LeftPanel',
propTypes: {
collapsed: React.PropTypes.bool.isRequired,
- teamToken: React.PropTypes.string,
},
getInitialState: function() {
@@ -97,17 +99,21 @@ var LeftPanel = React.createClass({
render: function() {
var RoomList = sdk.getComponent('rooms.RoomList');
var BottomLeftMenu = sdk.getComponent('structures.BottomLeftMenu');
- var SearchBox = sdk.getComponent('structures.SearchBox');
- var collapseButton;
+ var topBox;
+ if (MatrixClientPeg.get().isGuest()) {
+ var LoginBox = sdk.getComponent('structures.LoginBox');
+ topBox = ;
+ }
+ else {
+ var SearchBox = sdk.getComponent('structures.SearchBox');
+ topBox = ;
+ }
+
var classes = "mx_LeftPanel mx_fadable";
if (this.props.collapsed) {
classes += " collapsed";
}
- else {
- // Hide the collapse button until we work out how to display it in the new skin
- // collapseButton =
- }
var callPreview;
if (this.state.showCallElement && !this.props.collapsed) {
@@ -121,15 +127,14 @@ var LeftPanel = React.createClass({
return (
);
}
diff --git a/src/components/structures/LoginBox.js b/src/components/structures/LoginBox.js
new file mode 100644
index 00000000..c9f8e87a
--- /dev/null
+++ b/src/components/structures/LoginBox.js
@@ -0,0 +1,93 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+'use strict';
+
+var React = require('react');
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+var sdk = require('matrix-react-sdk')
+var dis = require('matrix-react-sdk/lib/dispatcher');
+var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
+var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
+
+module.exports = React.createClass({
+ displayName: 'LoginBox',
+
+ propTypes: {
+ collapsed: React.PropTypes.bool,
+ },
+
+ onToggleCollapse: function(show) {
+ if (show) {
+ dis.dispatch({
+ action: 'show_left_panel',
+ });
+ }
+ else {
+ dis.dispatch({
+ action: 'hide_left_panel',
+ });
+ }
+ },
+
+ onLoginClick: function() {
+ dis.dispatch({ action: 'start_login' });
+ },
+
+ onRegisterClick: function() {
+ dis.dispatch({ action: 'start_registration' });
+ },
+
+ render: function() {
+ var TintableSvg = sdk.getComponent('elements.TintableSvg');
+
+ var toggleCollapse;
+ if (this.props.collapsed) {
+ toggleCollapse =
+
+
+
+ }
+ else {
+ toggleCollapse =
+
+
+
+ }
+
+ var loginButton;
+ if (!this.props.collapsed) {
+ loginButton = (
+
;
diff --git a/src/components/structures/RoomDirectory.js b/src/components/structures/RoomDirectory.js
index e723cf1a..64a53d33 100644
--- a/src/components/structures/RoomDirectory.js
+++ b/src/components/structures/RoomDirectory.js
@@ -23,7 +23,6 @@ var ContentRepo = require("matrix-js-sdk").ContentRepo;
var Modal = require('matrix-react-sdk/lib/Modal');
var sdk = require('matrix-react-sdk');
var dis = require('matrix-react-sdk/lib/dispatcher');
-var GeminiScrollbar = require('react-gemini-scrollbar');
var linkify = require('linkifyjs');
var linkifyString = require('linkifyjs/string');
@@ -31,6 +30,8 @@ var linkifyMatrix = require('matrix-react-sdk/lib/linkify-matrix');
var sanitizeHtml = require('sanitize-html');
var q = require('q');
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+
import {instanceForInstanceId, protocolNameForInstanceId} from '../../utils/DirectoryUtils';
linkifyMatrix(linkify);
@@ -61,6 +62,7 @@ module.exports = React.createClass({
},
componentWillMount: function() {
+ this._unmounted = false;
this.nextBatch = null;
this.filterTimeout = null;
this.scrollPanel = null;
@@ -80,8 +82,8 @@ module.exports = React.createClass({
}
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
- title: "Failed to get protocol list from Home Server",
- description: "The Home Server may be too old to support third party networks",
+ title: _t('Failed to get protocol list from Home Server'),
+ description: _t('The Home Server may be too old to support third party networks'),
});
});
@@ -98,6 +100,10 @@ module.exports = React.createClass({
// sideOpacity: 1.0,
// middleOpacity: 1.0,
// });
+ if (this.filterTimeout) {
+ clearTimeout(this.filterTimeout);
+ }
+ this._unmounted = true;
},
refreshRoomList: function() {
@@ -140,6 +146,11 @@ module.exports = React.createClass({
return;
}
+ if (this._unmounted) {
+ // if we've been unmounted, we don't care either.
+ return;
+ }
+
this.nextBatch = data.next_batch;
this.setState((s) => {
s.publicRooms.push(...data.chunk);
@@ -157,12 +168,18 @@ module.exports = React.createClass({
// requests either
return;
}
+
+ if (this._unmounted) {
+ // if we've been unmounted, we don't care either.
+ return;
+ }
+
this.setState({ loading: false });
console.error("Failed to get publicRooms: %s", JSON.stringify(err));
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
- title: "Failed to get public room list",
- description: "The server may be unavailable or overloaded",
+ title: _t('Failed to get public room list'),
+ description: ((err && err.message) ? err.message : _t('The server may be unavailable or overloaded'))
});
});
},
@@ -176,42 +193,42 @@ module.exports = React.createClass({
*/
removeFromDirectory: function(room) {
var alias = get_display_alias_for_room(room);
- var name = room.name || alias || "Unnamed room";
+ var name = room.name || alias || _t('Unnamed room');
var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var desc;
if (alias) {
- desc = `Delete the room alias '${alias}' and remove '${name}' from the directory?`;
+ desc = _t('Delete the room alias %(alias)s and remove %(name)s from the directory?', {alias: alias, name: name});
} else {
- desc = `Remove '${name}' from the directory?`;
+ desc = _t('Remove %(name)s from the directory?', {name: name});
}
Modal.createDialog(QuestionDialog, {
- title: "Remove from Directory",
+ title: _t('Remove from Directory'),
description: desc,
onFinished: (should_delete) => {
if (!should_delete) return;
var Loader = sdk.getComponent("elements.Spinner");
var modal = Modal.createDialog(Loader);
- var step = `remove '${name}' from the directory.`;
+ var step = _t('remove %(name)s from the directory.', {name: name});
MatrixClientPeg.get().setRoomDirectoryVisibility(room.room_id, 'private').then(() => {
if (!alias) return;
- step = 'delete the alias.';
+ step = _t('delete the alias.');
return MatrixClientPeg.get().deleteAlias(alias);
}).done(() => {
modal.close();
this.refreshRoomList();
- }, function(err) {
+ }, (err) => {
modal.close();
this.refreshRoomList();
console.error("Failed to " + step + ": " + err);
Modal.createDialog(ErrorDialog, {
- title: "Error",
- description: "Failed to " + step,
+ title: _t('Error'),
+ description: ((err && err.message) ? err.message : _t('The server may be unavailable or overloaded'))
});
});
}
@@ -299,8 +316,8 @@ module.exports = React.createClass({
if (!fields) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
- title: "Unable to join network",
- description: "Riot does not know how to join a room on this network",
+ title: _t('Unable to join network'),
+ description: _t('Riot does not know how to join a room on this network'),
});
return;
}
@@ -310,15 +327,15 @@ module.exports = React.createClass({
} else {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
- title: "Room not found",
- description: "Couldn't find a matching Matrix room",
+ title: _t('Room not found'),
+ description: _t('Couldn\'t find a matching Matrix room'),
});
}
}, (e) => {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
- title: "Fetching third party location failed",
- description: "Unable to look up room ID from server",
+ title: _t('Fetching third party location failed'),
+ description: _t('Unable to look up room ID from server'),
});
});
}
@@ -336,11 +353,7 @@ module.exports = React.createClass({
// to the directory.
if (MatrixClientPeg.get().isGuest()) {
if (!room.world_readable && !room.guest_can_join) {
- var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
- Modal.createDialog(NeedToRegisterDialog, {
- title: "Failed to join the room",
- description: "This room is inaccessible to guests. You may be able to join if you register."
- });
+ dis.dispatch({action: 'view_set_mxid'});
return;
}
}
@@ -353,7 +366,7 @@ module.exports = React.createClass({
avatarUrl: room.avatar_url,
// XXX: This logic is duplicated from the JS SDK which
// would normally decide what the name is.
- name: room.name || room_alias || "Unnamed room",
+ name: room.name || room_alias || _t('Unnamed room'),
};
}
// It's not really possible to join Matrix rooms by ID because the HS has no way to know
@@ -378,18 +391,18 @@ module.exports = React.createClass({
var self = this;
var guestRead, guestJoin, perms;
for (var i = 0; i < rooms.length; i++) {
- var name = rooms[i].name || get_display_alias_for_room(rooms[i]) || "Unnamed room";
+ var name = rooms[i].name || get_display_alias_for_room(rooms[i]) || _t('Unnamed room');
guestRead = null;
guestJoin = null;
if (rooms[i].world_readable) {
guestRead = (
-
World readable
+
{ _t('World readable') }
);
}
if (rooms[i].guest_can_join) {
guestJoin = (
-
Guests can join
+
{ _t('Guests can join') }
);
}
@@ -460,6 +473,17 @@ module.exports = React.createClass({
return fields;
},
+ /**
+ * called by the parent component when PageUp/Down/etc is pressed.
+ *
+ * We pass it down to the scroll panel.
+ */
+ handleScrollKey: function(ev) {
+ if (this.scrollPanel) {
+ this.scrollPanel.handleScrollKey(ev);
+ }
+ },
+
render: function() {
const SimpleRoomHeader = sdk.getComponent('rooms.SimpleRoomHeader');
const Loader = sdk.getComponent("elements.Spinner");
@@ -467,7 +491,7 @@ module.exports = React.createClass({
if (this.state.protocolsLoading) {
return (
-
+
);
@@ -485,7 +509,7 @@ module.exports = React.createClass({
// request from the scrollpanel because there isn't one
let scrollpanel_content;
if (rows.length == 0) {
- scrollpanel_content = No rooms to show;
+ scrollpanel_content = { _t('No rooms to show') };
} else {
scrollpanel_content =
@@ -519,9 +543,9 @@ module.exports = React.createClass({
}
- let placeholder = 'Search for a room';
+ let placeholder = _t('Search for a room');
if (!this.state.instanceId) {
- placeholder = '#example:' + this.state.roomServer;
+ placeholder = _t('#example') + ':' + this.state.roomServer;
} else if (instance_expected_field_type) {
placeholder = instance_expected_field_type.placeholder;
}
@@ -538,7 +562,7 @@ module.exports = React.createClass({
const DirectorySearchBox = sdk.getComponent('elements.DirectorySearchBox');
return (
-
+
-
more
+
{ _t("more") }
{ content }
);
@@ -508,8 +513,8 @@ var RoomSubList = React.createClass({
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
console.error("Failed to add tag " + self.props.tagName + " to room" + err);
Modal.createDialog(ErrorDialog, {
- title: "Error",
- description: "Failed to add tag " + self.props.tagName + " to room",
+ title: _t('Failed to add tag %(tagName)s to room', {tagName: self.props.tagName}),
+ description: ((err && err.message) ? err.message : _t('Operation failed')),
});
});
break;
@@ -520,16 +525,15 @@ var RoomSubList = React.createClass({
render: function() {
var connectDropTarget = this.props.connectDropTarget;
- var RoomDropTarget = sdk.getComponent('rooms.RoomDropTarget');
var TruncatedList = sdk.getComponent('elements.TruncatedList');
var label = this.props.collapsed ? null : this.props.label;
- //console.log("render: " + JSON.stringify(this.state.sortedList));
-
- var target;
- if (this.state.sortedList.length == 0 && this.props.editable) {
- target = ;
+ let content;
+ if (this.state.sortedList.length == 0 && !this.props.searchFilter) {
+ content = this.props.emptyContent;
+ } else {
+ content = this.makeRoomTiles();
}
if (this.state.sortedList.length > 0 || this.props.editable) {
@@ -539,8 +543,7 @@ var RoomSubList = React.createClass({
if (!this.state.hidden) {
subList =
- { target }
- { this.makeRoomTiles() }
+ { content }
;
}
else {
diff --git a/src/components/structures/SearchBox.js b/src/components/structures/SearchBox.js
index 729e7ef7..99c44866 100644
--- a/src/components/structures/SearchBox.js
+++ b/src/components/structures/SearchBox.js
@@ -17,6 +17,7 @@ limitations under the License.
'use strict';
var React = require('react');
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
var sdk = require('matrix-react-sdk')
var dis = require('matrix-react-sdk/lib/dispatcher');
var rate_limited_func = require('matrix-react-sdk/lib/ratelimitedfunc');
@@ -99,13 +100,13 @@ module.exports = React.createClass({
if (this.props.collapsed) {
toggleCollapse =
-
+
}
else {
toggleCollapse =
-
+
}
@@ -134,7 +135,7 @@ module.exports = React.createClass({
className="mx_SearchBox_search"
value={ this.state.searchTerm }
onChange={ this.onChange }
- placeholder="Filter room names"
+ placeholder={ _t('Filter room names') }
/>
];
}
diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js
index db416b8a..bc82778a 100644
--- a/src/components/views/context_menus/MessageContextMenu.js
+++ b/src/components/views/context_menus/MessageContextMenu.js
@@ -16,13 +16,14 @@ limitations under the License.
'use strict';
-var React = require('react');
+const React = require('react');
-var MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
-var dis = require('matrix-react-sdk/lib/dispatcher');
-var sdk = require('matrix-react-sdk');
-var Modal = require('matrix-react-sdk/lib/Modal');
-var Resend = require("matrix-react-sdk/lib/Resend");
+const MatrixClientPeg = require('matrix-react-sdk/lib/MatrixClientPeg');
+const dis = require('matrix-react-sdk/lib/dispatcher');
+const sdk = require('matrix-react-sdk');
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+const Modal = require('matrix-react-sdk/lib/Modal');
+const Resend = require("matrix-react-sdk/lib/Resend");
import * as UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
module.exports = React.createClass({
@@ -39,13 +40,38 @@ module.exports = React.createClass({
onFinished: React.PropTypes.func,
},
+ getInitialState: function() {
+ return {
+ canRedact: false,
+ };
+ },
+
+ componentWillMount: function() {
+ MatrixClientPeg.get().on('RoomMember.powerLevel', this._checkCanRedact);
+ this._checkCanRedact();
+ },
+
+ componentWillUnmount: function() {
+ const cli = MatrixClientPeg.get();
+ if (cli) {
+ cli.removeListener('RoomMember.powerLevel', this._checkCanRedact);
+ }
+ },
+
+ _checkCanRedact: function() {
+ const cli = MatrixClientPeg.get();
+ const room = cli.getRoom(this.props.mxEvent.getRoomId());
+ const canRedact = room.currentState.maySendRedactionForEvent(this.props.mxEvent, cli.credentials.userId);
+ this.setState({canRedact});
+ },
+
onResendClick: function() {
Resend.resend(this.props.mxEvent);
if (this.props.onFinished) this.props.onFinished();
},
onViewSourceClick: function() {
- var ViewSource = sdk.getComponent('structures.ViewSource');
+ const ViewSource = sdk.getComponent('structures.ViewSource');
Modal.createDialog(ViewSource, {
content: this.props.mxEvent.event,
}, 'mx_Dialog_viewsource');
@@ -70,12 +96,12 @@ module.exports = React.createClass({
MatrixClientPeg.get().redactEvent(
this.props.mxEvent.getRoomId(), this.props.mxEvent.getId()
).catch(function(e) {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
// display error message stating you couldn't delete this.
- var code = e.errcode || e.statusCode;
+ const code = e.errcode || e.statusCode;
Modal.createDialog(ErrorDialog, {
- title: "Error",
- description: "You cannot delete this message. (" + code + ")"
+ title: _t('Error'),
+ description: _t('You cannot delete this message. (%(code)s)', {code: code})
});
}).done();
},
@@ -88,6 +114,14 @@ module.exports = React.createClass({
if (this.props.onFinished) this.props.onFinished();
},
+ onForwardClick: function() {
+ dis.dispatch({
+ action: 'forward_event',
+ event: this.props.mxEvent,
+ });
+ this.closeMenu();
+ },
+
closeMenu: function() {
if (this.props.onFinished) this.props.onFinished();
},
@@ -99,7 +133,7 @@ module.exports = React.createClass({
if (this.props.onFinished) this.props.onFinished();
},
- onQuoteClick: function () {
+ onQuoteClick: function() {
console.log(this.props.mxEvent);
dis.dispatch({
action: 'quote',
@@ -108,28 +142,29 @@ module.exports = React.createClass({
},
render: function() {
- var eventStatus = this.props.mxEvent.status;
- var resendButton;
- var viewSourceButton;
- var viewClearSourceButton;
- var redactButton;
- var cancelButton;
- var permalinkButton;
- var unhidePreviewButton;
- var externalURLButton;
+ const eventStatus = this.props.mxEvent.status;
+ let resendButton;
+ let redactButton;
+ let cancelButton;
+ let forwardButton;
+ let viewSourceButton;
+ let viewClearSourceButton;
+ let unhidePreviewButton;
+ let permalinkButton;
+ let externalURLButton;
if (eventStatus === 'not_sent') {
resendButton = (
- Resend
+ { _t('Resend') }
);
}
- if (!eventStatus && !this.props.mxEvent.isRedacted()) { // sent and not redacted
+ if (!eventStatus && this.state.canRedact) {
redactButton = (
Please describe the bug. What did you do?
- What did you expect to happen?
- What actually happened?
+
+ { _t("Please describe the bug. What did you do? What did you expect to happen? What actually happened?") }
+
-
In order to diagnose problems, logs from this client will be sent with
- this bug report.
- If you would prefer to only send the text above, please untick:
+
+ { _t("In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:") }
+
);
return (
)
diff --git a/src/components/views/dialogs/SetPasswordDialog.js b/src/components/views/dialogs/SetPasswordDialog.js
new file mode 100644
index 00000000..b82d0346
--- /dev/null
+++ b/src/components/views/dialogs/SetPasswordDialog.js
@@ -0,0 +1,137 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import React from 'react';
+import sdk from 'matrix-react-sdk';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+import Modal from 'matrix-react-sdk/lib/Modal';
+
+const WarmFuzzy = function(props) {
+ const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
+ let title = _t('You have successfully set a password!');
+ if (props.didSetEmail) {
+ title = _t('You have successfully set a password and an email address!');
+ }
+ const advice = _t('You can now return to your account after signing out, and sign in on other devices.');
+ let extraAdvice = null;
+ if (!props.didSetEmail) {
+ extraAdvice = _t('Remember, you can always set an email address in user settings if you change your mind.');
+ }
+
+ return
+
diff --git a/src/components/views/globals/GuestWarningBar.js b/src/components/views/globals/GuestWarningBar.js
deleted file mode 100644
index 810021cc..00000000
--- a/src/components/views/globals/GuestWarningBar.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Copyright 2016 OpenMarket Ltd
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-var React = require('react');
-var dis = require('matrix-react-sdk/lib/dispatcher')
-
-module.exports = React.createClass({
- displayName: 'GuestWarningBar',
-
- onRegisterClicked: function() {
- dis.dispatch({'action': 'start_upgrade_registration'});
- },
-
- onLoginClicked: function() {
- dis.dispatch({'action': 'logout'});
- dis.dispatch({'action': 'start_login'});
- },
-
- render: function() {
- return (
-
-
-
- You are Rioting as a guest. Register or sign in to access more rooms and features.
-
);
- }
+ },
});
diff --git a/src/components/views/globals/NewVersionBar.js b/src/components/views/globals/NewVersionBar.js
index 3e03be72..219ef02a 100644
--- a/src/components/views/globals/NewVersionBar.js
+++ b/src/components/views/globals/NewVersionBar.js
@@ -20,6 +20,7 @@ import React from 'react';
import sdk from 'matrix-react-sdk';
import Modal from 'matrix-react-sdk/lib/Modal';
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
/**
* Check a version string is compatible with the Changelog
@@ -40,9 +41,9 @@ export default React.createClass({
displayReleaseNotes: function(releaseNotes) {
const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog');
Modal.createDialog(QuestionDialog, {
- title: "What's New",
+ title: _t("What's New"),
description:
{releaseNotes}
,
- button: "Update",
+ button: _t("Update"),
onFinished: (update) => {
if(update && PlatformPeg.get()) {
PlatformPeg.get().installUpdate();
@@ -75,17 +76,29 @@ export default React.createClass({
// automatically tells you what's changed (provided the versions
// are in the right format)
if (this.props.releaseNotes) {
- action_button = ;
+ action_button = (
+
+ );
} else if (checkVersion(this.props.version) && checkVersion(this.props.newVersion)) {
- action_button = ;
+ action_button = (
+
+ );
} else if (PlatformPeg.get()) {
- action_button = ;
+ action_button = (
+
+ );
}
return (
- A new version of Riot is available.
+ {_t("A new version of Riot is available.")}
{action_button}
diff --git a/src/components/views/globals/PasswordNagBar.js b/src/components/views/globals/PasswordNagBar.js
new file mode 100644
index 00000000..37d011a6
--- /dev/null
+++ b/src/components/views/globals/PasswordNagBar.js
@@ -0,0 +1,60 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+'use strict';
+
+import React from 'react';
+import sdk from 'matrix-react-sdk';
+import Modal from 'matrix-react-sdk/lib/Modal';
+import dis from 'matrix-react-sdk/lib/dispatcher';
+
+export default React.createClass({
+ onUpdateClicked: function() {
+ const SetPasswordDialog = sdk.getComponent('dialogs.SetPasswordDialog');
+ Modal.createDialog(SetPasswordDialog, {
+ onFinished: (passwordChanged) => {
+ if (!passwordChanged) {
+ return;
+ }
+ // Notify SessionStore that the user's password was changed
+ dis.dispatch({
+ action: 'password_changed',
+ });
+ }
+ });
+ },
+
+ render: function() {
+ const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
+ const toolbarClasses = "mx_MatrixToolbar mx_MatrixToolbar_clickable";
+ return (
+
+
+
+ To return to your account in future you need to set a password
+
- Custom Server Options
+ { _t('Custom Server Options') }
-
- You can use the custom server options to sign into other Matrix
- servers by specifying a different Home server URL.
-
- This allows you to use Riot with an existing Matrix account on
- a different home server.
-
-
- You can also set a custom identity server but you won't be able to
- invite users by email address, or be invited by email address yourself.
-
+
diff --git a/src/components/views/login/VectorLoginFooter.js b/src/components/views/login/VectorLoginFooter.js
index 1382a862..e905afc1 100644
--- a/src/components/views/login/VectorLoginFooter.js
+++ b/src/components/views/login/VectorLoginFooter.js
@@ -17,6 +17,7 @@ limitations under the License.
'use strict';
var React = require('react');
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
module.exports = React.createClass({
displayName: 'VectorLoginFooter',
@@ -30,7 +31,7 @@ module.exports = React.createClass({
blog ·
twitter ·
github ·
- powered by Matrix
+ { _t('powered by Matrix') }
- All notifications are currently disabled for all targets.
+ { _t('All notifications are currently disabled for all targets.') }.
);
@@ -723,13 +735,13 @@ module.exports = React.createClass({
let emailNotificationsRow;
if (emailThreepids.length === 0) {
emailNotificationsRow =
- Add an email address above to configure email notifications
+ { _t('Add an email address above to configure email notifications') }
;
} else {
// This only supports the first email address in your profile for now
emailNotificationsRow = this.emailNotificationsRow(
emailThreepids[0].address,
- "Enable email notifications ("+emailThreepids[0].address+")"
+ _t('Enable email notifications') + ' (' + emailThreepids[0].address + ')'
);
}
@@ -737,7 +749,7 @@ module.exports = React.createClass({
var externalRules = [];
for (var i in this.state.externalPushRules) {
var rule = this.state.externalPushRules[i];
- externalRules.push(
{ rule.description }
);
+ externalRules.push(
{ _t(rule.description) }
);
}
// Show keywords not displayed by the vector UI as a single external push rule
@@ -748,12 +760,12 @@ module.exports = React.createClass({
}
if (externalKeyWords.length) {
externalKeyWords = externalKeyWords.join(", ");
- externalRules.push(
Notifications on the following keywords follow rules which can’t be displayed here: { externalKeyWords }
);
+ externalRules.push(
{ _t('Notifications on the following keywords follow rules which can’t be displayed here:') } { externalKeyWords }
);
}
var devicesSection;
if (this.state.pushers === undefined) {
- devicesSection =
Unable to fetch notification target list
+ devicesSection =
{ _t('Unable to fetch notification target list') }
- There are advanced notifications which are not shown here.
- You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply.
+
{ _t('Advanced notification settings') }
+ { _t('There are advanced notifications which are not shown here') }.
+ { _t('You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply') }.
diff --git a/src/i18n/strings/ar.json b/src/i18n/strings/ar.json
new file mode 100644
index 00000000..075c0b59
--- /dev/null
+++ b/src/i18n/strings/ar.json
@@ -0,0 +1,6 @@
+{
+ "All messages": "كل الرسائل",
+ "Continue": "استمر",
+ "Please set a password!": "يرجى تعيين كلمة مرور!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "سيسمح لك هذا بالعودة إلى حسابك بعد الخروج، وتسجيل الدخول على الأجهزة الأخرى."
+}
diff --git a/src/i18n/strings/basefile.json b/src/i18n/strings/basefile.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/src/i18n/strings/basefile.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/i18n/strings/be.json b/src/i18n/strings/be.json
new file mode 100644
index 00000000..69a6a923
--- /dev/null
+++ b/src/i18n/strings/be.json
@@ -0,0 +1,88 @@
+{
+ "Add an email address above to configure email notifications": "Дадайце адрас электроннай пошты вышэй, каб наладзіць апавяшчэнні",
+ "All messages": "Усе паведамленні",
+ "All messages (loud)": "Усе паведамленні (гучна)",
+ "All notifications are currently disabled for all targets.": "Усе апавяшчэнні ў цяперашні час адключаныя для ўсіх мэтаў.",
+ "An error occurred whilst saving your email notification preferences.": "Адбылася памылка падчас захавання налады апавяшчэнняў па электроннай пошце.",
+ "Cancel Sending": "Адмяніць адпраўку",
+ "Can't update user notification settings": "Немагчыма абнавіць налады апавяшчэнняў карыстальніка",
+ "Close": "Зачыніць",
+ "Create new room": "Стварыць новы пакой",
+ "Couldn't find a matching Matrix room": "Не атрымалася знайсці адпаведны пакой Matrix",
+ "Custom Server Options": "Карыстальніцкія параметры сервера",
+ "delete the alias.": "выдаліць псеўданім.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Выдаліць псеўданім пакоя %(alias)s і выдаліць %(name)s з каталога?",
+ "Direct Chat": "Прамы чат",
+ "Directory": "Каталог",
+ "Dismiss": "Aдхіліць",
+ "Download this file": "Спампаваць гэты файл",
+ "Drop here %(toAction)s": "Перацягнуць сюды %(toAction)s",
+ "Enable audible notifications in web client": "Ўключыць гукавыя апавяшчэнні ў вэб-кліенце",
+ "Enable desktop notifications": "Ўключыць апавяшчэнні на працоўным стале",
+ "Enable email notifications": "Ўключыць паведамлення па электроннай пошце",
+ "Enable notifications for this account": "Ўключыць апавяшчэнні для гэтага ўліковага запісу",
+ "Enable them now": "Уключыць іх зараз",
+ "Enter keywords separated by a comma:": "Калі ласка, увядзіце ключавыя словы, падзеленыя коскамі:",
+ "Error": "Памылка",
+ "Error saving email notification preferences": "Памылка захавання налад апавяшчэнняў па электроннай пошце",
+ "#example": "#прыклад",
+ "Failed to": "Не атрымалася",
+ "Failed to add tag %(tagName)s to room": "Не атрымалася дадаць %(tagName)s ў пакоі",
+ "Failed to change settings": "Не атрымалася змяніць налады",
+ "Failed to forget room %(errCode)s": "Не атрымалася забыць пакой %(errCode)s",
+ "Failed to update keywords": "Не атрымалася абнавіць ключавыя словы",
+ "Failed to get protocol list from Home Server": "Не ўдалося атрымаць спіс пратаколаў ад хатняга сервера",
+ "Failed to get public room list": "Не ўдалося атрымаць спіс агульных пакояў",
+ "Failed to join the room": "Не ўдалося далучыцца да пакоя",
+ "Failed to remove tag %(tagName)s from room": "Не ўдалося выдаліць %(tagName)s з пакоя",
+ "Failed to set direct chat tag": "Не ўдалося ўсталяваць тэг прамога чата",
+ "Failed to set Direct Message status of room": "Не ўдалося ўсталяваць статут прамога паведамлення пакою",
+ "Favourite": "Улюбёнае",
+ "Fetching third party location failed": "Не ўдалося атрымаць месцазнаходжанне трэцяга боку",
+ "Files": "Файлы",
+ "Filter room names": "Фільтр iмёнаў пакояў",
+ "Forget": "Забыць",
+ " from room": " з пакоя",
+ "Guests can join": "Госці могуць далучыцца",
+ "Guest users can't invite users. Please register to invite.": "Госцi не могуць запрашаць карыстальнікаў. Калі ласка, зарэгіструйцеся, каб запрасiць.",
+ "Invite to this room": "Запрасіць у гэты пакой",
+ "Keywords": "Ключавыя словы",
+ "Leave": "Пакінуць",
+ "Low Priority": "Нізкі прыярытэт",
+ "Members": "Удзельнікі",
+ "Mentions only": "Толькі згадкі",
+ "Mute": "Без гуку",
+ "No rooms to show": "Няма пакояў для паказу",
+ "Noisy": "Шумна",
+ "Notification targets": "Мэты апавяшчэння",
+ "Notifications": "Апавяшчэнні",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Апавяшчэнні па наступных ключавых словах прытрымліваюцца правілаў, якія не могуць быць адлюстраваны тут",
+ "Notify for all other messages/rooms": "Апавяшчаць для ўсіх іншых паведамленняў/пакояў",
+ "Notify me for anything else": "Паведаміць мне што-небудзь яшчэ",
+ "Off": "Выключыць",
+ "On": "Уключыць",
+ "Operation failed": "Не атрымалася выканаць аперацыю",
+ "Permalink": "Пастаянная спасылка",
+ "Please Register": "Калі ласка, зарэгіструйцеся",
+ "powered by Matrix": "працуе на Matrix",
+ "Quote": "Цытата",
+ "Redact": "Адрэдагаваць",
+ "Reject": "Адхіліць",
+ "Remove %(name)s from the directory?": "Выдаліць %(name)s з каталога?",
+ "Remove": "Выдалiць",
+ "remove %(name)s from the directory.": "выдаліць %(name)s з каталога.",
+ "Remove from Directory": "Выдалiць з каталога",
+ "Resend": "Паўторна",
+ "Riot does not know how to join a room on this network": "Riot не ведае, як увайсці ў пакой у гэтай сетке",
+ "Room directory": "Каталог пакояў",
+ "Room not found": "Пакой не знойдзены",
+ "Search for a room": "Пошук па пакоі",
+ "Settings": "Налады",
+ "Source URL": "URL-адрас крыніцы",
+ "Start chat": "Пачаць чат",
+ "The Home Server may be too old to support third party networks": "Хатні сервер можа быць занадта стары для падтрымкі іншых сетак",
+ "There are advanced notifications which are not shown here": "Ёсць пашыраныя апавяшчэння, якія не паказаныя тут",
+ "The server may be unavailable or overloaded": "Сервер можа быць недаступны ці перагружаны",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Гэты пакой недаступны для гасцей. Вы можаце далучыцца, калі вы зарэгіструецеся.",
+ " to room": " ў пакоі"
+}
diff --git a/src/i18n/strings/bn_BD.json b/src/i18n/strings/bn_BD.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/src/i18n/strings/bn_BD.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/i18n/strings/bn_IN.json b/src/i18n/strings/bn_IN.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/src/i18n/strings/bn_IN.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/i18n/strings/da.json b/src/i18n/strings/da.json
new file mode 100644
index 00000000..4cd6c4b0
--- /dev/null
+++ b/src/i18n/strings/da.json
@@ -0,0 +1,84 @@
+{
+ "Add an email address above to configure email notifications": "Tilføj en emailadresse ovenfor for at konfigurere e-mail-underretninger",
+ "All notifications are currently disabled for all targets.": "Alle meddelelser er for øjeblikket deaktiveret for alle mål.",
+ "An error occurred whilst saving your email notification preferences.": "Der opstod en fejl under opbevaring af dine e-mail-underretningsindstillinger.",
+ "and remove": "Og fjern",
+ "Can't update user notification settings": "Kan ikke opdatere brugermeddelelsesindstillinger",
+ "Create new room": "Opret nyt rum",
+ "Couldn't find a matching Matrix room": "Kunne ikke finde et matchende Matrix-rum",
+ "Custom Server Options": "Brugerdefinerede serverindstillinger",
+ "delete the alias.": "Slet aliaset.",
+ "Delete the room alias": "Slet room alias",
+ "Direct Chat": "Personligt Chat",
+ "Directory": "Rum fortegnelse",
+ "Dismiss": "Afskedige",
+ "Drop here to": "Drop her til",
+ "Enable audible notifications in web client": "Aktivér hørbare underretninger i webklienten",
+ "Enable desktop notifications": "Aktivér desktop meddelelser",
+ "Enable email notifications": "Aktivér e-mail-underretninger",
+ "Enable notifications for this account": "Aktivér underretninger for dette brugernavn",
+ "Enable them now": "Aktivér dem nu",
+ "Enter keywords separated by a comma:": "Indtast søgeord adskilt af et komma:",
+ "Error": "Fejl",
+ "Error saving email notification preferences": "Fejl ved at gemme e-mail-underretningsindstillinger",
+ "#example": "#eksempel",
+ "Failed to": "Var ikke i stand til at",
+ "Failed to add tag ": "Kunne ikke tilføje tag ",
+ "Failed to change settings": "Kunne ikke ændre indstillinger",
+ "Failed to update keywords": "Kunne ikke opdatere søgeord",
+ "Failed to get protocol list from Home Server": "Kunne ikke få protokolliste fra Home Server",
+ "Failed to get public room list": "Kunne ikke få offentlig rumliste",
+ "Failed to join the room": "Kunne ikke komme ind i rumet",
+ "Failed to remove tag ": "Kunne ikke fjerne tag ",
+ "Failed to set Direct Message status of room": "Kunne ikke indstille direkte beskedstatus for rumet",
+ "Favourite": "Favorit",
+ "Fetching third party location failed": "Hentning af tredjeparts placering mislykkedes",
+ "Files": "Filer",
+ "Filter room names": "Filtrer rumnavne",
+ "Forget": "Glem",
+ "from the directory": "fra fortegnelsen",
+ " from room": " fra rum",
+ "Guests can join": "Gæster kan deltage",
+ "Guest users can't invite users. Please register to invite.": "Gæstebrugere kan ikke invitere brugere. Tilmeld dig venligst for at invitere.",
+ "Invite to this room": "Inviter til dette rum",
+ "Keywords": "Søgeord",
+ "Leave": "Forlade",
+ "Low Priority": "Lav prioritet",
+ "Members": "Medlemmer",
+ "No rooms to show": "Ingen rum at vise",
+ "Noisy": "Støjende",
+ "Notification targets": "Meddelelsesmål",
+ "Notifications": "Meddelser",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Meddelelser om følgende søgeord følger regler, der ikke kan vises her:",
+ "Notify for all other messages/rooms": "Underret om alle andre meddelelser / rum",
+ "Notify me for anything else": "Underret mig om noget andet",
+ "Off": "Slukket",
+ "On": "Tændt",
+ "Operation failed": "Operation mislykkedes",
+ "Please Register": "Vær venlig at registrere",
+ "powered by Matrix": "Drevet af Matrix",
+ "Reject": "Afvise",
+ "Remove": "Fjerne",
+ "remove": "fjerner",
+ "Remove from Directory": "Fjern fra fortegnelse",
+ "Riot does not know how to join a room on this network": "Riot ved ikke, hvordan man kan deltage i et rum på dette netværk",
+ "Room directory": "Rum fortegnelse",
+ "Room not found": "Rumet ikke fundet",
+ "Search for a room": "Søg efter et rum",
+ "Settings": "Indstillinger",
+ "Start chat": "Begyndt chat",
+ "The Home Server may be too old to support third party networks": "Hjemmeserveren kan være for gammel til at understøtte tredjepartsnetværk",
+ "There are advanced notifications which are not shown here": "Der er avancerede meddelelser, som ikke vises her",
+ "The server may be unavailable or overloaded": "Serveren kan være utilgængelig eller overbelastet",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Dette rum er utilgængeligt for gæster. Du kan være i stand til at deltage, hvis du registrerer dig.",
+ " to room": " til rum",
+ "Unable to fetch notification target list": "Kan ikke hente meddelelsesmålliste",
+ "Unable to join network": "Kan ikke deltage i netværket",
+ "Unable to look up room ID from server": "Kunne ikke slå op på rum-id fra server",
+ "unknown error code": "Ukendt fejlkode",
+ "Unnamed room": "Unnamed rum",
+ "World readable": "Læselig til alle",
+ "You are not receiving desktop notifications": "Du modtager ikke desktop meddelelser",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Du har muligvis konfigureret dem i en anden klient end Riot. Du kan ikke tune dem i Riot, men de gælder stadig",
+ "Close": "Luk"
+}
diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json
new file mode 100644
index 00000000..e6ae460e
--- /dev/null
+++ b/src/i18n/strings/de_DE.json
@@ -0,0 +1,211 @@
+{
+ "Please Register": "Bitte registrieren",
+ "Guest users can't invite users. Please register to invite.": "Gäste können keine Nutzer einladen. Bitte registriere dich, um Nutzer einzuladen.",
+ "Members": "Mitglieder",
+ "Files": "Dateien",
+ "Notifications": "Benachrichtigungen",
+ "Invite to this room": "In diesen Raum einladen",
+ "Filter room names": "Raum-Namen filtern",
+ "Start chat": "Chat starten",
+ "Room directory": "Raum-Verzeichnis",
+ "Create new room": "Neuen Raum erstellen",
+ "Settings": "Einstellungen",
+ "powered by Matrix": "betrieben mit Matrix",
+ "Custom Server Options": "Erweiterte Server-Optionen",
+ "Dismiss": "Ablehnen",
+ "Failed to get protocol list from Home Server": "Fehler beim Abrufen der Protokoll-Liste vom Home-Server",
+ "The Home Server may be too old to support third party networks": "Der Home-Server ist eventuell zu alt, um Drittanbieter-Netzwerke zu unterstützen",
+ "Directory": "Raum-Verzeichnis",
+ "#example:": "#beispiel:",
+ "Search for a room": "Nach einem Raum suchen",
+ "No rooms to show": "Keine Räume zum anzeigen",
+ "World readable": "Alle können mitlesen",
+ "Guests can join": "Gäste können beitreten",
+ "You are not receiving desktop notifications": "Du erhältst keine Desktop-Benachrichtigungen",
+ "Enable them now": "Aktiviere diese jetzt",
+ "Add an email address above to configure email notifications": "Füge oben eine E-Mail-Adresse hinzu, um die E-Mail-Benachrichtigungseinstellungen zu konfigurieren",
+ "All notifications are currently disabled for all targets.": "Im Moment sind alle Benachrichtigungen für alle Ziele deaktiviert.",
+ "An error occurred whilst saving your email notification preferences.": "Beim Speichern deiner E-Mail-Benachrichtigungseinstellungen ist ein Fehler aufgetreten.",
+ "and remove": "und entfernen",
+ "Can't update user notification settings": "Benachrichtigungs-Einstellungen des Nutzers konnten nicht aktualisiert werden",
+ "Couldn't find a matching Matrix room": "Konnte keinen entsprechenden Matrix-Raum finden",
+ "delete the alias.": "Lösche den Alias.",
+ "Delete the room alias": "Lösche den Raum Alias",
+ "Direct Chat": "Privater Chat",
+ "Drop here to": "Hier ablegen",
+ "Enable audible notifications in web client": "Audio-Benachrichtigungen im Web-Client aktivieren",
+ "Enable desktop notifications": "Desktop-Benachrichtigungen aktivieren",
+ "Enable email notifications": "E-Mail-Benachrichtigungen aktivieren",
+ "Enable notifications for this account": "Benachrichtigungen für dieses Konto aktivieren",
+ "Enter keywords separated by a comma:": "Schlüsselwörter kommagetrennt eingeben:",
+ "Error": "Fehler",
+ "Error saving email notification preferences": "Fehler beim Speichern der E-Mail-Benachrichtigungseinstellungen",
+ "#example": "#Beispiel",
+ "Failed to": "Konnte nicht",
+ "Failed to add tag ": "Konnte Tag nicht hinzufügen ",
+ "Failed to change settings": "Einstellungen konnten nicht geändert werden",
+ "Failed to update keywords": "Schlüsselwörter konnten nicht aktualisiert werden",
+ "Failed to get public room list": "Die Liste der öffentlichen Räume konnte nicht geladen werden",
+ "Failed to join the room": "Fehler beim Betreten des Raumes",
+ "Failed to remove tag ": "Konnte Tag nicht entfernen ",
+ "Failed to set Direct Message status of room": "Konnte den direkten Benachrichtigungsstatus nicht setzen",
+ "Favourite": "Favorit",
+ "Fetching third party location failed": "Das Abrufen des Drittanbieterstandorts ist fehlgeschlagen",
+ "Forget": "Entfernen",
+ "from the directory": "aus dem Verzeichnis",
+ " from room": " aus dem Raum",
+ "Keywords": "Schlüsselwörter",
+ "Leave": "Verlassen",
+ "Low Priority": "Niedrige Priorität",
+ "Noisy": "Laut",
+ "Notification targets": "Benachrichtigungsziele",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Die Benachrichtigungen zu den folgenden Schlüsselwörtern folgen Regeln, die hier nicht angezeigt werden können:",
+ "Notify for all other messages/rooms": "Benachrichtigungen für alle anderen Mitteilungen/Räume aktivieren",
+ "Operation failed": "Aktion fehlgeschlagen",
+ "Reject": "ablehnen",
+ "Remove": "Entfernen",
+ "remove": "Entferner",
+ "Remove from Directory": "Aus dem Raum-Verzeichnis entfernen",
+ "Riot does not know how to join a room on this network": "Riot weiß nicht, wie es einem Raum auf diesem Netzwerk beitreten soll",
+ "Room not found": "Raum nicht gefunden",
+ "There are advanced notifications which are not shown here": "Es existieren erweiterte Benachrichtigungen, welche hier nicht angezeigt werden",
+ "The server may be unavailable or overloaded": "Der Server ist vermutlich nicht erreichbar oder überlastet",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Dieser Raum ist nicht verfügbar für Gäste. Vermutlich klappt es wenn du dich anmeldest.",
+ "Unable to fetch notification target list": "Liste der Benachrichtigungsempfänger konnte nicht abgerufen werden",
+ "Unable to join network": "Es ist nicht möglich, dem Netzwerk beizutreten",
+ "unknown error code": "Unbekannter Fehlercode",
+ "Unnamed room": "Unbenannter Raum",
+ "Notify me for anything else": "Über alles andere benachrichtigen",
+ "Off": "Aus",
+ "On": "An",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Du hast sie eventuell auf einem anderen Client als Riot konfiguriert. Sie können in Riot nicht verändert werden, gelten aber trotzdem",
+ " to room": " an Raum",
+ "Drop here %(toAction)s": "Hierher ziehen: %(toAction)s",
+ "All messages": "Alle Nachrichten",
+ "All messages (loud)": "Alle Nachrichten (laut)",
+ "Cancel Sending": "Senden abbrechen",
+ "Close": "Schließen",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Soll der Raum-Alias %(alias)s gelöscht und der %(name)s aus dem Verzeichnis entfernt werden?",
+ "Download this file": "Datei herunterladen",
+ "Failed to add tag %(tagName)s to room": "Das Hinzufügen des Tags %(tagName)s für den Raum ist fehlgeschlagen",
+ "Failed to forget room %(errCode)s": "Das Entfernen des Raums ist fehlgeschlagen %(errCode)s",
+ "Failed to remove tag %(tagName)s from room": "Das Entfernen des Tags %(tagName)s für den Raum ist fehlgeschlagen",
+ "Failed to set direct chat tag": "Fehler beim Setzen der \"Direkter Chat\"-Kennzeichnung",
+ "Mentions only": "Nur, wenn du erwähnt wirst",
+ "Mute": "Stummschalten",
+ "Permalink": "Permanenter Link",
+ "Quote": "Zitat",
+ "Redact": "Löschen",
+ "Remove %(name)s from the directory?": "Soll der Raum %(name)s aus dem Verzeichnis entfernt werden?",
+ "remove %(name)s from the directory.": "entferne %(name)s aus dem Verzeichnis.",
+ "Resend": "Erneut senden",
+ "Source URL": "Quell-URL",
+ "Unable to look up room ID from server": "Es ist nicht möglich, die Raum-ID auf dem Server nachzuschlagen",
+ "Unhide Preview": "Vorschau wieder anzeigen",
+ "Uploaded on %(date)s by %(user)s": "Hochgeladen am %(date)s von %(user)s",
+ "View Decrypted Source": "Entschlüsselten Quellcode ansehen",
+ "View Source": "Quellcode ansehen",
+ "You cannot delete this image. (%(code)s)": "Das Bild kann nicht gelöscht werden. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Diese Nachricht kann nicht gelöscht werden. (%(code)s)",
+ "Today": "Heute",
+ "Wednesday": "Mittwoch",
+ "Thursday": "Donnerstag",
+ "Friday": "Freitag",
+ "Saturday": "Samstag",
+ "Tuesday": "Dienstag",
+ "Sunday": "Sonntag",
+ "Monday": "Montag",
+ "Yesterday": "Gestern",
+ "Welcome page": "Willkommensseite",
+ "Advanced notification settings": "Erweiterte Benachrichtigungs-Einstellungen",
+ "Call invitation": "Anruf-Einladung",
+ "Messages containing my display name": "Nachrichten, die meinen Anzeigenamen enthalten",
+ "Messages containing my user name": "Nachrichten, die meinen Benutzernamen enthalten",
+ "Messages in group chats": "Nachrichten in Gruppen-Chats",
+ "Messages in one-to-one chats": "Nachrichten in Einzel-Chats",
+ "Messages sent by bot": "Nachrichten von Bots",
+ "more": "mehr",
+ "When I'm invited to a room": "Wenn ich in einen Raum eingeladen werde",
+ "customServer_text": "Du kannst die erweiterten Server-Optionen nutzen, um dich auf anderen Matrix-Servern anzumelden, indem du eine andere Heimserver-URL eingibst. Dies ermöglicht es dir, Riot mit einem bereits existierenden Matrix-Konto auf einem anderen Heimserver zu nutzen.
Du kannst auch einen benutzerdefinierten Identitäts-Server eingeben, allerdings wirst du dann nicht in der Lage sein, andere Benutzer per E-Mail-Adresse einzuladen oder selbst Einladungen per E-Mail-Adresse zu erhalten.",
+ "Safari and Opera work too.": "Safari und Opera funktionieren ebenfalls.",
+ "I understand the risks and wish to continue": "Ich verstehe das Risiko und möchte fortfahren",
+ "Messages containing keywords": "Nachrichten, die definierte Schlüsselwörter enthalten",
+ "Please install Chrome or Firefox for the best experience.": "Bitte installiere Chrome oder Firefox für die beste Erfahrung.",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot nutzt zahlreiche fortgeschrittene Browser-Funktionen, die teilweise in deinem aktuell verwendeten Browser noch nicht verfügbar sind oder sich noch im experimentellen Status befinden.",
+ "Sorry, your browser is not able to run Riot.": "Es tut uns leid, aber dein Browser kann Riot nicht ausführen.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "In deinem aktuellen Browser kann das Aussehen und Gefühl der Anwendung komplett inkorrekt sein und einige oder alle Funktionen funktionieren evtl. nicht. Du kannst es trotzdem versuchen und fortfahren, aber du bist alleine mit allen Problemen auf die du stößt!",
+ "Expand panel": "Panel ausklappen",
+ "Collapse panel": "Panel einklappen",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s auf %(osName)s",
+ "A new version of Riot is available.": "Eine neue Version von Riot ist verfügbar.",
+ "All Rooms": "Alle Räume",
+ "Cancel": "Abbrechen",
+ "Changelog": "Änderungshistorie",
+ "Collecting app version information": "App-Versionsinformationen werden abgerufen",
+ "Collecting logs": "Protokolle werden abgerufen",
+ "Describe your problem here.": "Beschreibe dein Problem hier.",
+ "Failed to send report: ": "Senden des Reports fehlgeschlagen: ",
+ "Forward Message": "Nachricht weiterleiten",
+ "Hide panel": "Verberge Feld",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Um Probleme zu diagnostizieren werden mit diesem Fehlerbericht Protokolle von diesem Client gesendet. Wenn du nur obigen text senden willst, deselektiere folgendes:",
+ "Loading bug report module": "Lade Fehlerbericht-Modul",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Bitte beschreibe (vorzugsweise auf Englisch) den Fehler. Was tatst du? Was wolltest du, dass es passiert? Was ist passiert?",
+ "Please describe the bug and/or send logs.": "Bitte beschreibe den Fehler und/oder sende Protokolle.",
+ "Report a bug": "Einen Fehler melden",
+ "Riot Desktop on %(platformName)s": "Riot Desktop auf %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot wird im mobilen Web nicht unterstützt. App installieren?",
+ "Search": "Suchen",
+ "Search…": "Suchen…",
+ "Send": "Sende",
+ "Send logs": "Sende Protokolle",
+ "This Room": "Dieser Raum",
+ "Unavailable": "Nicht verfügbar",
+ "Unknown device": "Unbekanntes Gerät",
+ "Update": "Aktualisiere",
+ "Uploading report": "Lade Bericht hoch",
+ "What's New": "Was ist neu",
+ "What's new?": "Was ist neu?",
+ "Waiting for response from server": "Auf Antwort vom Server warten",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Du verwendest Riot als Gast. Registriere oder melde dich an um Zugang zu mehr Räumen und Funktionen zu bekommen!",
+ "You need to be using HTTPS to place a screen-sharing call.": "Du musst HTTPS nutzen um einen Anruf mit Bildschirmfreigabe durchzuführen.",
+ "OK": "OK",
+ "Login": "Anmeldung",
+ "Welcome to Riot.im": "Willkommen bei Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Dezentralisierter, verschlüsselter Chat & Zusammenarbeit unterstützt von [matrix]",
+ "Search the room directory": "Raum-Verzeichnis durchsuchen",
+ "Chat with Riot Bot": "Chatte mit dem Riot-Bot",
+ "Get started with some tips from Riot Bot!": "Beginne mit einigen Tipps vom Riot-Bot!",
+ "General discussion about Matrix": "Allgemeine Diskussion über Matrix",
+ "Discussion of all things Matrix!": "\"Diskussion über alle Dinge\"-Matrix!",
+ "Riot/Web & Desktop chat": "Riot-Web & Desktop-Chat",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot-iOS & \"matrix-ios-sdk\"-Chat",
+ "Riot/Android & matrix-android-sdk chat": "Riot-Android & matrix-android-sdk-Chat",
+ "Matrix technical discussions": "Technische Diskussion über Matrix",
+ "Running Matrix services": "Matrix-Dienste betreiben",
+ "Community-run support for Synapse": "Synapse-Support von der Community",
+ "Admin support for Dendrite": "Admin-Unterstützung für Dendrite",
+ "Announcements about Synapse releases": "Ankündigungen über Synapse-Versionen",
+ "Support for those using and running matrix-appservice-irc": "Unterstützung für die, die \"matrix-appservice-irc\" betreiben und nutzen",
+ "Building services on Matrix": "Dienste bauen für Matrix",
+ "Support for those using the Matrix spec": "Unterstützung für die Nutzer der Matrix-Spezification",
+ "Design and implementation of E2E in Matrix": "Design und Implementierung von Ende-zu-Ende-Verschlüsselung in Matrix",
+ "Implementing VR services with Matrix": "Implementierung von VR-Diensten mit Matrix",
+ "Implementing VoIP services with Matrix": "Implementierung von VoIP-Diensten mit Matrix",
+ "Discussion of the Identity Service API": "Diskussion der Identitätsdienst-API",
+ "Support for those using, running and writing other bridges": "Unterstützung für die, die andere Brücken nutzen, betreiben oder schreiben",
+ "Contributing code to Matrix and Riot": "Code zu Matrix und Riot beitragen",
+ "Dev chat for the Riot/Web dev team": "Entwickler-Chat für das Riot-Web-Entwickler-Team",
+ "Co-ordination for Riot/Web translators": "Koordination für Riot/Web-Übersetzer",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Im Matrix-Netzwerk gibt es bereits jetzt zahlreiche Räume, die entweder mit bekannten Netzwerken wie Slack, IRC, Gitter, usw. verknüpft sind oder auch komplett eigenständig betrieben werden. Einen genauen Überblick erhältst du im Raum-Verzeichnis!",
+ "Failed to change password. Is your password correct?": "Passwortänderung fehlgeschlagen. Ist dein Passwort richtig?",
+ "You have successfully set a password!": "Du hast erfolgreich ein Passwort gesetzt!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Du kannst nun zu deinem Konto zurückkehren nach dem du dich an anderen Geräten ab- und angemeldet hast.",
+ "Continue": "Fortfahren",
+ "Please set a password!": "Bitte ein Passwort einrichten!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Dies erlaubt dir, dich wieder an deinem Konto anzumelden, nachdem du dich abgemeldet hast.",
+ "Dev chat for the Dendrite dev team": "Entwickler-Chat für das Dendrite-Entwickler-Team",
+ "General discussion about Matrix and Riot": "Allgemeine Diskussion über Matrix und Riot",
+ "(HTTP status %(httpStatus)s)": "(HTTP-Status %(httpStatus)s)",
+ "You have successfully set a password and an email address!": "Du hast erfolgreich ein Passwort und eine E-Mail-Adresse gesetzt!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Denk daran, dass du in den Benutzereinstellungen jederzeit eine E-Mail-Adresse setzen kannst."
+}
diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json
new file mode 100644
index 00000000..c9f9373a
--- /dev/null
+++ b/src/i18n/strings/el.json
@@ -0,0 +1,202 @@
+{
+ "A new version of Riot is available.": "Μία νέα έκδοση του Riot είναι διαθέσιμη.",
+ "Advanced notification settings": "Προχωρημένες ρυθμίσεις ειδοποιήσεων",
+ "All messages": "Όλα τα μηνύματα",
+ "All Rooms": "Όλα τα δωμάτια",
+ "All notifications are currently disabled for all targets.": "Όλες οι ειδοποιήσεις είναι προς το παρόν απενεργοποιημένες για όλες τις συσκευές.",
+ "An error occurred whilst saving your email notification preferences.": "Ένα σφάλμα προέκυψε κατά την αποθήκευση των ρυθμίσεων σας.",
+ "Call invitation": "Πρόσκληση σε κλήση",
+ "Cancel": "Ακύρωση",
+ "Cancel Sending": "Ακύρωση αποστολής",
+ "Can't update user notification settings": "Δεν είναι δυνατή η ενημέρωση των ρυθμίσεων ειδοποίησης χρήστη",
+ "Changelog": "Αλλαγές",
+ "Close": "Κλείσιμο",
+ "Collapse panel": "Ελαχιστοποίηση καρτέλας",
+ "Create new room": "Δημιουργία νέου δωματίου",
+ "Custom Server Options": "Προσαρμοσμένες ρυθμίσεις διακομιστή",
+ "Describe your problem here.": "Περιγράψτε το πρόβλημα σας εδώ.",
+ "Direct Chat": "Απευθείας συνομιλία",
+ "Directory": "Ευρετήριο",
+ "Download this file": "Λήψη αρχείου",
+ "Enable audible notifications in web client": "Ενεργοποίηση ηχητικών ειδοποιήσεων",
+ "Enable email notifications": "Ενεργοποίηση ειδοποιήσεων μέσω μηνυμάτων ηλ. αλληλογραφίας",
+ "Enable notifications for this account": "Ενεργοποίηση ειδοποιήσεων για τον λογαριασμό",
+ "Enter keywords separated by a comma:": "Προσθέστε λέξεις κλειδιά χωρισμένες με κόμμα:",
+ "Error": "Σφάλμα",
+ "#example": "#παράδειγμα",
+ "Expand panel": "Μεγιστοποίηση καρτέλας",
+ "Safari and Opera work too.": "Safari και Opera λειτουργούν επίσης.",
+ "Add an email address above to configure email notifications": "Προσθέστε μια διεύθυνση ηλεκτρονικής αλληλογραφίας στο παραπάνω πεδίο, για να έχετε τη δυνατότητα να λαμβάνετε ειδοποιήσεις",
+ "Collecting app version information": "Συγκέντρωση πληροφοριών σχετικά με την έκδοση της εφαρμογής",
+ "customServer_text": "Μπορείτε να χρησιμοποιήσετε τις προσαρμοσμένες ρυθμίσεις για να εισέλθετε σε άλλους διακομιστές Matrix επιλέγοντας μια διαφορετική διεύθυνση για το διακομιστή. Αυτό σας επιτρέπει να χρησιμοποιήσετε την εφαρμογή Riot με έναν υπάρχοντα λογαριασμό σε διαφορετικό διακομιστή.
Επίσης μπορείτε να επιλέξετε ένα διαφορετικό διακομιστή ταυτότητας αλλά δεν θα έχετε τη δυνατότητα να προσκαλέσετε άλλους χρήστες ή να σας προσκαλέσουν μέσω μηνυμάτων ηλεκτρονικής αλληλογραφίας.",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s μέσω %(browserName)s σε %(osName)s",
+ "All messages (loud)": "Όλα τα μηνύματα (δυνατά)",
+ "delete the alias.": "διέγραψε το ψευδώνυμο.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Διαγραφή του ψευδώνυμου %(alias)s και αφαίρεση του %(name)s από το ευρετήριο;",
+ "Dismiss": "Απόρριψη",
+ "Failed to add tag %(tagName)s to room": "Δεν ήταν δυνατή η προσθήκη της ετικέτας %(tagName)s στο δωμάτιο",
+ "Failed to change settings": "Δεν ήταν δυνατή η αλλαγή των ρυθμίσεων",
+ "Failed to join the room": "Δεν ήταν δυνατή η σύνδεση στο δωμάτιο",
+ "Favourite": "Αγαπημένο",
+ "Files": "Αρχεία",
+ "Filter room names": "Φιλτράρισμα δωματίων",
+ "Forward Message": "Προώθηση",
+ " from room": " από το δωμάτιο",
+ "Guests can join": "Επισκέπτες μπορούν να συνδεθούν",
+ "Guest users can't invite users. Please register to invite.": "Οι επισκέπτες δεν έχουν τη δυνατότητα να προσκαλέσουν άλλους χρήστες. Παρακαλούμε εγγραφείτε πρώτα.",
+ "Hide panel": "Απόκρυψη καρτέλας",
+ "I understand the risks and wish to continue": "Κατανοώ του κινδύνους και επιθυμώ να συνεχίσω",
+ "Invite to this room": "Πρόσκληση σε αυτό το δωμάτιο",
+ "Keywords": "Λέξεις κλειδιά",
+ "Leave": "Αποχώρηση",
+ "Low Priority": "Χαμηλή προτεραιότητα",
+ "Members": "Μέλη",
+ "Messages containing keywords": "Μηνύματα που περιέχουν λέξεις κλειδιά",
+ "Messages containing my user name": "Μηνύματα που περιέχουν το ψευδώνυμο μου",
+ "Messages in group chats": "Μηνύματα σε ομαδικές συνομιλίες",
+ "Messages in one-to-one chats": "Μηνύματα σε 1-προς-1 συνομιλίες",
+ "Messages sent by bot": "Μηνύματα από bots",
+ "more": "περισσότερα",
+ "Mute": "Σίγαση",
+ "No rooms to show": "Δεν υπάρχουν δωμάτια για εμφάνιση",
+ "Noisy": "Δυνατά",
+ "Notifications": "Ειδοποιήσεις",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Οι ειδοποιήσεις για τις επόμενες λέξεις κλειδία ακολουθούν κανόνες που δεν είναι δυνατόν να εμφανιστούν εδώ:",
+ "Notify for all other messages/rooms": "Ειδοποίηση για όλα τα υπόλοιπα μηνύματα/δωμάτια",
+ "Notify me for anything else": "Ειδοποίηση για οτιδήποτε άλλο",
+ "Operation failed": "Η λειτουργία απέτυχε",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Παρακαλούμε περιγράψτε το σφάλμα. Τι κάνατε; Τι περιμένατε να συμβεί; Τι έγινε τελικά;",
+ "Please Register": "Παρακαλούμε εγγραφείτε",
+ "Redact": "Ανάκληση",
+ "Reject": "Απόρριψη",
+ "Remove": "Αφαίρεση",
+ "Remove from Directory": "Αφαίρεση από το ευρετήριο",
+ "Resend": "Αποστολή ξανά",
+ "Riot Desktop on %(platformName)s": "Riot Desktop σε %(platformName)s",
+ "Room directory": "Ευρετήριο",
+ "Room not found": "Το δωμάτιο δεν βρέθηκε",
+ "Search": "Αναζήτηση",
+ "Search…": "Αναζήτηση…",
+ "Send": "Αποστολή",
+ "Settings": "Ρυθμίσεις",
+ "Start chat": "Έναρξη συνομιλίας",
+ "This Room": "Στο δωμάτιο",
+ "Unavailable": "Μη διαθέσιμο",
+ "Unknown device": "Άγνωστη συσκευή",
+ "Update": "Ενημέρωση",
+ "Enable desktop notifications": "Ενεργοποίηση ειδοποιήσεων στην επιφάνεια εργασίας",
+ "Error saving email notification preferences": "Σφάλμα κατά την αποθήκευση των προτιμήσεων",
+ "Failed to send report: ": "Δεν ήταν δυνατή η αποστολή της αναφοράς: ",
+ "Loading bug report module": "Φόρτωση μονάδας αναφοράς σφαλμάτων",
+ "Mentions only": "Μόνο αναφορές",
+ "Messages containing my display name": "Μηνύματα που περιέχουν το όνομα μου",
+ "Off": "Ανενεργό",
+ "On": "Ενεργό",
+ "Permalink": "Μόνιμος σύνδεσμος",
+ "Please install Chrome or Firefox for the best experience.": "Παρακαλούμε εγκαταστήστε έναν από τους περιηγητές Chrome ή Firefox για την καλύτερη δυνατή εμπειρία.",
+ "Report a bug": "Αναφορά σφάλματος",
+ "Riot does not know how to join a room on this network": "To Riot δεν γνωρίζει πως να συνδεθεί σε δωμάτια που ανήκουν σ' αυτό το δίκτυο",
+ "Search for a room": "Αναζήτηση δωματίου",
+ "Sorry, your browser is not able to run Riot.": "Λυπούμαστε, αλλά ο περιηγητές σας δεν υποστηρίζεται από το Riot.",
+ "There are advanced notifications which are not shown here": "Υπάρχουν προχωρημένες ειδοποιήσεις οι οποίες δεν εμφανίζονται εδώ",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Το δωμάτιο δεν είναι προσβάσιμο σε επισκέπτες. Πιθανόν να μπορέσετε να συνδεθείτε εάν εγγραφείτε.",
+ "Unable to join network": "Δεν είναι δυνατή η σύνδεση στο δίκτυο",
+ "unknown error code": "άγνωστος κωδικός σφάλματος",
+ "Unnamed room": "Ανώνυμο δωμάτιο",
+ "Uploaded on %(date)s by %(user)s": "Απεστάλη στις %(date)s από %(user)s",
+ "Uploading report": "Αποστολή αναφοράς",
+ "What's New": "Τι νέο υπάρχει",
+ "What's new?": "Τι νέο υπάρχει;",
+ "When I'm invited to a room": "Όταν με προσκαλούν σ' ένα δωμάτιο",
+ "World readable": "Εμφανές σε όλους",
+ "You cannot delete this image. (%(code)s)": "Δεν μπορείτε να διαγράψετε αυτή την εικόνα. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Δεν μπορείτε να διαγράψετε αυτό το μήνυμα. (%(code)s)",
+ "You are not receiving desktop notifications": "Δεν λαμβάνετε ειδοποιήσεις στην επιφάνεια εργασίας",
+ "Sunday": "Κυριακή",
+ "Monday": "Δευτέρα",
+ "Tuesday": "Τρίτη",
+ "Wednesday": "Τετάρτη",
+ "Thursday": "Πέμπτη",
+ "Friday": "Παρασκευή",
+ "Saturday": "Σάββατο",
+ "Today": "Σήμερα",
+ "Yesterday": "Χθές",
+ "OK": "Εντάξει",
+ "You need to be using HTTPS to place a screen-sharing call.": "Απαιτείται η χρήση HTTPS για το διαμοιρασμό της επιφάνειας εργασίας μέσω κλήσης.",
+ "Welcome page": "Αρχική σελίδα",
+ "Forget": "Παράλειψη",
+ "Riot is not supported on mobile web. Install the app?": "Το Riot δεν υποστηρίζεται από περιηγητές κινητών. Θέλετε να εγκαταστήσετε την εφαρμογή;",
+ "Unhide Preview": "Προεπισκόπηση",
+ "Waiting for response from server": "Αναμονή απάντησης από τον διακομιστή",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Χρησιμοποιείτε το Riot ως επισκέπτης. Εγγραφείτε ή συνδεθείτε για να αποκτήσετε πρόσβαση σε περισσότερα δωμάτια και χαρακτηριστικά!",
+ "Collecting logs": "Συγκέντρωση πληροφοριών",
+ "Enable them now": "Ενεργοποίηση",
+ "Failed to forget room %(errCode)s": "Δεν ήταν δυνατή η διαγραφή του δωματίου (%(errCode)s)",
+ "Failed to update keywords": "Οι λέξεις κλειδιά δεν ενημερώθηκαν",
+ "Failed to get protocol list from Home Server": "Δεν ήταν δυνατή η εύρεση των διαθέσιμων πρωτοκόλλων από το διακομιστή",
+ "Failed to remove tag %(tagName)s from room": "Δεν ήταν δυνατή η διαγραφή της ετικέτας %(tagName)s από το δωμάτιο",
+ "Notification targets": "Στόχοι ειδοποιήσεων",
+ "Please describe the bug and/or send logs.": "Παρακαλούμε περιγράψτε το σφάλμα και/ή στείλτε πληροφορίες σχετικά με την εφαρμογή.",
+ "Remove %(name)s from the directory?": "Αφαίρεση του %(name)s από το ευρετήριο;",
+ "remove %(name)s from the directory.": "αφαίρεση του %(name)s από το ευρετήριο.",
+ "Send logs": "Αποστολή πληροφοριών",
+ "Source URL": "Πηγαίο URL",
+ "The server may be unavailable or overloaded": "Ο διακομιστής είναι μη διαθέσιμος ή υπερφορτωμένος",
+ " to room": " στο δωμάτιο",
+ "Unable to fetch notification target list": "Δεν ήταν δυνατή η εύρεση στόχων για τις ειδοποιήσεις",
+ "Unable to look up room ID from server": "Δεν είναι δυνατή η εύρεση του ID για το δωμάτιο",
+ "View Decrypted Source": "Προβολή του αποκρυπτογραφημένου κώδικα",
+ "View Source": "Προβολή κώδικα",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Ισως να έχετε κάνει τις ρυθμίσεις σε άλλη εφαρμογή εκτός του Riot. Δεν μπορείτε να τις αλλάξετε μέσω του Riot αλλά ισχύουν κανονικά",
+ "Couldn't find a matching Matrix room": "Δεν βρέθηκε κάποιο δωμάτιο",
+ "Drop here %(toAction)s": "Αποθέστε εδώ %(toAction)s",
+ "Failed to": "Απέτυχε να",
+ "Failed to get public room list": "Δεν ήταν δυνατή η λήψη της λίστας με τα δημόσια δωμάτια",
+ "Failed to set direct chat tag": "Δεν ήταν δυνατός ο χαρακτηρισμός της συνομιλίας ως 1-προς-1",
+ "powered by Matrix": "βασισμένο στο πρωτόκολλο Matrix",
+ "Quote": "Παράθεση",
+ "Fetching third party location failed": "Η λήψη τοποθεσίας απέτυχε",
+ "(HTTP status %(httpStatus)s)": "(Κατάσταση HTTP %(httpStatus)s)",
+ "Login": "Σύνδεση",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Το Riot χρησιμοποιεί αρκετά προχωρημένα χαρακτηριστικά των περιηγητών Ιστού, ορισμένα από τα οποία δεν είναι διαθέσιμα ή είναι σε πειραματικό στάδιο στον περιηγητή σας.",
+ "The Home Server may be too old to support third party networks": "Ο διακομιστής μπορεί να είναι αρκετά παλιός για να υποστηρίζει δίκτυα τρίτων",
+ "Welcome to Riot.im": "Καλώς ήλθατε στο Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Αποκεντρωμένη, κρυπτογραφημένη συνομιλία & συνεργασία με τη βοήθεια του [matrix]",
+ "Search the room directory": "Αναζήτηση του ευρετηρίου δωματίων",
+ "Chat with Riot Bot": "Συνομιλία με το Riot Bot",
+ "Get started with some tips from Riot Bot!": "Ξεκινήστε με μερικές συμβουλές από το Riot Bot!",
+ "General discussion about Matrix and Riot": "Γενική συζήτηση σχετικά με Matrix και Riot",
+ "Discussion of all things Matrix!": "Συζήτηση για όλα τα πράγματα του Matrix!",
+ "Riot/Web & Desktop chat": "Συζήτηση για το Riot/Web & Desktop",
+ "Riot/iOS & matrix-ios-sdk chat": "Συζήτηση για το Riot/iOS & matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Συζήτηση για το Riot/Android & matrix-android-sdk",
+ "Matrix technical discussions": "Τεχνικές συζητήσεις σχετικά με το Matrix",
+ "Running Matrix services": "Χρησιμοποιώντας τις υπηρεσίες του Matrix",
+ "Community-run support for Synapse": "Κοινοτική υποστήριξη για το Synapse",
+ "Admin support for Dendrite": "Υποστήριξη διαχειριστή για το Dendrite",
+ "Announcements about Synapse releases": "Ανακοινώσεις σχετικά με τις εκδόσεις του Synapse",
+ "Support for those using and running matrix-appservice-irc": "Υποστήριξη για τους χρήστες που χρησιμοποιούν το matrix-appservice-irc",
+ "Building services on Matrix": "Ανάπτυξη υπηρεσιών στο Matrix",
+ "Support for those using the Matrix spec": "Υποστήριξη για τους χρήστες που χρησιμοποιούν το Matrix spec",
+ "Design and implementation of E2E in Matrix": "Σχεδιασμός και υλοποίηση του E2E στο Matrix",
+ "Implementing VR services with Matrix": "Υλοποίηση υπηρεσίων VR με το Matrix",
+ "Implementing VoIP services with Matrix": "Υλοποίηση υπηρεσίων VoIP με το Matrix",
+ "Discussion of the Identity Service API": "Συζήτηση σχετικά με το Identity Service API",
+ "Contributing code to Matrix and Riot": "Συνεισφορά κώδικα στο Matrix και Riot",
+ "Dev chat for the Riot/Web dev team": "Συζήτηση με την ομάδα ανάπτυξης του Riot/Web",
+ "Dev chat for the Dendrite dev team": "Συζήτηση με την ομάδα ανάπτυξης του Dendrite",
+ "Co-ordination for Riot/Web translators": "Συντονισμός για μεταφραστές του Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Αρκετά δωμάτια υπάρχουν ήδη στο Matrix, συνδεδεμένα σε υπάρχοντα δίκτυα (Slack, IRC, Gitter κ.λπ) ή αυτόνομα. Ρίξτε μια ματιά στο ευρετήριο!",
+ "Failed to change password. Is your password correct?": "Δεν ήταν δυνατή η αλλαγή του κωδικού πρόσβασης. Είναι σωστός ο κωδικός πρόσβασης;",
+ "You have successfully set a password!": "Ο κωδικός πρόσβασης ορίστηκε επιτυχώς!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Μπορείτε να επιστρέψετε στον λογαριασμό σας αφού αποσυνδεθείτε και συνδεθείτε από άλλες συσκευές.",
+ "Continue": "Συνέχεια",
+ "Please set a password!": "Παρακαλούμε ορίστε έναν κωδικό πρόσβασης!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Αυτό θα σας επιτρέψει να επιστρέψετε στον λογαριασμό σας αφού αποσυνδεθείτε και συνδεθείτε από άλλες συσκευές.",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Προκειμένου να διαγνωστούν προβλήματα, τα αρχεία καταγραφής από αυτόν τον πελάτη θα σταλούν με αυτήν την αναφορά σφάλματος. Αν προτιμάτε να στείλετε μόνο το παραπάνω κείμενο, απενεργοποιήστε:",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Με τον τρέχον περιηγητή, η εμφάνιση και η αίσθηση της εφαρμογής ενδέχεται να είναι εντελώς εσφαλμένη και ορισμένες ή όλες οι λειτουργίες ενδέχεται να μην λειτουργούν. Εάν θέλετε να το δοκιμάσετε ούτως ή άλλως μπορείτε να συνεχίσετε, αλλά είστε μόνοι σας σε ό, τι αφορά τα προβλήματα που μπορεί να αντιμετωπίσετε!",
+ "Failed to set Direct Message status of room": "Δεν ήταν δυνατός ο ορισμός της κατάστασης Direct Message του δωματίου",
+ "Support for those using, running and writing other bridges": "Υποστήριξη για τους χρήστες που χρησιμοποιούν ή αναπτύσσουν εφαρμογές ενσωμάτωσης για το Matrix",
+ "You have successfully set a password and an email address!": "Ο κωδικός πρόσβασης και η διεύθυνση ηλεκτρονικής αλληλογραφίας ορίστηκαν επιτυχώς!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Να θυμάστε ότι μπορείτε πάντα να ορίσετε μια διεύθυνση ηλεκτρονικής αλληλογραφίας στις ρυθμίσεις χρήστη αν αλλάξετε γνώμη."
+}
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
new file mode 100644
index 00000000..4717e267
--- /dev/null
+++ b/src/i18n/strings/en_EN.json
@@ -0,0 +1,202 @@
+{
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s on %(osName)s",
+ "Safari and Opera work too.": "Safari and Opera work too.",
+ "A new version of Riot is available.": "A new version of Riot is available.",
+ "Add an email address above to configure email notifications": "Add an email address above to configure email notifications",
+ "Advanced notification settings": "Advanced notification settings",
+ "All messages": "All messages",
+ "All messages (loud)": "All messages (loud)",
+ "All Rooms": "All Rooms",
+ "All notifications are currently disabled for all targets.": "All notifications are currently disabled for all targets.",
+ "An error occurred whilst saving your email notification preferences.": "An error occurred whilst saving your email notification preferences.",
+ "Call invitation": "Call invitation",
+ "Cancel": "Cancel",
+ "Cancel Sending": "Cancel Sending",
+ "Can't update user notification settings": "Can't update user notification settings",
+ "Changelog": "Changelog",
+ "Close": "Close",
+ "Collapse panel": "Collapse panel",
+ "Collecting app version information": "Collecting app version information",
+ "Collecting logs": "Collecting logs",
+ "Create new room": "Create new room",
+ "Couldn't find a matching Matrix room": "Couldn't find a matching Matrix room",
+ "Custom Server Options": "Custom Server Options",
+ "customServer_text": "You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL. This allows you to use Riot with an existing Matrix account on a different home server.
You can also set a custom identity server but you won't be able to invite users by email address, or be invited by email address yourself.",
+ "delete the alias.": "delete the alias.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Delete the room alias %(alias)s and remove %(name)s from the directory?",
+ "Describe your problem here.": "Describe your problem here.",
+ "Direct Chat": "Direct Chat",
+ "Directory": "Directory",
+ "Dismiss": "Dismiss",
+ "Download this file": "Download this file",
+ "Drop here %(toAction)s": "Drop here %(toAction)s",
+ "Enable audible notifications in web client": "Enable audible notifications in web client",
+ "Enable desktop notifications": "Enable desktop notifications",
+ "Enable email notifications": "Enable email notifications",
+ "Enable notifications for this account": "Enable notifications for this account",
+ "Enable them now": "Enable them now",
+ "Enter keywords separated by a comma:": "Enter keywords separated by a comma:",
+ "Error": "Error",
+ "Error saving email notification preferences": "Error saving email notification preferences",
+ "#example": "#example",
+ "Expand panel": "Expand panel",
+ "Failed to": "Failed to",
+ "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room",
+ "Failed to change settings": "Failed to change settings",
+ "Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s",
+ "Failed to update keywords": "Failed to update keywords",
+ "Failed to get protocol list from Home Server": "Failed to get protocol list from Home Server",
+ "Failed to get public room list": "Failed to get public room list",
+ "Failed to join the room": "Failed to join the room",
+ "Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
+ "Failed to send report: ": "Failed to send report: ",
+ "Failed to set direct chat tag": "Failed to set direct chat tag",
+ "Failed to set Direct Message status of room": "Failed to set Direct Message status of room",
+ "Favourite": "Favourite",
+ "Fetching third party location failed": "Fetching third party location failed",
+ "Files": "Files",
+ "Filter room names": "Filter room names",
+ "Forget": "Forget",
+ "Forward Message": "Forward Message",
+ " from room": " from room",
+ "Guests can join": "Guests can join",
+ "Guest users can't invite users. Please register to invite.": "Guest users can't invite users. Please register to invite.",
+ "Hide panel": "Hide panel",
+ "(HTTP status %(httpStatus)s)": "(HTTP status %(httpStatus)s)",
+ "I understand the risks and wish to continue": "I understand the risks and wish to continue",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:",
+ "Invite to this room": "Invite to this room",
+ "Keywords": "Keywords",
+ "Leave": "Leave",
+ "Login": "Login",
+ "Loading bug report module": "Loading bug report module",
+ "Low Priority": "Low Priority",
+ "Members": "Members",
+ "Mentions only": "Mentions only",
+ "Messages containing my display name": "Messages containing my display name",
+ "Messages containing keywords": "Messages containing keywords",
+ "Messages containing my user name": "Messages containing my user name",
+ "Messages in group chats": "Messages in group chats",
+ "Messages in one-to-one chats": "Messages in one-to-one chats",
+ "Messages sent by bot": "Messages sent by bot",
+ "more": "more",
+ "Mute": "Mute",
+ "No rooms to show": "No rooms to show",
+ "Noisy": "Noisy",
+ "Notification targets": "Notification targets",
+ "Notifications": "Notifications",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Notifications on the following keywords follow rules which can’t be displayed here:",
+ "Notify for all other messages/rooms": "Notify for all other messages/rooms",
+ "Notify me for anything else": "Notify me for anything else",
+ "Off": "Off",
+ "On": "On",
+ "Operation failed": "Operation failed",
+ "Permalink": "Permalink",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Please describe the bug. What did you do? What did you expect to happen? What actually happened?",
+ "Please describe the bug and/or send logs.": "Please describe the bug and/or send logs.",
+ "Please install Chrome or Firefox for the best experience.": "Please install Chrome or Firefox for the best experience.",
+ "Please Register": "Please Register",
+ "powered by Matrix": "powered by Matrix",
+ "Quote": "Quote",
+ "Redact": "Redact",
+ "Reject": "Reject",
+ "Remove %(name)s from the directory?": "Remove %(name)s from the directory?",
+ "Remove": "Remove",
+ "remove %(name)s from the directory.": "remove %(name)s from the directory.",
+ "Remove from Directory": "Remove from Directory",
+ "Report a bug": "Report a bug",
+ "Resend": "Resend",
+ "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s",
+ "Riot does not know how to join a room on this network": "Riot does not know how to join a room on this network",
+ "Riot is not supported on mobile web. Install the app?": "Riot is not supported on mobile web. Install the app?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.",
+ "Room directory": "Room directory",
+ "Room not found": "Room not found",
+ "Search": "Search",
+ "Search…": "Search…",
+ "Search for a room": "Search for a room",
+ "Send": "Send",
+ "Send logs": "Send logs",
+ "Settings": "Settings",
+ "Source URL": "Source URL",
+ "Sorry, your browser is not able to run Riot.": "Sorry, your browser is not able to run Riot.",
+ "Start chat": "Start chat",
+ "The Home Server may be too old to support third party networks": "The Home Server may be too old to support third party networks",
+ "There are advanced notifications which are not shown here": "There are advanced notifications which are not shown here",
+ "The server may be unavailable or overloaded": "The server may be unavailable or overloaded",
+ "This Room": "This Room",
+ "This room is inaccessible to guests. You may be able to join if you register.": "This room is inaccessible to guests. You may be able to join if you register.",
+ " to room": " to room",
+ "Unable to fetch notification target list": "Unable to fetch notification target list",
+ "Unable to join network": "Unable to join network",
+ "Unable to look up room ID from server": "Unable to look up room ID from server",
+ "Unavailable": "Unavailable",
+ "Unhide Preview": "Unhide Preview",
+ "Unknown device": "Unknown device",
+ "unknown error code": "unknown error code",
+ "Unnamed room": "Unnamed room",
+ "Update": "Update",
+ "Uploaded on %(date)s by %(user)s": "Uploaded on %(date)s by %(user)s",
+ "Uploading report": "Uploading report",
+ "View Decrypted Source": "View Decrypted Source",
+ "View Source": "View Source",
+ "What's New": "What's New",
+ "What's new?": "What's new?",
+ "Waiting for response from server": "Waiting for response from server",
+ "When I'm invited to a room": "When I'm invited to a room",
+ "World readable": "World readable",
+ "You cannot delete this image. (%(code)s)": "You cannot delete this image. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
+ "You are not receiving desktop notifications": "You are not receiving desktop notifications",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "You are Rioting as a guest. Register or sign in to access more rooms and features!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply",
+ "Sunday": "Sunday",
+ "Monday": "Monday",
+ "Tuesday": "Tuesday",
+ "Wednesday": "Wednesday",
+ "Thursday": "Thursday",
+ "Friday": "Friday",
+ "Saturday": "Saturday",
+ "Today": "Today",
+ "Yesterday": "Yesterday",
+ "OK": "OK",
+ "You need to be using HTTPS to place a screen-sharing call.": "You need to be using HTTPS to place a screen-sharing call.",
+ "Welcome page": "Welcome page",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
+ "Welcome to Riot.im": "Welcome to Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralised, encrypted chat & collaboration powered by [matrix]",
+ "Search the room directory": "Search the room directory",
+ "Chat with Riot Bot": "Chat with Riot Bot",
+ "Get started with some tips from Riot Bot!": "Get started with some tips from Riot Bot!",
+ "General discussion about Matrix and Riot": "General discussion about Matrix and Riot",
+ "Discussion of all things Matrix!": "Discussion of all things Matrix!",
+ "Riot/Web & Desktop chat": "Riot/Web & Desktop chat",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/iOS & matrix-ios-sdk chat",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Android & matrix-android-sdk chat",
+ "Matrix technical discussions": "Matrix technical discussions",
+ "Running Matrix services": "Running Matrix services",
+ "Community-run support for Synapse": "Community-run support for Synapse",
+ "Admin support for Dendrite": "Admin support for Dendrite",
+ "Announcements about Synapse releases": "Announcements about Synapse releases",
+ "Support for those using and running matrix-appservice-irc": "Support for those using and running matrix-appservice-irc",
+ "Building services on Matrix": "Building services on Matrix",
+ "Support for those using the Matrix spec": "Support for those using the Matrix spec",
+ "Design and implementation of E2E in Matrix": "Design and implementation of E2E in Matrix",
+ "Implementing VR services with Matrix": "Implementing VR services with Matrix",
+ "Implementing VoIP services with Matrix": "Implementing VoIP services with Matrix",
+ "Discussion of the Identity Service API": "Discussion of the Identity Service API",
+ "Support for those using, running and writing other bridges": "Support for those using, running and writing other bridges",
+ "Contributing code to Matrix and Riot": "Contributing code to Matrix and Riot",
+ "Dev chat for the Riot/Web dev team": "Dev chat for the Riot/Web dev team",
+ "Dev chat for the Dendrite dev team": "Dev chat for the Dendrite dev team",
+ "Co-ordination for Riot/Web translators": "Co-ordination for Riot/Web translators",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!",
+ "Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
+ "You have successfully set a password!": "You have successfully set a password!",
+ "You can now return to your account after signing out, and sign in on other devices.": "You can now return to your account after signing out, and sign in on other devices.",
+ "Continue": "Continue",
+ "Please set a password!": "Please set a password!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "This will allow you to return to your account after signing out, and sign in on other devices.",
+ "You have successfully set a password and an email address!": "You have successfully set a password and an email address!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Remember, you can always set an email address in user settings if you change your mind."
+}
diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json
new file mode 100644
index 00000000..2d7a5fa1
--- /dev/null
+++ b/src/i18n/strings/en_US.json
@@ -0,0 +1,202 @@
+{
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s on %(osName)s",
+ "Safari and Opera work too.": "Safari and Opera work too.",
+ "A new version of Riot is available.": "A new version of Riot is available.",
+ "Add an email address above to configure email notifications": "Add an email address above to configure email notifications",
+ "Advanced notification settings": "Advanced notification settings",
+ "All messages": "All messages",
+ "All messages (loud)": "All messages (loud)",
+ "All Rooms": "All Rooms",
+ "All notifications are currently disabled for all targets.": "All notifications are currently disabled for all targets.",
+ "An error occurred whilst saving your email notification preferences.": "An error occurred while saving your email notification preferences.",
+ "Call invitation": "Call invitation",
+ "Cancel": "Cancel",
+ "Cancel Sending": "Cancel Sending",
+ "Can't update user notification settings": "Can't update user notification settings",
+ "Changelog": "Changelog",
+ "Close": "Close",
+ "Collapse panel": "Collapse panel",
+ "Collecting app version information": "Collecting app version information",
+ "Collecting logs": "Collecting logs",
+ "Create new room": "Create new room",
+ "Couldn't find a matching Matrix room": "Couldn't find a matching Matrix room",
+ "Custom Server Options": "Custom Server Options",
+ "customServer_text": "You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL. This allows you to use Riot with an existing Matrix account on a different home server.
You can also set a custom identity server but you won't be able to invite users by email address, or be invited by email address yourself.",
+ "delete the alias.": "delete the alias.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Delete the room alias %(alias)s and remove %(name)s from the directory?",
+ "Describe your problem here.": "Describe your problem here.",
+ "Direct Chat": "Direct Chat",
+ "Directory": "Directory",
+ "Dismiss": "Dismiss",
+ "Download this file": "Download this file",
+ "Drop here %(toAction)s": "Drop here %(toAction)s",
+ "Enable audible notifications in web client": "Enable audible notifications in web client",
+ "Enable desktop notifications": "Enable desktop notifications",
+ "Enable email notifications": "Enable email notifications",
+ "Enable notifications for this account": "Enable notifications for this account",
+ "Enable them now": "Enable them now",
+ "Enter keywords separated by a comma:": "Enter keywords separated by a comma:",
+ "Error": "Error",
+ "Error saving email notification preferences": "Error saving email notification preferences",
+ "#example": "#example",
+ "Expand panel": "Expand panel",
+ "Failed to": "Failed to",
+ "Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room",
+ "Failed to change settings": "Failed to change settings",
+ "Failed to forget room %(errCode)s": "Failed to forget room %(errCode)s",
+ "Failed to update keywords": "Failed to update keywords",
+ "Failed to get protocol list from Home Server": "Failed to get protocol list from Home Server",
+ "Failed to get public room list": "Failed to get public room list",
+ "Failed to join the room": "Failed to join the room",
+ "Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
+ "Failed to send report: ": "Failed to send report: ",
+ "Failed to set direct chat tag": "Failed to set direct chat tag",
+ "Failed to set Direct Message status of room": "Failed to set Direct Message status of room",
+ "Favourite": "Favorite",
+ "Fetching third party location failed": "Fetching third party location failed",
+ "Files": "Files",
+ "Filter room names": "Filter room names",
+ "Forget": "Forget",
+ "Forward Message": "Forward Message",
+ " from room": " from room",
+ "Guests can join": "Guests can join",
+ "Guest users can't invite users. Please register to invite.": "Guest users can't invite users. Please register to invite.",
+ "Hide panel": "Hide panel",
+ "I understand the risks and wish to continue": "I understand the risks and wish to continue",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please uncheck:",
+ "Invite to this room": "Invite to this room",
+ "Keywords": "Keywords",
+ "Leave": "Leave",
+ "Loading bug report module": "Loading bug report module",
+ "Low Priority": "Low Priority",
+ "Members": "Members",
+ "Mentions only": "Mentions only",
+ "Messages containing my display name": "Messages containing my display name",
+ "Messages containing keywords": "Messages containing keywords",
+ "Messages containing my user name": "Messages containing my user name",
+ "Messages in group chats": "Messages in group chats",
+ "Messages in one-to-one chats": "Messages in one-to-one chats",
+ "Messages sent by bot": "Messages sent by bot",
+ "more": "more",
+ "Mute": "Mute",
+ "No rooms to show": "No rooms to show",
+ "Noisy": "Noisy",
+ "Notification targets": "Notification targets",
+ "Notifications": "Notifications",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Notifications on the following keywords follow rules which can’t be displayed here:",
+ "Notify for all other messages/rooms": "Notify for all other messages/rooms",
+ "Notify me for anything else": "Notify me for anything else",
+ "Off": "Off",
+ "On": "On",
+ "Operation failed": "Operation failed",
+ "Permalink": "Permalink",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Please describe the bug. What did you do? What did you expect to happen? What actually happened?",
+ "Please describe the bug and/or send logs.": "Please describe the bug and/or send logs.",
+ "Please install Chrome or Firefox for the best experience.": "Please install Chrome or Firefox for the best experience.",
+ "Please Register": "Please Register",
+ "powered by Matrix": "powered by Matrix",
+ "Quote": "Quote",
+ "Redact": "Redact",
+ "Reject": "Reject",
+ "Remove %(name)s from the directory?": "Remove %(name)s from the directory?",
+ "Remove": "Remove",
+ "remove %(name)s from the directory.": "remove %(name)s from the directory.",
+ "Remove from Directory": "Remove from Directory",
+ "Report a bug": "Report a bug",
+ "Resend": "Resend",
+ "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s",
+ "Riot does not know how to join a room on this network": "Riot does not know how to join a room on this network",
+ "Riot is not supported on mobile web. Install the app?": "Riot is not supported on mobile web. Install the app?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.",
+ "Room directory": "Room directory",
+ "Room not found": "Room not found",
+ "Search": "Search",
+ "Search…": "Search…",
+ "Search for a room": "Search for a room",
+ "Send": "Send",
+ "Send logs": "Send logs",
+ "Settings": "Settings",
+ "Source URL": "Source URL",
+ "Sorry, your browser is not able to run Riot.": "Sorry, your browser is not able to run Riot.",
+ "Start chat": "Start chat",
+ "The Home Server may be too old to support third party networks": "The Home Server may be too old to support third party networks",
+ "There are advanced notifications which are not shown here": "There are advanced notifications which are not shown here",
+ "The server may be unavailable or overloaded": "The server may be unavailable or overloaded",
+ "This Room": "This Room",
+ "This room is inaccessible to guests. You may be able to join if you register.": "This room is inaccessible to guests. You may be able to join if you register.",
+ " to room": " to room",
+ "Unable to fetch notification target list": "Unable to fetch notification target list",
+ "Unable to join network": "Unable to join network",
+ "Unable to look up room ID from server": "Unable to look up room ID from server",
+ "Unavailable": "Unavailable",
+ "Unhide Preview": "Unhide Preview",
+ "Unknown device": "Unknown device",
+ "unknown error code": "unknown error code",
+ "Unnamed room": "Unnamed room",
+ "Update": "Update",
+ "Uploaded on %(date)s by %(user)s": "Uploaded on %(date)s by %(user)s",
+ "Uploading report": "Uploading report",
+ "View Decrypted Source": "View Decrypted Source",
+ "View Source": "View Source",
+ "What's New": "What's New",
+ "What's new?": "What's new?",
+ "Waiting for response from server": "Waiting for response from server",
+ "When I'm invited to a room": "When I'm invited to a room",
+ "World readable": "World readable",
+ "You cannot delete this image. (%(code)s)": "You cannot delete this image. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
+ "You are not receiving desktop notifications": "You are not receiving desktop notifications",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "You are Rioting as a guest. Register or sign in to access more rooms and features!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply",
+ "Sunday": "Sunday",
+ "Monday": "Monday",
+ "Tuesday": "Tuesday",
+ "Wednesday": "Wednesday",
+ "Thursday": "Thursday",
+ "Friday": "Friday",
+ "Saturday": "Saturday",
+ "Today": "Today",
+ "Yesterday": "Yesterday",
+ "OK": "OK",
+ "You need to be using HTTPS to place a screen-sharing call.": "You need to be using HTTPS to place a screen-sharing call.",
+ "Welcome page": "Welcome page",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
+ "Login": "Login",
+ "Continue": "Continue",
+ "Failed to change password. Is your password correct?": "Failed to change password. Is your password correct?",
+ "(HTTP status %(httpStatus)s)": "(HTTP status %(httpStatus)s)",
+ "Welcome to Riot.im": "Welcome to Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralised, encrypted chat & collaboration powered by [matrix]",
+ "Chat with Riot Bot": "Chat with Riot Bot",
+ "Search the room directory": "Search the room directory",
+ "Get started with some tips from Riot Bot!": "Get started with some tips from Riot Bot!",
+ "General discussion about Matrix and Riot": "General discussion about Matrix and Riot",
+ "Discussion of all things Matrix!": "Discussion of all things Matrix!",
+ "Matrix technical discussions": "Matrix technical discussions",
+ "Running Matrix services": "Running Matrix services",
+ "Community-run support for Synapse": "Community-run support for Synapse",
+ "Admin support for Dendrite": "Admin support for Dendrite",
+ "Announcements about Synapse releases": "Announcements about Synapse releases",
+ "Support for those using and running matrix-appservice-irc": "Support for those using and running matrix-appservice-irc",
+ "Building services on Matrix": "Building services on Matrix",
+ "Support for those using the Matrix spec": "Support for those using the Matrix spec",
+ "Design and implementation of E2E in Matrix": "Design and implementation of E2E in Matrix",
+ "Implementing VR services with Matrix": "Implementing VR services with Matrix",
+ "Implementing VoIP services with Matrix": "Implementing VoIP services with Matrix",
+ "Discussion of the Identity Service API": "Discussion of the Identity Service API",
+ "Support for those using, running and writing other bridges": "Support for those using, running and writing other bridges",
+ "Contributing code to Matrix and Riot": "Contributing code to Matrix and Riot",
+ "Dev chat for the Riot/Web dev team": "Dev chat for the Riot/Web dev team",
+ "Dev chat for the Dendrite dev team": "Dev chat for the Dendrite dev team",
+ "Co-ordination for Riot/Web translators": "Co-ordination for Riot/Web translators",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!",
+ "You have successfully set a password!": "You have successfully set a password!",
+ "You can now return to your account after signing out, and sign in on other devices.": "You can now return to your account after signing out, and sign in on other devices.",
+ "Please set a password!": "Please set a password!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "This will allow you to return to your account after signing out, and sign in on other devices.",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Android & matrix-android-sdk chat",
+ "Riot/Web & Desktop chat": "Riot/Web & Desktop chat",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/iOS & matrix-ios-sdk chat",
+ "You have successfully set a password and an email address!": "You have successfully set a password and an email address!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Remember, you can always set an email address in user settings if you change your mind."
+}
diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json
new file mode 100644
index 00000000..a7baa043
--- /dev/null
+++ b/src/i18n/strings/eo.json
@@ -0,0 +1,202 @@
+{
+ "A new version of Riot is available.": "Nova versio de \"Riot\" haveblas.",
+ "All messages": "Ĉiuj mesaĝoj",
+ "All messages (loud)": "Ĉiuj mesaĝoj (lauta)",
+ "All Rooms": "Ĉiuj babilejoj",
+ "Cancel": "Nuligi",
+ "Create new room": "Krei novan babilejon",
+ "delete the alias.": "Forviŝi la kromnomon.",
+ "Describe your problem here.": "Priskribi vian problemon ĉi tie.",
+ "Direct Chat": "Rekta babilejo",
+ "Directory": "Dosierujo",
+ "Dismiss": "Eksigu",
+ "Download this file": "Elŝutu ĉi-tiun dosieron",
+ "#example": "#ekzemplo",
+ "Files": "Dosieroj",
+ "Forget": "Forgesi",
+ " from room": " el babilejo",
+ "Guests can join": "Gastoj povas aliĝi",
+ "Guest users can't invite users. Please register to invite.": "Gasta uzantoj ne povas inviti uzantojn. Bonvolu registri por inviti.",
+ "I understand the risks and wish to continue": "Mi komprenas la riskonj kaj volas daŭrigi",
+ "Invite to this room": "Inviti en ĉi tiun babilejon",
+ "Keywords": "Ŝlosilvortoj",
+ "Leave": "Foriri",
+ "Low Priority": "Malalta prioritato",
+ "Messages containing my display name": "Mesaĝoj enhavantaj mian vidigan nomon",
+ "Messages containing keywords": "Mesaĝoj enhavantaj ŝlosilovortojn",
+ "Messages containing my user name": "Mesaĝoj enhavantaj mian uzantnomon",
+ "Messages in group chats": "Mesaĝoj en grupaj babilejoj",
+ "Mute": "Silentigi",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Bonvolu priskribi la cimon. Kion vi faris? Kion vi atendis okazi? Kion fakte okazis?",
+ "Please install Chrome or Firefox for the best experience.": "Bonvolu instali \"Chrome\" aŭ \"Firefox\" por la plej bona sperto.",
+ "Please Register": "Bonvolu registri",
+ "powered by Matrix": "funkciigata de \"Matrix\"",
+ "Quote": "Citu",
+ "Reject": "Malakcepti",
+ "Resend": "Resendi",
+ "Room directory": "Babileja dosierujo",
+ "Room not found": "Babilejo ne trovita",
+ "Search": "Serĉi",
+ "Search…": "Serĉi…",
+ "Search for a room": "Serĉi babilejon",
+ "Send": "Sendi",
+ "Start chat": "Komenci babiladon",
+ "This Room": "Ĉi tiu Babilejo",
+ "Add an email address above to configure email notifications": "Aldonu retadreson supre por agordi retpoŝtajn sciigojn",
+ "Advanced notification settings": "Agordoj de sciigoj specialaj",
+ "Call invitation": "Invito al voko",
+ "All notifications are currently disabled for all targets.": "Ĉiuj sciigoj estas malvalidigitaj por ĉiu aparato.",
+ "An error occurred whilst saving your email notification preferences.": "Eraro okazis dum konservado de agordoj por retpoŝtaj sciigoj.",
+ "Cancel Sending": "Nuligi sendadon",
+ "Can't update user notification settings": "Ne eblas ĝisdatigi la agordojn de sciigoj al uzanto",
+ "Changelog": "Protokolo de ŝanĝoj",
+ "Close": "Fermi",
+ "Collapse panel": "Kaŝi panelon",
+ "Collecting app version information": "Kolektante informon pri versio de la aplikaĵo",
+ "Collecting logs": "Kolektante protokolon",
+ "Couldn't find a matching Matrix room": "Ne eblis trovi kongruantan ejon Matrix",
+ "Custom Server Options": "Opcioj pri personigo de servilo",
+ "customServer_text": "Vi povas uzi opciojn personigitajn de la servilo por ensaluti en aliajn servilojn Matrix specifante alian adreson URL-an de alia servilo Home. Tio permesas al vi uzi Riot per ekzistanta konto en alia Home servilo.
Vi povas ankaŭ agordi servilon identecan personigita, sed ne eblos inviti uzantojn pere de retpoŝtadreso, aŭ esti invitita pere de retpoŝtadreso vi mem.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Forviŝi la kromnomon de la ejo %(alias)s and forigi %(name)s el la dosierujo?",
+ "Enable audible notifications in web client": "Ebligi aŭdeblajn sciigojn en la retkliento",
+ "Enable desktop notifications": "Ebligi labortablajn sciigojn",
+ "Enable email notifications": "Ebligi retpoŝtajn sciigojn",
+ "Enable notifications for this account": "Ebligi sciigojn por tiu ĉi konto",
+ "Enable them now": "Ebligi ilin nun",
+ "Enter keywords separated by a comma:": "Entajpi ŝlosilvortojn apartigitaj per komoj:",
+ "Error": "Eraro",
+ "Error saving email notification preferences": "Eraro konservante agordojn pri retpoŝtaj sciigoj",
+ "Expand panel": "Pli grandigi panelon",
+ "Failed to": "Malsukcesis",
+ "Failed to add tag %(tagName)s to room": "Malsukcesis aldoni etikedon %(tagName)s al la ejo",
+ "Failed to change settings": "Malsukcesis ŝanĝi la agordojn",
+ "Failed to forget room %(errCode)s": "Malsukcesis forgesi la ejon %(errCode)s",
+ "Failed to update keywords": "Malsukcesis ĝisdatigi la ŝlosilvortojn",
+ "Failed to get protocol list from Home Server": "Malsukcesis obteni la liston de protokoloj por la servilo Home",
+ "Failed to get public room list": "Malsukcesis obteni la liston de publikaj ejoj",
+ "Failed to join the room": "Malsukcesis aliĝi al la ejo",
+ "Failed to remove tag %(tagName)s from room": "Malsukcesis forigi la etikedon %(tagName)s el la ejo",
+ "Failed to send report: ": "Malsukcesis sendi raporton: ",
+ "Failed to set direct chat tag": "Malsukcesis agordi la etikedon de rekta babilejo",
+ "Failed to set Direct Message status of room": "Malsukcesis agordi la staton de Rekta Mesaĝo de la ejo",
+ "Forward Message": "Plusendi mesaĝon",
+ "Hide panel": "Kaŝi panelon",
+ "(HTTP status %(httpStatus)s)": "(stato HTTP %(httpStatus)s)",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Por diagnozi problemojn, protokoloj el tiu ĉi kliento sendiĝos kune kun tiu ĉi raporto de eraro. Se vi preferas sendi nur la supran tekston, bonvolu malŝalti:",
+ "Login": "Ensaluti",
+ "Loading bug report module": "Ŝarĝante modulon pri eraroraporto",
+ "Members": "Membroj",
+ "Mentions only": "Nur mencioj",
+ "Messages in one-to-one chats": "Mesaĝoj en unu-je-unu babilejoj",
+ "Messages sent by bot": "Mesaĝoj sendita per roboto",
+ "more": "pli",
+ "No rooms to show": "Neniu ejo por montri",
+ "Noisy": "Brua",
+ "Notification targets": "Celo de sciigoj",
+ "Notifications": "Sciigoj",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "La sciigoj de la sekvaj ŝlosilvortoj sekvas regulojn kiuj ne povas esti montrataj ĉi tie:",
+ "Notify for all other messages/rooms": "Sciigu min por ĉiu alia babilejo",
+ "Notify me for anything else": "Sciigu min por ĉio alia",
+ "Off": "Malŝaltita",
+ "On": "Ŝaltita",
+ "Operation failed": "La operacio malsukcesis",
+ "Permalink": "Konstanta ligilo",
+ "Please describe the bug and/or send logs.": "Bonvolu priskribi la cimon kaj/aŭ sendi protokolojn.",
+ "Redact": "Redakti",
+ "Remove %(name)s from the directory?": "Forigi %(name)s el la dosierujo?",
+ "Remove": "Forigi",
+ "remove %(name)s from the directory.": "forigi %(name)s el la dosierujo.",
+ "Remove from Directory": "Forigi el Dosierujo",
+ "Report a bug": "Raporti cimon",
+ "Riot Desktop on %(platformName)s": "Riot Labortablo sur %(platformName)s",
+ "Riot does not know how to join a room on this network": "Riot ne scias kiel aliĝi al ejo en tiu ĉi reto",
+ "Riot is not supported on mobile web. Install the app?": "Riot ne estas subtenita je mobile web. Instali la aplikaĵon?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uzas multajn specialajn trajtojn, kelkaj ne estas disponeblaj aŭ estas eksperimentaj en via nuna retumilo.",
+ "Send logs": "Sendi protokolojn",
+ "Settings": "Agordoj",
+ "Source URL": "Fonta URL",
+ "Sorry, your browser is not able to run Riot.": "Pardonu, via retumilo ne kapablas funkciigi Riot.",
+ "The Home Server may be too old to support third party networks": "La servilo Home povas esti tro malnova por subteni retoj de ekstera liveranto",
+ "There are advanced notifications which are not shown here": "Estas specialaj sciigoj kiuj ne estas montritaj ĉi tie",
+ "The server may be unavailable or overloaded": "La servilo povas esti maldisponebla aŭ tro ŝarĝita",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Ci tiu ejo estas neenirebla por gastoj. Vi povus aliĝi se vi registriĝas.",
+ " to room": " al ejo",
+ "Unable to fetch notification target list": "Ne eblis obteni la liston de celoj por sciigoj",
+ "Unable to join network": "Ne eblis kuniĝi kun la reto",
+ "Unable to look up room ID from server": "Ne eblis trovi la identigon el la servilo",
+ "Unavailable": "Maldisponebla",
+ "Unhide Preview": "Malkaŝi antaŭrigardon",
+ "Unknown device": "Nekonata aparato",
+ "unknown error code": "kodo de nekonata eraro",
+ "Unnamed room": "Nekonata ejo",
+ "Update": "Ĝisdatigi",
+ "Uploaded on %(date)s by %(user)s": "Alŝutita je %(date)s per %(user)s",
+ "Uploading report": "Alŝutante raporton",
+ "View Decrypted Source": "Vidi malĉifritan fonton",
+ "View Source": "Vidi fonton",
+ "What's New": "Kio novas",
+ "What's new?": "Kio novas?",
+ "Waiting for response from server": "Atendante respondon el la servilo",
+ "When I'm invited to a room": "Kiam mi estas invitita en ejon",
+ "World readable": "Legebla tutmonde",
+ "You cannot delete this image. (%(code)s)": "Vi ne povas forviŝi tiun ĉi bildon. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Vi ne povas forviŝi tiun ĉi mesaĝon. (%(code)s)",
+ "You are not receiving desktop notifications": "Vi ne estas ricevante sciigojn labortablan",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Vi uzas Riot kiel gasto. Registriĝu aŭ ensalutu por atingi pli da ejoj kaj funkcioj!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Vi eble agordis ilin en kliento kiu ne estis Riot. Vi ne povas agordi ilin en Riot sed ili ankoraŭ validas",
+ "Sunday": "Dimanĉo",
+ "Monday": "Lundo",
+ "Tuesday": "Mardo",
+ "Wednesday": "Merkredo",
+ "Thursday": "Ĵaŭdo",
+ "Friday": "Vendredo",
+ "Saturday": "Sabato",
+ "Today": "Hodiaŭ",
+ "Yesterday": "Hieraŭ",
+ "OK": "Bone",
+ "You need to be using HTTPS to place a screen-sharing call.": "Vi devas uzi HTTPS por starigi ekranan vokon.",
+ "Welcome page": "Paĝo de bonveno",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Kun via nuna retumilo, la aspekto kaj funkciado de la aplikaĵo povas esti tute malĝusta, kaj kelkaj aŭ ĉiu funkcioj eble ne funkcios. Se vi volas provi ĉiuokaze vi rajtas daŭrigi, sed ne estos subteno se vi trafas problemojn!",
+ "Welcome to Riot.im": "Bonvenon al Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Malcentra, ĉifrita babilejo & kunlaboro povigita de [matrix]",
+ "Search the room directory": "Serĉi la ejan dosierujon",
+ "Chat with Riot Bot": "Babili kun la roboto Riot Bot",
+ "Get started with some tips from Riot Bot!": "Eki per sugesto de la roboto Riot Bot!",
+ "General discussion about Matrix and Riot": "Ĝenerala diskutado pri Matrix kaj Riot",
+ "Discussion of all things Matrix!": "Diskutado pri ĉio rilate al Matrix!",
+ "Riot/Web & Desktop chat": "Diskudato labortabla pri Riot/Web",
+ "Riot/iOS & matrix-ios-sdk chat": "Diskutado pri Riot/iOS & matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Diskutado pri Riot/Android & matrix-android-sdk",
+ "Matrix technical discussions": "Teknikaj diskutoj pri Matrix",
+ "Running Matrix services": "Funkciigado de servoj Matrix",
+ "Community-run support for Synapse": "Komunuma subtenado de Synapse",
+ "Admin support for Dendrite": "Administra subtenado por Dendrite",
+ "Announcements about Synapse releases": "Anoncoj pri eldonoj Synapse",
+ "Support for those using and running matrix-appservice-irc": "Subteno por tiuj, kiuj uzas kaj funkciigas matrix-appservice-irc",
+ "Building services on Matrix": "Konstruante servojn per Matrix",
+ "Support for those using the Matrix spec": "Subteno por tiuj, kiuj uzas la specifon Matrix",
+ "Design and implementation of E2E in Matrix": "Dizajno kaj realigo de E2E en Matrix",
+ "Implementing VR services with Matrix": "Realigi VR-servojn per Matrix",
+ "Implementing VoIP services with Matrix": "Realigi VoIP-servojn per Matrix",
+ "Discussion of the Identity Service API": "Diskutado pri la API de Identiga Servo",
+ "Support for those using, running and writing other bridges": "Subteno por tiuj, kiuj uzas, funkciigas kaj skribas aliajn pontojn",
+ "Contributing code to Matrix and Riot": "Kontribui kodon al Matrix kaj Riot",
+ "Dev chat for the Riot/Web dev team": "Programista babilado por la programteamo de Riot/Web",
+ "Dev chat for the Dendrite dev team": "Programista babilado por la programteamo de Dendrite",
+ "Co-ordination for Riot/Web translators": "Kunordigado por tradukistoj de Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Multaj ejoj jam ekzistas en Matrix, ligitaj al ekzistantaj retoj (Slock, IRC, Gitter, ktp) aŭ sendependaj. Kontrolu la dosierujon!",
+ "Failed to change password. Is your password correct?": "Malsukcesis ŝanĝi la pasvorton. Ĉu via pasvorto pravas?",
+ "You have successfully set a password!": "Vi sukcese agordis pasvorton!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Vi nun rajtas reiri al via konto post elsaluto, kaj ensaluti per aliaj aparatoj.",
+ "Continue": "Daŭrigi",
+ "Please set a password!": "Bonvolu agordi pasvorton!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Tio ĉi permesos vin reiri al via konto post elsaluto, kaj ensaluti per alia aparato.",
+ "You have successfully set a password and an email address!": "Vi sukcese agordis pasvorton kaj retpoŝtadreson!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Memoru, vi ĉiam povas agordi retpoŝtadreson en via uzanta agordo se vi decidas ŝanĝi ĝin poste.",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s per %(browserName)s je %(osName)s",
+ "Safari and Opera work too.": "Safari kaj Opera ankaŭ funkcias.",
+ "Drop here %(toAction)s": "Forlasi ĉi tie %(toAction)s",
+ "Favourite": "Plej ŝatata",
+ "Fetching third party location failed": "Venigado de ekstere liverita loko malsukcesis",
+ "Filter room names": "Filtri nomojn de ejoj"
+}
diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json
new file mode 100644
index 00000000..af1efb60
--- /dev/null
+++ b/src/i18n/strings/es.json
@@ -0,0 +1,202 @@
+{
+ "Add an email address above to configure email notifications": "Añade una dirección de email arriba para configurar las notificaciones por email",
+ "Advanced notification settings": "Configuración de notificaciones avanzada",
+ "All messages": "Todos los mensajes",
+ "An error occurred whilst saving your email notification preferences.": "Se ha producido un error al guardar las preferencias de notificación por email.",
+ "Call invitation": "Invitación a la llamada",
+ "Cancel Sending": "Cancelar envío",
+ "Can't update user notification settings": "No se puede actualizar la configuración de notificación de usuario",
+ "Close": "Cerrar",
+ "Create new room": "Crear nueva sala",
+ "Couldn't find a matching Matrix room": "No se encontró una sala Matrix que coincidiera",
+ "Custom Server Options": "Opciones de Servidor Personalizado",
+ "customServer_text": "Puedes utilizar las opciones de servidor personalizadas para iniciar sesión en otros servidores Matrix especificando una URL de Home server distinta. Esto te permite usar Riot con una cuenta Matrix existente en un Home server distinto.
También puedes configurar un servidor de identidad personalizado, pero no podrás invitar usuarios por dirección de email, ni ser invitado por email por ti mismo.",
+ "delete the alias.": "borrar el alias.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "¿Borrar la sala alias %(alias)s y retirar %(name)s del directorio?",
+ "Direct Chat": "Conversación directa",
+ "Directory": "Directorio",
+ "Download this file": "Descargar este archivo",
+ "Drop here %(toAction)s": "Suelta aquí %(toAction)s",
+ "Enable audible notifications in web client": "Habilitar notificaciones audibles en el cliente web",
+ "Enable desktop notifications": "Habilitar notificaciones de escritorio",
+ "Enable email notifications": "Habilitar notificaciones por email",
+ "Enable notifications for this account": "Habilitar notificaciones para esta cuenta",
+ "Enable them now": "Habilitarlos ahora",
+ "Enter keywords separated by a comma:": "Introduzca palabras clave separadas por una coma:",
+ "Error": "Error",
+ "Error saving email notification preferences": "Error al guardar las preferencias de notificación por email",
+ "#example": "#ejemplo",
+ "Failed to add tag %(tagName)s to room": "Error al añadir la etiqueta %(tagName)s a la sala",
+ "Failed to change settings": "Error al cambiar la configuración",
+ "Failed to forget room %(errCode)s": "Falló al olvidar la sala %(errCode)s",
+ "Failed to update keywords": "Error al actualizar las palabras clave",
+ "Failed to get protocol list from Home Server": "Error al obtener la lista de protocolos de Home Server",
+ "Failed to get public room list": "No se pudo obtener la lista de salas públicas",
+ "Failed to join the room": "Falló al unirse a la sala",
+ "Failed to remove tag %(tagName)s from room": "Error al eliminar la etiqueta %(tagName)s de la sala",
+ "Failed to set direct chat tag": "Error al establecer la etiqueta de chat directo",
+ "Failed to set Direct Message status of room": "No se pudo establecer el estado de Mensaje Directo de la sala",
+ "Favourite": "Favorito",
+ "Fetching third party location failed": "Falló la obtención de la ubicación de un tercero",
+ "Files": "Archivos",
+ "Filter room names": "Filtrar los nombres de las salas",
+ "Forget": "Olvidar",
+ " from room": " de la sala",
+ "Guests can join": "Los invitados se pueden unir",
+ "Guest users can't invite users. Please register to invite.": "Los usuarios invitados no pueden invitar usuarios. Por favor, regístrate para poder invitar.",
+ "Invite to this room": "Invitar a esta sala",
+ "Keywords": "Palabras clave",
+ "Leave": "Salir",
+ "Low Priority": "Baja Prioridad",
+ "Members": "Miembros",
+ "Mentions only": "Sólo menciones",
+ "Messages containing my display name": "Mensajes que contienen mi nombre para mostrar",
+ "Messages containing my user name": "Mensajes que contienen mi nombre de usuario",
+ "Messages in group chats": "Mensajes en chats de grupo",
+ "Messages in one-to-one chats": "Mensajes en chats uno a uno",
+ "Messages sent by bot": "Mensajes enviados por bot",
+ "more": "más",
+ "Mute": "Silenciar",
+ "No rooms to show": "Sin salas para mostrar",
+ "Noisy": "Ruidoso",
+ "Notification targets": "Objetivos de notificación",
+ "Notifications": "Notificaciones",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Las notificaciones de las siguientes palabras clave siguen reglas que no se pueden mostrar aquí:",
+ "Notify me for anything else": "Notificarme para cualquier otra cosa",
+ "Off": "Apagado",
+ "On": "Encendido",
+ "Operation failed": "Falló la operación",
+ "Permalink": "Enlace permanente",
+ "Please Register": "Por favor, regístrese",
+ "Quote": "Citar",
+ "Redact": "Redactar",
+ "Reject": "Rechazar",
+ "Remove %(name)s from the directory?": "¿Retirar %(name)s del directorio?",
+ "Remove": "Eliminar",
+ "remove %(name)s from the directory.": "retirar %(name)s del directorio.",
+ "Remove from Directory": "Retirar del Directorio",
+ "Resend": "Reenviar",
+ "Riot does not know how to join a room on this network": "Riot no sabe cómo unirse a una sala en esta red",
+ "Room directory": "Directorio de salas",
+ "Room not found": "Sala no encontrada",
+ "Search for a room": "Buscar sala",
+ "Settings": "Configuración",
+ "Source URL": "URL de origen",
+ "Start chat": "Comenzar chat",
+ "The Home Server may be too old to support third party networks": "El Home Server puede ser demasiado antiguo para soportar redes de terceros",
+ "There are advanced notifications which are not shown here": "Hay notificaciones avanzadas que no se muestran aquí",
+ "The server may be unavailable or overloaded": "El servidor puede estar no disponible o sobrecargado",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Esta sala es inaccesible para los invitados. Puedes unirse si te registras.",
+ " to room": " a la sala",
+ "Unable to fetch notification target list": "No se puede obtener la lista de objetivos de notificación",
+ "Unable to join network": "No se puede unir a la red",
+ "Unable to look up room ID from server": "No se puede buscar el ID de la sala desde el servidor",
+ "Unhide Preview": "Mostrar Vista Previa",
+ "unknown error code": "Código de error desconocido",
+ "Unnamed room": "Sala sin nombre",
+ "Uploaded on %(date)s by %(user)s": "Subido el %(date)s por %(user)s",
+ "View Decrypted Source": "Ver Fuente Descifrada",
+ "View Source": "Ver Fuente",
+ "When I'm invited to a room": "Cuando estoy invitado a una sala",
+ "World readable": "Legible por todo el mundo",
+ "You cannot delete this image. (%(code)s)": "No puedes eliminar esta imagen. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "No puedes eliminar este mensaje. (%(code)s)",
+ "You are not receiving desktop notifications": "No estás recibiendo notificaciones de escritorio",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Es posible que los hayas configurado en un cliente que no sea Riot. No puedes ajustarlos en Riot, pero todavía se aplican",
+ "Sunday": "Domingo",
+ "Monday": "Lunes",
+ "Tuesday": "Martes",
+ "Wednesday": "Miércoles",
+ "Thursday": "Jueves",
+ "Friday": "Viernes",
+ "Saturday": "Sábado",
+ "Today": "Hoy",
+ "Yesterday": "Ayer",
+ "Welcome page": "Página de bienvenida",
+ "Continue": "Continuar",
+ "Search": "Búsqueda",
+ "OK": "Correcto",
+ "Failed to change password. Is your password correct?": "Falló al cambiar la clave, ¿Está correcta tu clave?",
+ "Safari and Opera work too.": "Safari y Opera también funcionan.",
+ "A new version of Riot is available.": "Una nueva versión de Riot está disponible.",
+ "Cancel": "Cancelar",
+ "Describe your problem here.": "Describa su problema aquí.",
+ "Forward Message": "Reenviar mensaje",
+ "Hide panel": "Ocultar panel",
+ "(HTTP status %(httpStatus)s)": "(estado HTTP %(httpStatus)s)",
+ "I understand the risks and wish to continue": "Entiendo los riesgos y deseo continuar",
+ "Changelog": "Bitácora de cambios",
+ "Collapse panel": "Colapsar panel",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Recuerde que, si es necesario, puede establecer una dirección de email en las preferencias de usuario.",
+ "All Rooms": "Todas las salas",
+ "Expand panel": "Expandir panel",
+ "Failed to": "Falló",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Para diagnosticar los problemas, las trazas de este cliente serán enviadas adjuntas a este informe de defecto. Si quisiera enviar el texto anterior solamente, entonces desmarque:",
+ "Login": "Abrir sesión",
+ "Report a bug": "Informe un defecto",
+ "Search…": "Buscar…",
+ "Send": "Enviar",
+ "Send logs": "Enviar trazas",
+ "Sorry, your browser is not able to run Riot.": "¡Lo sentimos! Su navegador no puede ejecutar Riot.",
+ "This Room": "Esta sala",
+ "Unavailable": "No disponible",
+ "Unknown device": "Dispositivo desconocido",
+ "Update": "Actualizar",
+ "Uploading report": "Enviando informe",
+ "What's New": "Lo que hay de nuevo",
+ "What's new?": "¿Qué hay de nuevo?",
+ "Waiting for response from server": "Esperando una respuesta del servidor",
+ "You have successfully set a password and an email address!": "¡Ha establecido exitosamente la contraseña y la dirección de email!",
+ "You have successfully set a password!": "¡Ha establecido exitosamente una contraseña!",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s en %(osName)s",
+ "All messages (loud)": "Todos los mensajes (ruidoso)",
+ "All notifications are currently disabled for all targets.": "Las notificaciones estan desactivadas en todos los objetivos.",
+ "Collecting app version information": "Recolectando información de la versión de la aplicación",
+ "Collecting logs": "Recolectando registros",
+ "Dismiss": "Omitir",
+ "Failed to send report: ": "Error al enviar reporte: ",
+ "Loading bug report module": "Cargando módulo de reporte de errores",
+ "Messages containing keywords": "Mensajes que contienen palabras clave",
+ "Notify for all other messages/rooms": "Notificar para todos los demás mensajes/salas",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Por favor describa el error. Qué acción ejecutó? Cuál era el resultado que esperaba? Que pasó realmente?",
+ "Please describe the bug and/or send logs.": "Por favor describa el error y/o envíe los registros.",
+ "Please install Chrome or Firefox for the best experience.": "Por favor instale Google Chrome o Mozilla Firefox para una mejor experiencia.",
+ "powered by Matrix": "con el poder de Matrix",
+ "Riot Desktop on %(platformName)s": "Riot Desktop en %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot no está soportado en navegadores Web móviles. Quieres instalar la aplicación?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot usa muchas características avanzadas del navegador, algunas de las cuales no están disponibles en su navegador actual.",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Está usando Riot como invitado. ¡Regístrese o inicie sesión para acceder más salas y características!",
+ "You need to be using HTTPS to place a screen-sharing call.": "Debes usar HTTPS para hacer una llamada con pantalla compartida.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "En su navegador actual, la apariencia de la aplicación puede ser completamente incorrecta, y algunas de las características podrían no funcionar. Si aún desea probarlo puede continuar, pero ¡no podremos ofrecer soporte por cualquier problema que pudiese tener!",
+ "Welcome to Riot.im": "Bienvenido a Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Conversaciones & colaboración cifradas y descentralizadas con el poder de [matrix]",
+ "Search the room directory": "Buscar en el directorio de salas",
+ "Chat with Riot Bot": "Conversar con el Bot de Riot",
+ "Get started with some tips from Riot Bot!": "¡Comenzar con algunos tips de Riot Bot!",
+ "General discussion about Matrix and Riot": "Discusión general sobre Matrix y Riot",
+ "Discussion of all things Matrix!": "¡Discusión sobre todas las cosas de Matrix!",
+ "Riot/Web & Desktop chat": "Conversaciones de Riot/Web & Desktop",
+ "Riot/iOS & matrix-ios-sdk chat": "Conversaciones sobre Riot/iOS & matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Conversaciones sobre Riot/Android & matrix-android-sdk",
+ "Matrix technical discussions": "Discusiones técnicas sobre Matrix",
+ "Running Matrix services": "Ejecutando servicios de Matrix",
+ "Community-run support for Synapse": "Soporte comunitario de Synapse",
+ "Admin support for Dendrite": "Soporte administrativo para Dendrite",
+ "Announcements about Synapse releases": "Anuncios de lanzamientos de Synapse",
+ "Support for those using and running matrix-appservice-irc": "Soporte para aquellos que usan o administran matrix-appservice-irc",
+ "Building services on Matrix": "Construyendo servicios con Matrix",
+ "Support for those using the Matrix spec": "Soporte para usuarios de la especificación de Matrix",
+ "Design and implementation of E2E in Matrix": "Diseño e implementación de E2E en Matrix",
+ "Implementing VR services with Matrix": "Implementación de servicios VR con Matrix",
+ "Implementing VoIP services with Matrix": "Implementación de servicios VoIP con Matrix",
+ "Discussion of the Identity Service API": "Discusión sobre el API de Identity Service",
+ "Support for those using, running and writing other bridges": "Soporte para usuarios, administradores y desarrolladores de otros puentes",
+ "Contributing code to Matrix and Riot": "Contribuciones de código para Matrix y Riot",
+ "Dev chat for the Riot/Web dev team": "Conversaciones del equipo de desarrollo de Riot/Web",
+ "Dev chat for the Dendrite dev team": "Conversaciones del equipo de desarrollo de Dendrite",
+ "Co-ordination for Riot/Web translators": "Coordinación para traductores de Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Muchas salas ya están disponibles en Matrix, enlazadas a redes existentes (Slack, IRC, Gitter, etc) o independientes. ¡Revisa el directorio!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Ahora puedes regresar a tu cuenta después de cerrar tu sesión, e iniciar sesión en otros dispositivos.",
+ "Please set a password!": "¡Por favor establece una contraseña!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Esto le permitirá regresar a su cuenta después de cerrar sesión, así como iniciar sesión en otros dispositivos."
+}
diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json
new file mode 100644
index 00000000..d2e59432
--- /dev/null
+++ b/src/i18n/strings/fi.json
@@ -0,0 +1,3 @@
+{
+ "Sunday": "Sunnuntai"
+}
diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json
new file mode 100644
index 00000000..13cf15ce
--- /dev/null
+++ b/src/i18n/strings/fr.json
@@ -0,0 +1,203 @@
+{
+ "Add an email address above to configure email notifications": "Ajouter une adresse email pour la configuration des notifications par email",
+ "All messages": "Tous les messages",
+ "All messages (loud)": "Tous les messages (fort)",
+ "All notifications are currently disabled for all targets.": "Toutes les notifications sont désactivées pour tous les appareils.",
+ "An error occurred whilst saving your email notification preferences.": "Une erreur est survenue lors de la sauvegarde de vos préférences de notifications par e-mail.",
+ "Cancel Sending": "Annuler l'envoi",
+ "Can't update user notification settings": "Impossible de mettre à jour les notifications utilisateur",
+ "Close": "Fermer",
+ "Create new room": "Créer un nouveau salon",
+ "Couldn't find a matching Matrix room": "Impossible de trouver un salon Matrix",
+ "Custom Server Options": "Options de serveur personnalisées",
+ "delete the alias.": "supprimer l'alias.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Supprimer l'alias %(alias)s du salon et supprimer %(name)s du répertoire ?",
+ "Direct Chat": "Conversation Directe",
+ "Directory": "Répertoire",
+ "Dismiss": "Ignorer",
+ "Download this file": "Télécharger ce fichier",
+ "Drop here %(toAction)s": "Déposer ici %(toAction)s",
+ "Enable audible notifications in web client": "Activer les notifications sonores pour le client web",
+ "Enable desktop notifications": "Activer les notifications de bureau",
+ "Enable email notifications": "Activer les notifications par e-mail",
+ "Enable notifications for this account": "Activer les notifications pour ce compte",
+ "Enable them now": "Les activer maintenant",
+ "Enter keywords separated by a comma:": "Entrez les mots clés séparés par une virgule :",
+ "Error": "Erreur",
+ "Error saving email notification preferences": "Erreur lors de la sauvegarde des notifications par email",
+ "#example": "#exemple",
+ "Failed to": "Échec pour",
+ "Failed to add tag %(tagName)s to room": "Échec lors de l'ajout de l’étiquette %(tagName)s au salon",
+ "Failed to change settings": "Échec de la mise à jour des paramètres",
+ "Failed to forget room %(errCode)s": "Échec lors de l'oubli du salon %(errCode)s",
+ "Failed to update keywords": "Échec dans la mise à jour des mots-clés",
+ "Failed to get protocol list from Home Server": "Échec lors de la récupération de la liste sur le serveur",
+ "Failed to get public room list": "Échec lors de la récupération de la liste des salons publics",
+ "Failed to join the room": "Échec de l'adhésion au salon",
+ "Failed to remove tag %(tagName)s from room": "Échec dans la suppression de l’étiquette %(tagName)s du salon",
+ "Failed to set direct chat tag": "Échec dans l'attribution d'une étiquette dans le chat direct",
+ "Favourite": "Favoris",
+ "Operation failed": "L'opération a échoué",
+ "Please Register": "Veuillez vous enregistrer",
+ "powered by Matrix": "propulsé par Matrix",
+ "Quote": "Citer",
+ "Redact": "Rédiger",
+ "Reject": "Rejeter",
+ "Remove %(name)s from the directory?": "Supprimer %(name)s du répertoire ?",
+ "Remove": "Supprimer",
+ "Resend": "Renvoyer",
+ "Settings": "Paramètres",
+ "Start chat": "Démarrer une discussion",
+ "unknown error code": "Code erreur inconnu",
+ "View Source": "Voir la source",
+ "You cannot delete this image. (%(code)s)": "Vous ne pouvez pas supprimer cette image. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Vous ne pouvez pas supprimer ce message. (%(code)s)",
+ "You are not receiving desktop notifications": "Vous ne recevez pas les notifications sur votre bureau",
+ "Sunday": "Dimanche",
+ "Monday": "Lundi",
+ "Tuesday": "Mardi",
+ "Wednesday": "Mercredi",
+ "Thursday": "Jeudi",
+ "Friday": "Vendredi",
+ "Saturday": "Samedi",
+ "Today": "Aujourd'hui",
+ "Yesterday": "Hier",
+ "Welcome page": "Page d'accueil",
+ "Call invitation": "Appel entrant",
+ "Failed to set Direct Message status of room": "Échec de la configuration de l'état de Message Direct du salon",
+ "Fetching third party location failed": "Échec de la récupération de la localisation tierce",
+ "Files": "Fichiers",
+ "Filter room names": "Filtrer les salons par nom",
+ "Forget": "Oublier",
+ " from room": " du salon",
+ "Guest users can't invite users. Please register to invite.": "Les visiteurs ne peuvent démarrer une discussion. Merci de vous enregistrer pour pouvoir démarrer une discussion.",
+ "Invite to this room": "Inviter dans ce salon",
+ "Keywords": "Mots-clés",
+ "Leave": "Quitter",
+ "Low Priority": "Priorité Basse",
+ "Members": "Membres",
+ "Mentions only": "Seulement les mentions",
+ "Messages containing my display name": "Messages contenant mon nom",
+ "Messages containing my user name": "Message contenant mon nom d'utilisateur",
+ "Messages in group chats": "Messages dans les conversations de groupe",
+ "Messages in one-to-one chats": "Messages dans les conversations directes",
+ "Messages sent by bot": "Messages envoyés par des robots",
+ "more": "plus",
+ "Mute": "Couper le son",
+ "No rooms to show": "Aucun salon à afficher",
+ "Noisy": "Activer le son",
+ "Notification targets": "Appareils recevant les notifications",
+ "Notifications": "Notifications",
+ "Notifications on the following keywords follow rules which can’t be displayed here": "Les mots-clés suivants suivent des règles de notification qui ne peuvent être affichées ici",
+ "Notify for all other messages/rooms": "Me notifier pour tous les autres messages/salons",
+ "Notify me for anything else": "Me notifier pour tout le reste",
+ "Off": "Désactivé",
+ "On": "Activé",
+ "Permalink": "Permalien",
+ "remove %(name)s from the directory.": "supprimer %(name)s du répertoire.",
+ "Remove from Directory": "Supprimer du répertoire",
+ "Riot does not know how to join a room on this network": "Riot ne peut pas joindre un salon sur ce réseau",
+ "Room directory": "Répertoire des salons",
+ "Room not found": "Salon non trouvé",
+ "Search for a room": "Chercher un salon",
+ "Source URL": "URL source",
+ "The Home Server may be too old to support third party networks": "Le Home Server semble trop ancien pour supporter des réseaux tiers",
+ "There are advanced notifications which are not shown here": "Il existe une configuration avancée des notifications qui ne peut être affichée ici",
+ "The server may be unavailable or overloaded": "Le serveur est indisponible ou surchargé",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Ce salon n'est pas ouvert aux visiteurs. Vous pourrez peut-être le rejoindre si vous vous enregistrez.",
+ "Unable to fetch notification target list": "Impossible de récupérer la liste des appareils recevant les notifications",
+ "Unable to join network": "Impossible de rejoindre le réseau",
+ "Unable to look up room ID from server": "Impossible de récupérer l'ID du salon sur le serveur",
+ "Unhide Preview": "Dévoiler l'aperçu",
+ "Unnamed room": "Salon anonyme",
+ "Uploaded on %(date)s by %(user)s": "Téléchargé le %(date)s par %(user)s",
+ "View Decrypted Source": "Voir la source décryptée",
+ "When I'm invited to a room": "Quand je suis invité dans un salon",
+ "World readable": "Visible par tout le monde",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Vous les avez probablement configurées dans un autre client que Riot. Vous ne pouvez pas les configurer dans Riot mais elles s'appliquent quand même",
+ "Guests can join": "Ouvert aux visiteurs",
+ " to room": " au salon",
+ "Advanced notification settings": "Paramètres de notification avancés",
+ "customServer_text": "Vous pouvez utiliser l'option de serveur personnalisé pour vous connectez à d'autres serveurs Matrix, en spécifiant une adresse de homerserver différente. Cela permet d'utiliser Riot avec un compte existant sur un homeserver différent.
Vous pouvez aussi indiquer un serveur d'identité personnel mais vous ne pourrez plus inviter des utilisateurs par email, ou être invité par email.",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Les notifications pour les mots-clés suivant répondent à des critères qui ne peuvent pas être affichés ici :",
+ "Collapse panel": "Cacher le panneau",
+ "Expand panel": "Dévoiler le panneau",
+ "I understand the risks and wish to continue": "Je comprends les risques et souhaite continuer",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot utilise de nombreuses fonctionnalités avancées du navigateur, certaines ne sont pas disponibles ou expérimentales dans votre navigateur actuel.",
+ "Sorry, your browser is not able to run Riot.": "Désolé, Riot n'est pas supporté par votre navigateur.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Depuis votre navigateur actuel, le visuel et le ressenti de l'application pourraient être complètement incorrects, et certaines fonctionnalités pourraient ne pas être supportées. Vous pouvez continuer malgré tout, mais vous n'aurez pas de support si vous rencontrez des problèmes !",
+ "Please install Chrome or Firefox for the best experience.": "Veuillez installer Chrome ou Firefox pour une expérience optimale.",
+ "Safari and Opera work too.": "Safari et Opera fonctionnent aussi.",
+ "Messages containing keywords": "Messages contenant des mots-clés",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s dans %(browserName)s sous %(osName)s",
+ "A new version of Riot is available.": "Une nouvelle version de Riot est disponible.",
+ "All Rooms": "Tous les salons",
+ "Cancel": "Annuler",
+ "Changelog": "Journal des modif",
+ "Collecting app version information": "Récupération des info de version de l’application",
+ "Collecting logs": "Récupération des traces",
+ "Describe your problem here.": "Décrivez votre problème ici.",
+ "Failed to send report: ": "Échec de l’envoi du rapport : ",
+ "Forward Message": "Transférer le message",
+ "Hide panel": "Cacher le panneau",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Afin de diagnostiquer le problème, les traces de ce client vont être envoyées avec ce rapport d’erreur. Si vous préférez seulement envoyer le texte ci-dessus, décochez la case :",
+ "Loading bug report module": "Chargement du module de rapport d’erreur",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Veuillez décrire le problème. Qu’avez-vous fait ? Quel comportement vous attendiez vous à voir ? Que s’est-il effectivement passé ?",
+ "Please describe the bug and/or send logs.": "Veuillez décrire le problème et/ou envoyer les traces.",
+ "Report a bug": "Reporter un problème",
+ "Riot Desktop on %(platformName)s": "Version bureau de Riot sur %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot Web n’est pas supporté sur mobile. Installer l’application ?",
+ "Search": "Rechercher",
+ "Search…": "Rechercher…",
+ "Send": "Envoyer",
+ "Send logs": "Envoyer les traces",
+ "This Room": "Ce salon",
+ "Unavailable": "Indisponible",
+ "Unknown device": "Appareil inconnu",
+ "Update": "Mettre à jour",
+ "Uploading report": "Téléchargement du rapport",
+ "What's New": "Nouveautés",
+ "What's new?": "Nouveautés ?",
+ "Waiting for response from server": "En attente d’une réponse du serveur",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Vous utilisez Riot en tant que visiteur. Enregistrez-vous ou identifiez-vous pour accéder à plus de salons et de fonctionnalités !",
+ "You need to be using HTTPS to place a screen-sharing call.": "Vous devez utiliser HTTPS pour effectuer un appel en partage d’écran.",
+ "OK": "OK",
+ "Failed to change password. Is your password correct?": "Échec du changement de mot de passe. Votre mot de passe est-il correct ?",
+ "You have successfully set a password!": "Vous avez paramétré un mot de passe avec succès !",
+ "Continue": "Continuer",
+ "Please set a password!": "Veuillez définir un mot de passe !",
+ "You can now return to your account after signing out, and sign in on other devices.": "Vous pouvez maintenant revenir sur votre compte après vous être déconnecté, et vous identifier sur d'autres appareils.",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Cela vous permettra de retourner sur votre compte après vous être déconnecté, et de vous identifier sur d'autres appareils.",
+ "Welcome to Riot.im": "Bienvenue sur Riot.im",
+ "(HTTP status %(httpStatus)s)": "(statut HTTP %(httpStatus)s)",
+ "Login": "S'identifier",
+ "Chat with Riot Bot": "Discussion avec Riot Bot",
+ "Search the room directory": "Rechercher dans le répertoire de salon",
+ "Get started with some tips from Riot Bot!": "Démarrer avec quelques astuces de Riot Bot !",
+ "Riot/Android & matrix-android-sdk chat": "Discussions Riot/Android & matrix-android-sd",
+ "Riot/iOS & matrix-ios-sdk chat": "Discussions Riot/iOS & matrix-ios-sdk",
+ "General discussion about Matrix and Riot": "Discussion générale sur Matrix et Riot",
+ "Riot/Web & Desktop chat": "Discussions Riot/Web & Desktop",
+ "Running Matrix services": "Execution de services Matrix",
+ "Admin support for Dendrite": "Support admin pour Dendrite",
+ "Announcements about Synapse releases": "Communiqués sur les nouvelles versions de Synapse",
+ "Matrix technical discussions": "Discussions techniques sur Matrix",
+ "Community-run support for Synapse": "Support communautaire sur Synape",
+ "Support for those using and running matrix-appservice-irc": "Support pour ceux qui utilisent et exécutent matrix-appservice-irc",
+ "Building services on Matrix": "Développement de services sur Matrix",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Discussion & collaboration décentralisées et encryptées propulsé par [matrix]",
+ "Discussion of all things Matrix!": "Discussion de tous les sujets Matrix !",
+ "Support for those using the Matrix spec": "Support pour les utilisateurs de la spec Matrix",
+ "Design and implementation of E2E in Matrix": "Définition et implémentation de la crypto dans Matrix",
+ "Implementing VR services with Matrix": "Implémentation de de services de réalité virtuelle avec Matrix",
+ "Implementing VoIP services with Matrix": "Implémentation de de services de voix sur IP avec Matrix",
+ "Discussion of the Identity Service API": "Discussion sur l’API du Service Identité",
+ "Support for those using, running and writing other bridges": "Support pour les utilisateurs, administrateurs et développeurs de passerelles",
+ "Contributing code to Matrix and Riot": "Contribuer à Matrix et Riot",
+ "Dev chat for the Riot/Web dev team": "Forum pour les discussions sur les développements de Riot/Web",
+ "Dev chat for the Dendrite dev team": "Forum pour les discussion sur les développements de Dendrite",
+ "Co-ordination for Riot/Web translators": "Coordination des traducteurs de Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Beaucoup de salons existent déjà dans Matrix, liés à des réseaux existants (Slsck, IRC, Gitter etc) ou indépendants. Jetez un oeil au répertoire !",
+ "You have successfully set a password and an email address!": "Vous avez configuré un mot de passe et une adresse e-mail avec succès !",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Souvenez-vous que vous pourrez toujours définir une adresse e-mail dans la configuration utilisateur si vous changez d’avis."
+}
diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json
new file mode 100644
index 00000000..22c2de59
--- /dev/null
+++ b/src/i18n/strings/he.json
@@ -0,0 +1,199 @@
+{
+ "A new version of Riot is available.": "יצאה גרסה חדשה של Riot.",
+ "Add an email address above to configure email notifications": "הוסף כתובת דואר אלקטורני למעלה בכדי להגדיר התראות",
+ "Advanced notification settings": "הגדרות מתקדמות להתראות",
+ "All messages": "כל ההודעות",
+ "All messages (loud)": "כל ההודעות (צעקה)",
+ "All Rooms": "כל החדרים",
+ "All notifications are currently disabled for all targets.": "התראות מנוטרלות לכלל המערכת.",
+ "An error occurred whilst saving your email notification preferences.": "קרתה שגיאה בזמן שמירת הגדרות התראה באמצעות הדואר האלקטרוני.",
+ "Call invitation": "הזמנה לשיחה",
+ "Cancel": "ביטול",
+ "Cancel Sending": "ביטול שליחה",
+ "Can't update user notification settings": "לא ניתן לעדכן הגדרות התראה למשתמש",
+ "Changelog": "דו\"ח שינויים",
+ "Close": "סגור",
+ "Collapse panel": "סגור פאנל",
+ "Collecting app version information": "אוסף מידע על גרסת האפליקציה",
+ "Collecting logs": "אוסף לוגים",
+ "Create new room": "צור חדר חדש",
+ "Couldn't find a matching Matrix room": "לא נמצא חדר כזה ב Matrix",
+ "Custom Server Options": "הגדרות שרת מותאמות אישית",
+ "customServer_text": "אפשר להשתמש בהגדרות שרת מותאמות אישית בכדי להתחבר לשרתים אחרים באמצעות בחירת כתובת שרת בית שונה. זה יאפשר לך להשתמש ב Riot עם חשבון קיים ב Matrix אבל אל מול שרת בית שונה.
כמו כן אפשר להגדיר זהות מותאמת אישית אבל אז לא תהיה אפשרות להזמין משתמשים באמצעות כתובת אימייל, או להזמין את עצמך באמצעות כתובת האימייל.",
+ "delete the alias.": "מחיקת כינוי.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "מחק כינוי %(alias)s של החדר והסר את %(name)s מהרשימה?",
+ "Describe your problem here.": "תאר את הבעיה כאן.",
+ "Direct Chat": "שיחה ישירה",
+ "Directory": "ספרייה",
+ "Dismiss": "שחרר",
+ "Download this file": "הורד את הקובץ",
+ "Enable audible notifications in web client": "אפשר התראות קוליות בדפדפן",
+ "Enable desktop notifications": "אפשר התראות בשולחן העבודה",
+ "Enable email notifications": "אפשר התראות באמצעות הדואר האלקטרוני",
+ "Enable notifications for this account": "אפשר התראות לחשבון זה",
+ "Enable them now": "אפשר אותם כעת",
+ "Enter keywords separated by a comma:": "הכנס מילים מופרדות באמצעות פסיק:",
+ "Error": "שגיאה",
+ "Error saving email notification preferences": "שגיאה בעת שמירת הגדרות התראה באמצעות הדואר האלקטרוני",
+ "#example": "#דוגמא",
+ "Expand panel": "הרחב פנאל",
+ "Failed to": "נכשל ב",
+ "Failed to add tag %(tagName)s to room": "נכשל בעת הוספת תג %(tagName)s לחדר",
+ "Failed to change settings": "נכשל בעת שינוי הגדרות",
+ "Failed to forget room %(errCode)s": "נכשל בעת בקשה לשכוח חדר %(errCode)s",
+ "Failed to update keywords": "נכשל עדכון מילים",
+ "Failed to get protocol list from Home Server": "נכשל בעת נסיון קבלת רשימת פרוטוקולים משרת הבית",
+ "Failed to get public room list": "נכשלה קבלת רשימת חדרים ציבוריים",
+ "Failed to join the room": "הצטרפות לחדר נכשלה",
+ "Failed to remove tag %(tagName)s from room": "נכשל בעת נסיון הסרת תג %(tagName)s מהחדר",
+ "Failed to send report: ": "נכשל בעת שליחת דו\"ח: ",
+ "Failed to set direct chat tag": "נכשל בעת סימון תג לשיחה ישירה",
+ "Failed to set Direct Message status of room": "נכשל בעת סימון סטטוס הודעה ישירה של החדר",
+ "Favourite": "מועדף",
+ "Fetching third party location failed": "נסיון להביא מיקום צד שלישי נכשל",
+ "Files": "קבצים",
+ "Filter room names": "מיין לפי שמות חדרים",
+ "Forget": "שכח",
+ "Forward Message": "העבר הודעה",
+ " from room": " מחדר",
+ "Guests can join": "אורחים יכולים להצטרף",
+ "Guest users can't invite users. Please register to invite.": "משתמש אורח לא יכול להזמין משתמשים אחרים. נא להרשם בכדי להזמין.",
+ "Hide panel": "הסתר פנאל",
+ "I understand the risks and wish to continue": "אני מבין את הסיכונים אבל מבקש להמשיך",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "בכדי לנתח את הבעיות, ישלח דוח עם פרטי הבעיה. אם ברצונך רק לשלוח את שנאמר למעלה, נא הסר את הסימון:",
+ "Invite to this room": "הזמן לחדר זה",
+ "Keywords": "מילות מפתח",
+ "Leave": "לעזוב",
+ "Login": "התחבר",
+ "Loading bug report module": "טוען רכיב דיווח דו\"ח שגיאה",
+ "Low Priority": "עדיפות נמוכה",
+ "Members": "חברים",
+ "Mentions only": "הערות בלבד",
+ "Messages containing my display name": "הודעות המכילות את שם התצוגה שלי",
+ "Messages containing keywords": "הודעות המכילות מילות מפתח ",
+ "Messages containing my user name": "הודעות המכילות את שם המשתמש שלי",
+ "Messages in group chats": "הודעות בקבוצות השיחה",
+ "Messages in one-to-one chats": "הודעות בשיחות פרטיות",
+ "Messages sent by bot": "הודעות שנשלחו באמצעות בוט",
+ "more": "עוד",
+ "Mute": "השתק",
+ "No rooms to show": "אין חדרים להצגה",
+ "Noisy": "רועש",
+ "Notification targets": "יעדי התראה",
+ "Notifications": "התראות",
+ "Notify for all other messages/rooms": "התראה לכל שאר ההודעות/החדרים",
+ "Notify me for anything else": "התראה לי על כל דבר אחר",
+ "Off": "סגור",
+ "On": "דלוק",
+ "Operation failed": "פעולה נכשלה",
+ "Permalink": "קישור קבוע",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "נא תאר את הבאג. מה עשית? מה ציפית שיקרה? מה קרה בפועל?",
+ "Please describe the bug and/or send logs.": "נא תאר את הבאג ו/או שלח את הלוגים.",
+ "Please install Chrome or Firefox for the best experience.": "נא התקן כרום או פיירפוקס לשימוש מייטבי.",
+ "Please Register": "נא להרשם",
+ "powered by Matrix": "מופעל ע\"י Matrix",
+ "Quote": "ציטוט",
+ "Reject": "דחה",
+ "Remove %(name)s from the directory?": "הסר את %(name)s מהרשימה?",
+ "Remove": "הסר",
+ "remove %(name)s from the directory.": "הסר את %(name)s מהרשימה.",
+ "Remove from Directory": "הסר מהרשימה",
+ "Report a bug": "דווח על שגיאה",
+ "Resend": "שלח מחדש",
+ "Riot Desktop on %(platformName)s": "Riot לשולחן העבודה על גבי %(platformName)s",
+ "Riot does not know how to join a room on this network": "Riot אינו יודע כיצד להצטרף לחדר ברשת זו",
+ "Riot is not supported on mobile web. Install the app?": "Riot לא נתמך באמצעות דפדפן במכשיר הסלולארי. האם ברצונך להתקין את האפליקציה?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot משתמש במספר רב של אפשרויות מתקדמות בדפדפן, חלק מהן לא זמינות או בשלבי נסיון בדפדפן שבשימושך כרגע.",
+ "Room directory": "רשימת חדרים",
+ "Room not found": "חדר לא נמצא",
+ "Search": "חפש",
+ "Search…": "חפש…",
+ "Search for a room": "חפש חדר",
+ "Send": "שלח",
+ "Send logs": "שלח לוגים",
+ "Settings": "הגדרות",
+ "Source URL": "כתובת אתר המקור",
+ "Sorry, your browser is not able to run Riot.": "מצטערים, הדפדפן שלך הוא אינו יכול להריץ את Riot.",
+ "Start chat": "התחל שיחה",
+ "The Home Server may be too old to support third party networks": "שרת הבית ישן ואינו יכול לתמוך ברשתות צד שלישי",
+ "There are advanced notifications which are not shown here": "ישנן התראות מתקדמות אשר אינן מוצגות כאן",
+ "The server may be unavailable or overloaded": "השרת אינו זמין או עמוס",
+ "This Room": "החדר הזה",
+ "This room is inaccessible to guests. You may be able to join if you register.": "החדר אינו זמין לאורחים. יש באפשרותך להצטרף רק אחרי רישום.",
+ " to room": " אל חדר",
+ "Unable to fetch notification target list": "לא ניתן לאחזר רשימת יעדי התראה",
+ "Unable to join network": "לא ניתן להצטרף לרשת",
+ "Unable to look up room ID from server": "לא ניתן לאתר מזהה חדר על השרת",
+ "Unavailable": "לא זמין",
+ "Unhide Preview": "הצג מחדש תצוגה מקדימה",
+ "Unknown device": "מכשיר לא ידוע",
+ "unknown error code": "קוד שגיאה לא מוכר",
+ "Unnamed room": "חדר ללא שם",
+ "Update": "עדכון",
+ "Uploaded on %(date)s by %(user)s": "עודכן ב %(date)s ע\"י %(user)s",
+ "Uploading report": "מעדכן דוח",
+ "View Decrypted Source": "הצג מקור מוצפן",
+ "View Source": "הצג מקור",
+ "What's New": "מה חדש",
+ "What's new?": "מה חדש?",
+ "Waiting for response from server": "ממתין לתשובה מהשרת",
+ "When I'm invited to a room": "מתי אני מוזמן לחדר",
+ "World readable": "העולם קריא",
+ "You cannot delete this image. (%(code)s)": "אי אפשר למחוק את התמונה. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "לא ניתן למחוק הודעה זו. (%(code)s)",
+ "You are not receiving desktop notifications": "אתה לא מקבל התראות משולחן העבודה",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "אתה משתמש ב Riot כאורח. הרשם או התחבר בכדי לגשת לחדרים נוספים!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "יתכן כי בצעת את ההגדרות בצד לקוח ולא ב Riot. לא תוכל לווסת אותם ב Riot אבל הם עדיין תקפים",
+ "Sunday": "ראשון",
+ "Monday": "שני",
+ "Tuesday": "שלישי",
+ "Wednesday": "רביעי",
+ "Thursday": "חמישי",
+ "Friday": "שישי",
+ "Saturday": "שבת",
+ "Today": "היום",
+ "Yesterday": "אתמול",
+ "OK": "בסדר",
+ "You need to be using HTTPS to place a screen-sharing call.": "עליך להשתמש ב HTTPS בכדי לבצע שיחה משותפת.",
+ "Welcome page": "מסך פתיחה",
+ "Welcome to Riot.im": "ברוכים הבאים ל Riot.im",
+ "Search the room directory": "חפש ברשימת החדרים",
+ "Chat with Riot Bot": "שיחה עם Riot בוט",
+ "Get started with some tips from Riot Bot!": "התחל באמצעות מספר טיפים מהבוט של Riot!",
+ "General discussion about Matrix and Riot": "דיון כללי על Matrix ו Riot",
+ "Discussion of all things Matrix!": "דיון על כל הדברים הקשורים ל Matrix!",
+ "Riot/Web & Desktop chat": "Riot/Web & צ'ט שולחן עבודה",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/iOS & שיחה עם matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Android & צ'ט matrix-android-sdk",
+ "Matrix technical discussions": "פורום טכני של Matrix",
+ "Running Matrix services": "הרץ את שירותי ה Matrix",
+ "Community-run support for Synapse": "תמיכה בקהילה של Synapse",
+ "Admin support for Dendrite": "תמיכת מנהל מערכת עבור Dendrite",
+ "Announcements about Synapse releases": "הודעות לגבי גרסאות Synapse",
+ "Support for those using and running matrix-appservice-irc": "תמיכה באלו המשתמשים ב matrix-appservice-irc",
+ "Building services on Matrix": "בניית שירותים על גבי ה Matrix",
+ "Support for those using the Matrix spec": "תמיכה באלו המשתמשים בהגדרות ה Matrix",
+ "Design and implementation of E2E in Matrix": "תכנון וביצוע קצה לקצה ב Matrix",
+ "Implementing VR services with Matrix": "מימוש שירותי VR ב Matrix",
+ "Implementing VoIP services with Matrix": "מימוש Voip ב Matrix",
+ "Discussion of the Identity Service API": "דיון על שירות זהויות",
+ "Support for those using, running and writing other bridges": "שירות לכל אותם אלו המשתמשים, מריצים וכותבים חיבורים נוספים",
+ "Contributing code to Matrix and Riot": "תרומת קוד ל Matrix ו Riot",
+ "Dev chat for the Riot/Web dev team": "שיחה עם המפתחים עבור ה קבוצת הפיתוח של Riot/Web",
+ "Dev chat for the Dendrite dev team": "שיחת מפתחים עבור Dendrite",
+ "Co-ordination for Riot/Web translators": "תאום למתרגמי ה Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "הרבה חדרים כבר קיימים ב Matrix ומקושרים לרשתות קיימות (Slack, IRC, Gitter וכו') או עצמאיים. בדוק את הספרייה!",
+ "Failed to change password. Is your password correct?": "נכשל בעת שינוי סיסמא, האם הסיסמא אינה שגויה?",
+ "You have successfully set a password!": "שינוי סיסמא בוצע בהצלחה!",
+ "You can now return to your account after signing out, and sign in on other devices.": "תוכל עתה לחזור לחשבון שלך רק אחרי התנתקות וחיבור מחדש לחשבון.",
+ "Continue": "המשך",
+ "Please set a password!": "נא להגדיר סיסמא!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "זה יאפשר לך לחזור לחשבונך אחרי התנתקות ולהתחבר באמצעות התקנים אחרים.",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s באמצעות הדפדפן %(browserName)s על גבי %(osName)s",
+ "Safari and Opera work too.": " ספארי ו אופרה עובדים גם כן.",
+ "Drop here %(toAction)s": "זרוק כאן %(toAction)s",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "התראה על מילות המפתח הבאות עוקבת אחר החוקים שאינם יכולים להיות מוצגים כאן:",
+ "Redact": "אדום",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "באמצעות הדפדפן הנוכחי שלך המראה של האפליקציה יכול להיות שגוי לחלוטין וחלק מהאפשרויות לא תתפקדנה. אם תרצה לנסות בכל זאת תוכל אבל אז הסיכון חל עליך!",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "צ'ט מוצפן & ושת\"פ נעשה ע\"י ה [matrix]"
+}
diff --git a/src/i18n/strings/hi.json b/src/i18n/strings/hi.json
new file mode 100644
index 00000000..f8bfb088
--- /dev/null
+++ b/src/i18n/strings/hi.json
@@ -0,0 +1,8 @@
+{
+ "A new version of Riot is available.": "रायट के एक नया वर्शन उपलब्ध है।",
+ "All messages": "सारे संदेश",
+ "All Rooms": "सारे कमरे",
+ "Please set a password!": "कृपया एक पासवर्ड सेट करें!",
+ "Continue": "आगे बढ़ें",
+ "You have successfully set a password and an email address!": "आपने सफलतापूर्वक एक पासवर्ड और एक ईमेल एड्रेस सेट कर लिया है!"
+}
diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json
new file mode 100644
index 00000000..a08a8b86
--- /dev/null
+++ b/src/i18n/strings/hu.json
@@ -0,0 +1,202 @@
+{
+ "Add an email address above to configure email notifications": "E-mail értesítés beállításához írd be az e-mail címed",
+ "Advanced notification settings": "Haladó értesítési beállítások",
+ "All messages": "Minden üzenet",
+ "All messages (loud)": "Minden üzenet (hangos)",
+ "All notifications are currently disabled for all targets.": "Minden céleszközön minden értesítés tiltva van.",
+ "An error occurred whilst saving your email notification preferences.": "Hiba történt az e-mail értesítés beállításánál.",
+ "Call invitation": "Hívás meghívó",
+ "Cancel Sending": "Küldés megszakítása",
+ "Can't update user notification settings": "Nem sikerül frissíteni az értesítési beállításokat",
+ "Close": "Bezár",
+ "Create new room": "Új szoba létrehozása",
+ "Couldn't find a matching Matrix room": "Nem található a keresett Matrix szoba",
+ "Custom Server Options": "Egyedi szerver beállítások",
+ "delete the alias.": "becenév törlése.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Törlöd a(z) %(alias)s szobát és kiveszed a könyvtárból ezt: %(name)s?",
+ "Direct Chat": "Közvetlen csevegés",
+ "Directory": "Könyvtár",
+ "Dismiss": "Eltűntet",
+ "Download this file": "Fájl letöltése",
+ "Drop here %(toAction)s": "%(toAction)s -t húzd ide",
+ "Enable audible notifications in web client": "Hallható értesítések engedélyezése a webes kliensben",
+ "Enable desktop notifications": "Asztali értesítések engedélyezése",
+ "Enable email notifications": "E-mail értesítések engedélyezése",
+ "Enable notifications for this account": "Értesítések engedélyezése a fiókhoz",
+ "Enable them now": "Engedélyezés most",
+ "Enter keywords separated by a comma:": "Kulcsszavak vesszővel elválasztva:",
+ "Error": "Hiba",
+ "Error saving email notification preferences": "Hiba email értesítés beállításának mentésénél",
+ "#example": "#példa",
+ "Failed to": "Nem lehet",
+ "Failed to add tag %(tagName)s to room": "Nem lehet a címkét hozzáadni a szobához: %(tagName)s",
+ "Failed to change settings": "Nem lehet a beállítást megváltoztatni",
+ "Failed to forget room %(errCode)s": "Nem lehet eltávolítani a szobát: %(errCode)s",
+ "Failed to update keywords": "Nem lehet a kulcsszavakat frissíteni",
+ "Failed to get protocol list from Home Server": "Nem lehet a protokoll listát lekérni a Saját szerverről",
+ "Failed to get public room list": "Nem lehet lekérdezni a nyílt szobák listáját",
+ "Failed to join the room": "Nem lehet csatlakozni a szobához",
+ "Failed to remove tag %(tagName)s from room": "Nem lehet törölni a(z) %(tagName)s címkét a szobáról",
+ "Failed to set direct chat tag": "Nem lehet a címkét beállítani a közvetlen beszélgetéshez",
+ "Failed to set Direct Message status of room": "Nem lehet beállítani a Közvetlen beszélgetés státuszt a szobához",
+ "Favourite": "Kedvenc",
+ "Fetching third party location failed": "Nem sikerült lekérdezni a harmadik felet",
+ "Files": "Fájlok",
+ "Filter room names": "Szoba nevek szűrése",
+ "Forget": "Elfelejt",
+ " from room": " szobából",
+ "Guests can join": "Vendégek csatlakozhatnak",
+ "Guest users can't invite users. Please register to invite.": "Vendég felhasználó nem küldhet meghívót. Kérlek regisztrálj meghívó küldéshez.",
+ "Invite to this room": "Meghívás a szobába",
+ "Keywords": "Kulcsszavak",
+ "Leave": "Elhagy",
+ "Low Priority": "Alacsony priorítás",
+ "Members": "Résztvevők",
+ "Mentions only": "Csak ha megemlítenek",
+ "Messages containing my display name": "Az üzenet tartalmazza a nevem",
+ "Messages containing my user name": "Az üzenet tartalmazza a felhasználói nevem",
+ "Messages in group chats": "Üzenetek a csoportszobában",
+ "Messages in one-to-one chats": "Üzenetek közvetlen beszélgetésekben",
+ "Messages sent by bot": "Botok által küldött üzenetek",
+ "more": "további",
+ "Mute": "Elnémít",
+ "No rooms to show": "Nincs megjeleníthető szoba",
+ "Noisy": "Hangos",
+ "Notification targets": "Értesítések célpontja",
+ "Notifications": "Értesítések",
+ "Notify for all other messages/rooms": "Értesítés minden más üzenethez/szobához",
+ "Safari and Opera work too.": "Safarival és Operaval is működik.",
+ "Collapse panel": "Panel bezárása",
+ "customServer_text": "Egyedi Matrix szervert használhatsz a Saját szerver URL beállításával. Ezzel meglévő Matrix fiókot használhatsz Riot klienssel és egyedi szerverrel.
Beállíthatsz egyedi \"identity\" szervert de akkor nem tudsz e-maillel meghívni felhasználót és téged sem tudnak meghívni e-maillel.",
+ "Expand panel": "Panel kinyitása",
+ "I understand the risks and wish to continue": "Megértettem a kockázatot és folytatom",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "A kulcsszavakhoz tartozó értesítések olyan szabályokat követnek amiket nem lehet itt megjeleníteni:",
+ "Notify me for anything else": "Értesíts minden egyéb esetben",
+ "Off": "Ki",
+ "On": "Be",
+ "Operation failed": "Művelet sikertelen",
+ "Permalink": "Állandó hivatkozás",
+ "Please install Chrome or Firefox for the best experience.": "A legjobb élmény érdekében telepíts Chromeot vagy Firefoxot.",
+ "Please Register": "Regisztrálj",
+ "powered by Matrix": "Matrixon alapul",
+ "Quote": "Idézet",
+ "Redact": "Szerkeszt",
+ "Reject": "Elutasít",
+ "Remove %(name)s from the directory?": "Törlöd a %(name)s szobát a listából?",
+ "Remove": "Töröl",
+ "remove %(name)s from the directory.": "%(name)s szoba törlése a listából.",
+ "Remove from Directory": "Törlés a szobák listájából",
+ "Resend": "Újraküld",
+ "Riot does not know how to join a room on this network": "Riot nem tudja, hogy csatlakozzon ehhez a szobához ezen a hálózaton",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot sok haladó képességét használja a böngészőnek amik közül lehet, hogy nem mind érhető el a most használt böngészőben vagy még csak kísérleti jellegű.",
+ "Room directory": "Szobák listája",
+ "Room not found": "A szoba nem található",
+ "Search for a room": "Szoba keresése",
+ "Settings": "Beállítások",
+ "Source URL": "Forrás URL",
+ "Sorry, your browser is not able to run Riot.": "Elnézést, a böngésződ nem képes futtatni a Riotot.",
+ "Start chat": "Csevegés indítása",
+ "The Home Server may be too old to support third party networks": "A Saját szerver lehet, hogy túl régi ahhoz, hogy más hálózatokhoz tudjon kapcsolódni",
+ "There are advanced notifications which are not shown here": "Vannak haladó értesítések amik itt nincsenek megjelenítve",
+ "The server may be unavailable or overloaded": "A szerver nem érhető el vagy túl van terhelve",
+ "This room is inaccessible to guests. You may be able to join if you register.": "A szoba vendégek számára elérhetetlen. Csak regisztráció után tudsz csatlakozni.",
+ " to room": " szobába",
+ "Unable to fetch notification target list": "Nem sikerült letölteni az értesítési célok listáját",
+ "Unable to join network": "Nem sikerült kapcsolódni a hálózathoz",
+ "Unable to look up room ID from server": "Nem lehet lekérdezni a szoba ID-ját a szervertől",
+ "Unhide Preview": "Előkép felfedése",
+ "unknown error code": "ismeretlen hiba kód",
+ "Unnamed room": "Név nélküli szoba",
+ "Uploaded on %(date)s by %(user)s": "Feltöltés: %(date)s, %(user)s",
+ "View Decrypted Source": "Visszafejtett forrás megjelenítése",
+ "View Source": "Forrás megjelenítése",
+ "When I'm invited to a room": "Amikor meghívtak a szobába",
+ "World readable": "Mindenki olvashatja",
+ "You cannot delete this image. (%(code)s)": "Nem törölheted ezt a képet. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Nem törölheted ezt az üzenetet. (%(code)s)",
+ "You are not receiving desktop notifications": "Nem fogadsz asztali értesítéseket",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Valószínűleg Riottól eltérő klienssel állítottad be. Riotból nem állítható de érvényben van",
+ "Sunday": "Vasárnap",
+ "Monday": "Hétfő",
+ "Tuesday": "Kedd",
+ "Wednesday": "Szerda",
+ "Thursday": "Csütörtök",
+ "Friday": "Péntek",
+ "Saturday": "Szombat",
+ "Today": "Ma",
+ "Yesterday": "Tegnap",
+ "Welcome page": "Üdvözlő oldal",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "A jelenlegi bőngésződdel teljesen hibás lehet az alkalmazás kinézete és bizonyos funkciók, ha nem az összes, nem fog működni. Ha mindenképpen ki akarod próbálni, folytathatod de egyedül vagy minden felbukkanó problémával!",
+ "Messages containing keywords": "Az üzenet kulcsszavakat tartalmaz",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s alkalmazás %(browserName)s böngészőn %(osName)s rendszeren",
+ "A new version of Riot is available.": "Új verzió érhető el a Riot-ból.",
+ "All Rooms": "Minden szoba",
+ "Cancel": "Mégse",
+ "Changelog": "Változások",
+ "Collecting app version information": "Alkalmazás verzió információk összegyűjtése",
+ "Collecting logs": "Naplók összegyűjtése",
+ "Describe your problem here.": "Írd le a problémád itt.",
+ "Failed to send report: ": "A jelentést nem lehetett elküldeni: ",
+ "Forward Message": "Üzenet továbbküldése",
+ "Hide panel": "Panel elrejtése",
+ "Loading bug report module": "Hibabejelentő modul betöltése",
+ "Please describe the bug and/or send logs.": "Írd le a hibát és/vagy küld el a naplókat.",
+ "Report a bug": "Hiba bejelentése",
+ "Riot Desktop on %(platformName)s": "Riot Desktop ezen: %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot nem támogatott mobil webböngészőn. Telepíted az alkalmazást?",
+ "Search": "Keresés",
+ "Search…": "Keresés…",
+ "Send": "Küld",
+ "Send logs": "Naplók elküldése",
+ "This Room": "Ez a szoba",
+ "Unavailable": "Elérhetetlen",
+ "Unknown device": "Ismeretlen eszköz",
+ "Update": "Frissítés",
+ "Uploading report": "Jelentés feltöltése",
+ "What's New": "Mik az újdonságok",
+ "What's new?": "Mik az újdonságok?",
+ "Waiting for response from server": "Válasz várása a szervertől",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Vendégként használod a Riot-ot. Regisztrálj vagy jelentkezz be további szobák és lehetőségek eléréséhez!",
+ "OK": "Rendben",
+ "You need to be using HTTPS to place a screen-sharing call.": "HTTPS-t kell használnod hogy képernyőmegosztásos hívást kezdeményezz.",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "A problémák diagnosztizálása érdekében erről a kliensről a hibajelentésben naplók lesznek elküldve. Ha csak az alábbi szöveget szeretnéd elküldeni akkor ezt ne jelöld meg:",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Írd le a hibát. Mit csináltál? Mi az amit szerettél volna ha történik? Ezzel szemben mi az ami történt?",
+ "Login": "Bejelentkezés",
+ "Welcome to Riot.im": "Üdvözlünk a Riot.im-en",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralizált, titkosított csevegés és kollaboráció [matrix] alapokon",
+ "Search the room directory": "Keresés a szobák jegyzékében",
+ "Chat with Riot Bot": "Csevegés a Riot Robottal",
+ "Get started with some tips from Riot Bot!": "Kezdd el a Riot használatát a Riot Robot tippjei segítségével!",
+ "General discussion about Matrix and Riot": "Általános beszélgetések a Matrixról és a Riotról",
+ "Discussion of all things Matrix!": "Beszélgetések mindenről, ami a Matrixhoz kapcsolódik!",
+ "Riot/Web & Desktop chat": "Riot/Web és asztali csevegés",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/iOS és matrix-ios-sdk csevegés",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Android és matrix-android-sdk csevegés",
+ "Matrix technical discussions": "Technikai jellegű beszélgetések a Matrixról",
+ "Community-run support for Synapse": "Közösségi támogatás a Synapse-hez",
+ "Admin support for Dendrite": "Adminisztrációs támogatás a Dendrite-hoz",
+ "Announcements about Synapse releases": "Bejelentések a Synapse kiadásairól",
+ "Running Matrix services": "Matrixszolgáltatások működtetése",
+ "Support for those using and running matrix-appservice-irc": "Támogatás a matrix-appservice-irc használatáról és működtetéséről",
+ "Building services on Matrix": "Szolgáltatások fejlesztése a Matrixra",
+ "Support for those using the Matrix spec": "Támogatás a Matrix specifikáció használatáról",
+ "Design and implementation of E2E in Matrix": "A végponttól végpontig történő titkosítás (E2E) tervezése és implementációja a Matrixban",
+ "Implementing VR services with Matrix": "A Matrixszal együttműködő virtuális valóság (VR) szolgáltatások implementációja",
+ "Implementing VoIP services with Matrix": "A Matrixszal együttműködő VoIP szolgáltatások implementációja",
+ "Discussion of the Identity Service API": "Beszélgetések az Identity Service API-ról",
+ "Support for those using, running and writing other bridges": "Támogatás egyéb hídak használáról, működtetéséről és fejlesztéséről",
+ "Contributing code to Matrix and Riot": "Hozzájárulás a Matrix és Riot programkódjának fejlesztéséhez",
+ "Dev chat for the Riot/Web dev team": "Csevegés a Riot/Web fejlesztői csapatával fejlesztőknek",
+ "Dev chat for the Dendrite dev team": "Csevegés a Dendrite fejlesztői csapatával fejlesztőknek",
+ "Co-ordination for Riot/Web translators": "Egyeztetés a Riot/Web fordítóival",
+ "Failed to change password. Is your password correct?": "Nem sikerült megváltoztatni a jelszót. Helyesen írtad be a jelszavadat?",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Már sok létező szoba van a Matrixon, melyek más hálózatokkal vannak összekapcsolva (Slack, IRC, Gitter stb.) vagy függetlenek. Látogasd meg a szobajegyzéket!",
+ "You have successfully set a password!": "Sikeresen állítottál be jelszót!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Most már visszatérhetsz a fiókodhoz kijelentkezés után, és más eszközökkel is be tudsz jelentkezni.",
+ "Continue": "Folytatás",
+ "Please set a password!": "Kérlek, állíts be egy jelszót!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Ezzel visszatérhetsz kijelentkezés után a fiókodhoz és más eszközökkel is be tudsz jelentkezni.",
+ "(HTTP status %(httpStatus)s)": "(HTTP állapot %(httpStatus)s)",
+ "You have successfully set a password and an email address!": "Sikeresen beállítottad a jelszavad és e-mail címed!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Ha meggondolod magad, bármikor beállíthatod az e-mail címed a felhasználói beállításoknál."
+}
diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/src/i18n/strings/id.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json
new file mode 100644
index 00000000..8dcc2984
--- /dev/null
+++ b/src/i18n/strings/it.json
@@ -0,0 +1,65 @@
+{
+ "Safari and Opera work too.": "Anche Safari e Opera funzionano.",
+ "A new version of Riot is available.": "È disponibile una nuova versione di Riot.",
+ "Add an email address above to configure email notifications": "Specifica un indirizzo email per configurazione le notifiche via email",
+ "Advanced notification settings": "Impostazioni notifiche avanzate",
+ "All messages": "Tutti i messaggi",
+ "All messages (loud)": "Tutti i messaggi (rumoroso)",
+ "All Rooms": "Tutte le stanze",
+ "An error occurred whilst saving your email notification preferences.": "È avvenuto un errore durante il salvataggio delle tue preferenze sulle notifiche email.",
+ "Call invitation": "Invito ad una chiamata",
+ "Cancel": "Annulla",
+ "Cancel Sending": "Annulla invio",
+ "Can't update user notification settings": "Impossibile aggiornare le impostazioni di notifica dell'utente",
+ "Changelog": "Cambiamenti",
+ "Close": "Chiudi",
+ "Collapse panel": "Riduci pannello",
+ "Collecting app version information": "Raccolta delle informazioni sulla versione dell'applicazione",
+ "Collecting logs": "Raccolta del registro",
+ "Create new room": "Crea una nuova stanza",
+ "Couldn't find a matching Matrix room": "Impossibile trovare una stanza Matrix corrispondente",
+ "Custom Server Options": "Opzioni server personale",
+ "customServer_text": "Puoi utilizzare un server personale per entrare in altri server Matrix specificando un diverso indirizzo per il server Home. Questo ti permetterà di usare Riot con un account Matrix già esistente su un altro server.
Puoi anche specificare un diverso server di identità ma non sarai in grado di invitare utenti o di essere invitato tramite indirizzo email.",
+ "delete the alias.": "Elimina gli alias.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Eliminare l'alias %(alias)s e rimuovere %(name)s dalla lista?",
+ "Describe your problem here.": "Descrivi qui il tuo problema.",
+ "Direct Chat": "Chat diretta",
+ "Directory": "Lista",
+ "Dismiss": "Scarta",
+ "Download this file": "Scarica questo file",
+ "Enable audible notifications in web client": "Abilita notifiche audio nel client Web",
+ "Enable desktop notifications": "Abilita le notifiche desktop",
+ "Enable email notifications": "Abilita le notifiche email",
+ "Enable notifications for this account": "Abilita le notifiche per questo account",
+ "Enable them now": "Abilitale adesso",
+ "Enter keywords separated by a comma:": "Inserisci le parole chiave separate da virgole:",
+ "Error": "Errore",
+ "Error saving email notification preferences": "Errore nel salvataggio delle preferenze di notifica email",
+ "#example": "#esempio",
+ "Expand panel": "Espandi il pannello",
+ "Failed to": "Non si è riuscito a",
+ "Failed to add tag %(tagName)s to room": "Non si è riuscito ad aggiungere l'etichetta %(tagName)s alla stanza",
+ "Failed to change settings": "Non si è riuscito ad aggiornare le impostazioni",
+ "Failed to update keywords": "Non si è riuscito ad aggiornare le parole chiave",
+ "Failed to get protocol list from Home Server": "Non si è riuscito ad ottenere la lista protocollo dal server Home",
+ "Failed to get public room list": "Non si è riuscito ad ottenere la lista delle stanze pubbliche",
+ "Failed to join the room": "Non si è riuscito a entrare nella stanza",
+ "Failed to remove tag %(tagName)s from room": "Non si è riuscito a rimuovere il tag %(tagName)s dalla stanza",
+ "Failed to send report: ": "Non si è riuscito ad inviare il resoconto: ",
+ "Failed to set direct chat tag": "Non si è riuscito a impostare l'etichetta di chat diretta",
+ "Failed to set Direct Message status of room": "Non si è riuscito ad impostare lo stato di Messaggio Diretto alla stanza",
+ "Favourite": "Preferito",
+ "Files": "File",
+ "Filter room names": "Filtra i nomi delle stanze",
+ "Forget": "Dimentica",
+ "Forward Message": "Inoltra messaggio",
+ " from room": " dalla stanza",
+ "Guests can join": "Gli ospiti sono ammessi",
+ "Guest users can't invite users. Please register to invite.": "Gli utenti ospite non possono invitare altri utenti. Registrati per invitare.",
+ "Hide panel": "Nascondi pannello",
+ "I understand the risks and wish to continue": "Sono consapevole dei rischi e vorrei continuare",
+ "Invite to this room": "Invita a entrare in questa stanza",
+ "Keywords": "Parole chiave",
+ "Leave": "Abbandona",
+ "Login": "Entra"
+}
diff --git a/src/i18n/strings/ko.json b/src/i18n/strings/ko.json
new file mode 100644
index 00000000..862fbc0a
--- /dev/null
+++ b/src/i18n/strings/ko.json
@@ -0,0 +1,202 @@
+{
+ "A new version of Riot is available.": "라이엇의 새 버전을 사용하실 수 있어요.",
+ "Add an email address above to configure email notifications": "이메일 알림을 설정하기 위해 이메일 주소를 추가해주세요",
+ "Advanced notification settings": "고급 알림 설정",
+ "All messages": "모든 메시지",
+ "All messages (loud)": "모든 메시지 (크게)",
+ "All Rooms": "모든 방",
+ "All notifications are currently disabled for all targets.": "현재 모든 알림이 모든 상대에게서 꺼졌어요.",
+ "An error occurred whilst saving your email notification preferences.": "이메일 알림을 설정하다가 오류가 일어났어요.",
+ "Call invitation": "전화가 왔어요",
+ "Cancel": "취소",
+ "Cancel Sending": "보내기 취소",
+ "Can't update user notification settings": "사용자 알림 설정을 갱신할 수 없어요",
+ "Changelog": "바뀐 점",
+ "Close": "닫기",
+ "Collapse panel": "패널 접기",
+ "Collecting app version information": "앱 버전 정보를 수집하는 중",
+ "Collecting logs": "로그 수집 중",
+ "Create new room": "새 방 만들기",
+ "Couldn't find a matching Matrix room": "일치하는 매트릭스 방을 찾을 수 없어요",
+ "Custom Server Options": "사용자 지정 서버 설정",
+ "delete the alias.": "가명을 지울게요.",
+ "Describe your problem here.": "여기에 일어난 문제를 적어주세요.",
+ "Direct Chat": "직접 이야기하기",
+ "Directory": "목록",
+ "Dismiss": "없애기",
+ "Download this file": "이 파일 받기",
+ "Enable desktop notifications": "데스크탑에서 알림 받기",
+ "Enable email notifications": "이메일로 알림 받기",
+ "Enable notifications for this account": "이 계정의 알림 받기",
+ "Error": "오류",
+ "Error saving email notification preferences": "이메일 알림을 설정하는데 오류가 일어났어요",
+ "#example": "#예",
+ "Expand panel": "확장 패널",
+ "Forget": "잊기",
+ "Hide panel": "패널 숨기기",
+ "Guest users can't invite users. Please register to invite.": "손님은 사용자를 초대할 수 없어요. 초대하려면 계정을 등록해주세요.",
+ "I understand the risks and wish to continue": "위험할 수 있는 걸 알고 계속하기를 바라요",
+ "Invite to this room": "이 방에 초대하기",
+ "Leave": "떠나기",
+ "Login": "로그인",
+ "Loading bug report module": "오류 보고 모듈을 불러오는 중",
+ "Low Priority": "낮은 우선순위",
+ "Members": "구성원",
+ "more": "더 보기",
+ "Mute": "알림 끄기",
+ "No rooms to show": "보여드릴 방이 없어요",
+ "Notification targets": "알림 대상",
+ "Notifications": "알림",
+ "Off": "끄기",
+ "On": "켜기",
+ "Permalink": "고유주소",
+ "Please describe the bug and/or send logs.": "오류를 적어주시거나 로그를 보내주세요.",
+ "Please Register": "계정을 등록해주세요",
+ "powered by Matrix": "매트릭스의 지원을 받고 있어요",
+ "Quote": "인용하기",
+ "Redact": "지우기",
+ "Reject": "거절하기",
+ "Remove %(name)s from the directory?": "목록에서 %(name)s을 지우시겠어요?",
+ "Remove": "지우기",
+ "remove %(name)s from the directory.": "목록에서 %(name)s을 지웠어요.",
+ "Remove from Directory": "목록에서 지우기",
+ "Report a bug": "오류 보고하기",
+ "Resend": "다시 보내기",
+ "Riot Desktop on %(platformName)s": "%(platformName)s에서 라이엇 데스크탑",
+ "Riot is not supported on mobile web. Install the app?": "라이엇은 모바일 사이트를 지원하지 않아요. 앱을 설치하시겠어요?",
+ "Room directory": "방 목록",
+ "Room not found": "방을 찾지 못했어요",
+ "Search": "찾기",
+ "Search…": "찾기…",
+ "Search for a room": "방에서 찾기",
+ "Send": "보내기",
+ "Send logs": "로그 보내기",
+ "Settings": "설정",
+ "Source URL": "출처 주소",
+ "Sorry, your browser is not able to run Riot.": "죄송해요. 브라우저에서 라이엇을 켤 수가 없어요.",
+ "Start chat": "이야기하기",
+ "This Room": "방",
+ "Unavailable": "이용할 수 없음",
+ "Unknown device": "알 수 없는 장치",
+ "unknown error code": "알 수 없는 오류 코드",
+ "Unnamed room": "이름없는 방",
+ "Update": "업데이트",
+ "Uploading report": "보고를 올리는 중",
+ "What's New": "새로운 점",
+ "What's new?": "새로운 점은?",
+ "Waiting for response from server": "서버에서 응답을 기다리는 중",
+ "You cannot delete this image. (%(code)s)": "이 사진을 지우실 수 없어요. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "이 메시지를 지우실 수 없어요. (%(code)s)",
+ "You are not receiving desktop notifications": "데스크탑 알림을 받지 않고 있어요",
+ "Sunday": "일요일",
+ "Monday": "월요일",
+ "Tuesday": "화요일",
+ "Wednesday": "수요일",
+ "Thursday": "목요일",
+ "Friday": "금요일",
+ "Saturday": "토요일",
+ "Today": "오늘",
+ "Yesterday": "어제",
+ "OK": "알았어요",
+ "Welcome page": "환영 화면",
+ "Welcome to Riot.im": "라이엇에 오신 걸 환영해요",
+ "Chat with Riot Bot": "Riot 봇과 이야기하기",
+ "You have successfully set a password!": "비밀번호를 설정했어요!",
+ "Continue": "게속하기",
+ "Please set a password!": "비밀번호를 설정해주세요!",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(osName)s의 %(browserName)s을 통한 %(appName)s",
+ "Safari and Opera work too.": "사파리와 오페라에서도 작동해요.",
+ "customServer_text": "사용자 지정 서버 설정에서 다른 홈 서버 주소를 지정해 다른 매트릭스 서버에 로그인할 수 있어요. 이를 통해 라이엇과 다른 홈 서버의 기존 매트릭스 계정을 함께 쓸 수 있죠.
사용자 지정 ID 서버를 설정할 수도 있지만 이메일 주소로 사용자를 초대하거나 초대받을 수는 없답니다.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "방 가명 %(alias)s 을 지우고 목록에서 %(name)s를 지우시겠어요?",
+ "Drop here %(toAction)s": "여기에 놓아주세요 %(toAction)s",
+ "Enable audible notifications in web client": "웹 클라이언트에서 알림 소리 켜기",
+ "Enable them now": "지금 켜기",
+ "Enter keywords separated by a comma:": "키워드를 쉼표로 구분해 입력해주세요:",
+ "Failed to": "실패했어요",
+ "Failed to add tag %(tagName)s to room": "방에 %(tagName)s로 지정하지 못했어요",
+ "Failed to change settings": "설정을 바꾸지 못했어요",
+ "Failed to forget room %(errCode)s": "방 %(errCode)s를 잊지 못했어요",
+ "Failed to update keywords": "키워드를 갱신하지 못했어요",
+ "Failed to get protocol list from Home Server": "홈 서버에서 프로토콜 목록을 얻지 못했어요",
+ "Failed to get public room list": "공개한 방 목록을 얻지 못했어요",
+ "Failed to join the room": "방에 들어가지 못했어요",
+ "Failed to remove tag %(tagName)s from room": "방에서 %(tagName)s 지정을 지우지 못했어요",
+ "Failed to send report: ": "보고를 보내지 못했어요: ",
+ "Failed to set direct chat tag": "직접 이야기 지정을 설정하지 못했어요",
+ "Failed to set Direct Message status of room": "방의 쪽지 상태를 설정하지 못했어요",
+ "Favourite": "즐겨찾기",
+ "Fetching third party location failed": "타사 위치를 불러오지 못했어요",
+ "Files": "파일",
+ "Filter room names": "방 이름 거르기",
+ "Forward Message": "메시지 전달",
+ " from room": " 방에서",
+ "Guests can join": "손님이 들어올 수 있어요",
+ "(HTTP status %(httpStatus)s)": "(HTTP 상태 %(httpStatus)s)",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "문제를 진단하기 위해서, 이 클라이언트의 로그를 오류 보고서와 같이 보낼 거에요. 위 내용만 보내시려면, 체크를 해제하세요:",
+ "Keywords": "키워드",
+ "Mentions only": "답만 하기",
+ "Messages containing my display name": "내 별명이 적힌 메시지",
+ "Messages containing keywords": "키워드가 적힌 메시지",
+ "Messages containing my user name": "내 사용자 이름이 적힌 메시지",
+ "Messages in group chats": "이야기 모임의 메시지",
+ "Messages in one-to-one chats": "1:1 이야기의 메시지",
+ "Messages sent by bot": "봇이 보낸 메시지",
+ "Noisy": "소리",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "여기 표시될 수 없는 규칙에 따라 다음 키워드는 알리지 않아요:",
+ "Notify for all other messages/rooms": "다른 모든 메시지/방 알리기",
+ "Notify me for anything else": "모든 걸 알리기",
+ "Operation failed": "작업 실패",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "오류를 설명해주세요. 무슨 일을 하셨나요? 어떤 일을 예상하셨나요? 실제로는 어떤 일이 일어났나요?",
+ "Please install Chrome or Firefox for the best experience.": "최상의 경험을 위해 크롬이나 파이어폭스를 설치해주세요.",
+ "Riot does not know how to join a room on this network": "라이엇이 이 네트워크에서 방에 들어가는 법을 알 수 없어요",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "라이엇은 많은 고급 브라우저 기능을 사용해요. 일부는 현재 브라우저에서 쓸 수 없거나 실험적이에요.",
+ "The Home Server may be too old to support third party networks": "타사 네트워크를 지원하기에는 홈 서버가 너무 오래된 걸 수 있어요",
+ "There are advanced notifications which are not shown here": "여기 보이지 않는 고급 알림이 있어요",
+ "The server may be unavailable or overloaded": "서버를 쓸 수 없거나 과부하일 수 있어요",
+ "This room is inaccessible to guests. You may be able to join if you register.": "이 방은 손님이 들어가실 수 없어요. 계정을 등록하시면 들어가실 수 있을 거에요.",
+ " to room": " 방에서",
+ "Unable to fetch notification target list": "알림 대상 목록을 불러올 수 없어요",
+ "Unable to join network": "네트워크에 들어갈 수 없어요",
+ "Unable to look up room ID from server": "서버에서 방 ID를 찾아볼 수 없어요",
+ "Unhide Preview": "미리보기를 숨기지 않기",
+ "Uploaded on %(date)s by %(user)s": "by %(user)s가 %(date)s에 올림",
+ "View Decrypted Source": "해독된 출처 보기",
+ "View Source": "출처 보기",
+ "When I'm invited to a room": "방에 초대받았을 때",
+ "World readable": "세계에 보이기",
+ "You need to be using HTTPS to place a screen-sharing call.": "화면 공유를 하려면 HTTPS를 써야만 해요.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "현재 브라우저에서는, 응용 프로그램의 모양과 기능이 완벽하게 맞지 않거나, 일부 혹은 모든 기능이 작동하지 않을 수 있어요. 계속할 수는 있지만, 맞닥뜨리는 모든 문제는 직접 해결하셔야해요!",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "분산되고, 암호화된 대화 & [matrix]의 지원으로 협력",
+ "Search the room directory": "방 목록을 찾기",
+ "Get started with some tips from Riot Bot!": "라이엇 봇에게 조언을 받고 시작하세요!",
+ "General discussion about Matrix and Riot": "매트릭스와 라이엇에 대한 일반 논의",
+ "Discussion of all things Matrix!": "매트릭스의 모든 것에 대한 토론!",
+ "Riot/Web & Desktop chat": "라이엇/웹 & 데스크탑 대화",
+ "Riot/iOS & matrix-ios-sdk chat": "라이엇/IOS & matrix-ios-sdk 대화",
+ "Riot/Android & matrix-android-sdk chat": "매트릭스/안드로이드 & matrix-ios-sdk 대화",
+ "Matrix technical discussions": "매트릭스 기술 논의",
+ "Running Matrix services": "매트릭스 서비스 실행",
+ "Community-run support for Synapse": "시냅스 커뮤니티 운영 지원",
+ "Admin support for Dendrite": "덴드라이트 관리 지원",
+ "Announcements about Synapse releases": "시냅스 공개 발표",
+ "Support for those using and running matrix-appservice-irc": "matrix-appservice-irc를 사용하고 운영하는 사람들을 지원",
+ "Building services on Matrix": "매트릭스에서 서비스 구축",
+ "Support for those using the Matrix spec": "Matrix spec을 사용하는 사람들을 지원",
+ "Design and implementation of E2E in Matrix": "매트릭스에서 E2E 설계와 구현",
+ "Implementing VR services with Matrix": "매트릭스로 VR 서비스 구현",
+ "Implementing VoIP services with Matrix": "매트릭스로 인터넷전화 서비스 구현",
+ "Discussion of the Identity Service API": "ID 서비스 API에 대한 논의",
+ "Support for those using, running and writing other bridges": "다른 브릿지를 사용하고, 운영하고, 기록하는 사람들을 지원",
+ "Contributing code to Matrix and Riot": "매트릭스와 라이엇에 코드 기여하기",
+ "Dev chat for the Riot/Web dev team": "라이엇/웹 개발 팀을 위한 개발자 대화",
+ "Dev chat for the Dendrite dev team": "덴드라이트 개발 팀을 위한 개발자 대화",
+ "Co-ordination for Riot/Web translators": "라이엇/웹 번역자를 위한 조정",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "기존 네트워크(Slack, IRC, Gitter 등)에 연결되있거나 독립된 많은 방들이 이미 매트릭스에 있어요. 목록을 확인해보세요!",
+ "Failed to change password. Is your password correct?": "비밀번호를 바꾸지 못했어요. 이 비밀번호가 정말 맞으세요?",
+ "You can now return to your account after signing out, and sign in on other devices.": "계정을 로그아웃하신 뒤에 계정으로 돌아가, 다른 장치에서 로그인하실 수 있어요.",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "이런 식으로 로그아웃한 뒤 계정으로 돌아가, 다른 장치에서 로그인하실 수 있어요.",
+ "You have successfully set a password and an email address!": "비밀번호와 이메일 주소를 설정했어요!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "잊지마세요, 마음이 바뀌면 언제라도 사용자 설정에서 이메일 주소를 바꾸실 수 있다는 걸요.",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "손님으로 라이엇에 들어오셨네요. 계정을 등록하거나로그인하시고 더 많은 방과 기능을 즐기세요!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "라이엇이 아닌 다른 클라이언트에서 구성하셨을 수도 있어요. 라이엇에서 조정할 수는 없지만 여전히 적용되있을 거에요"
+}
diff --git a/src/i18n/strings/ml.json b/src/i18n/strings/ml.json
new file mode 100644
index 00000000..9f2ad64a
--- /dev/null
+++ b/src/i18n/strings/ml.json
@@ -0,0 +1,6 @@
+{
+ "Add an email address above to configure email notifications": "ഇ മെയില് അറിയിപ്പുകൾ ലഭിക്കാന് മുകളില് ഇ-മെയില് വിലാസം നല്കൂ",
+ "All messages": "എല്ലാ സന്ദേശങ്ങളും",
+ "All messages (loud)": "എല്ലാ സന്ദേശങ്ങളും (ഉച്ചത്തിൽ)",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(osName)sല് %(browserName)s വഴി %(appName)s"
+}
diff --git a/src/i18n/strings/nb_NO.json b/src/i18n/strings/nb_NO.json
new file mode 100644
index 00000000..813abc6e
--- /dev/null
+++ b/src/i18n/strings/nb_NO.json
@@ -0,0 +1,125 @@
+{
+ "Add an email address above to configure email notifications": "Legg til en epost adresse for å sette opp epost varsling",
+ "Advanced notification settings": "Avanserte varslingsinnstillinger",
+ "All messages": "Alle meldinger",
+ "All messages (loud)": "Alle meldinger (høy)",
+ "All notifications are currently disabled for all targets.": "Alle varsler er deaktivert for alle mottakere.",
+ "An error occurred whilst saving your email notification preferences.": "En feil oppsto i forbindelse med lagring av epost varsel innstillinger.",
+ "Cancel Sending": "Avbryt sending",
+ "Can't update user notification settings": "Kan ikke oppdatere brukervarsel innstillinger",
+ "Close": "Lukk",
+ "Create new room": "Opprett nytt rom",
+ "Couldn't find a matching Matrix room": "Kunne ikke finne et samsvarende Matrix rom",
+ "Safari and Opera work too.": "Safari og Opera fungerer også.",
+ "Call invitation": "Anropsinvitasjon",
+ "Collapse panel": "Skjul panel",
+ "Custom Server Options": "Tilpassede serveralternativer",
+ "customServer_text": "Du kan benytte de egendefinerte serveralternativene til å logge deg på andre Matrix-servere ved å spesifisere en annen Hjemmeserver-URL. Dette lar deg benytte Riot med en eksisterende Matrix konto på en annen hjemmeserver.
Du kan også angi en egendefinert identitetsserver, men du vil ikke kunne invitere brukere via e-post, eller bli invitert via e-post selv.",
+ "delete the alias.": "Slett aliaset.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Slett rom alias %(alias)s og fjern %(name)s fra katalogen?",
+ "Direct Chat": "Direkte Chat",
+ "Directory": "Katalog",
+ "Download this file": "Last ned filen",
+ "Drop here %(toAction)s": "Dra hit %(toAction)s",
+ "Enable audible notifications in web client": "Aktiver lyd-varsel i webklient",
+ "Enable desktop notifications": "Aktiver skrivebordsvarsler",
+ "Enable email notifications": "Aktiver e-postvarsler",
+ "Enable notifications for this account": "Aktiver varsler for denne konto",
+ "Enable them now": "Aktiver dem nå",
+ "Enter keywords separated by a comma:": "Angi nøkkelord adskilt med komma:",
+ "Error": "Feil",
+ "Error saving email notification preferences": "Feil ved lagring av e-postvarselinnstillinger",
+ "#example": "#eksempel",
+ "Expand panel": "Utvid panel",
+ "Failed to": "Feilet å",
+ "Failed to add tag %(tagName)s to room": "Kunne ikke legge til tagg %(tagName)s til rom",
+ "Failed to change settings": "Kunne ikke endre innstillingene",
+ "Failed to forget room %(errCode)s": "Kunne ikke glemme rommet %(errCode)s",
+ "Failed to update keywords": "Kunne ikke oppdatere nøkkelord",
+ "Failed to get protocol list from Home Server": "Kunne ikke hente protokolliste fra Hjemme-Server",
+ "Failed to get public room list": "Kunne ikke hente offentlig romliste",
+ "Failed to join the room": "Kunne ikke bli med på rommet",
+ "Failed to remove tag %(tagName)s from room": "Kunne ikke fjerne tagg %(tagName)s fra rommet",
+ "Failed to set direct chat tag": "Kunne ikke angi direkte chat-tagg",
+ "Failed to set Direct Message status of room": "Kunne ikke angi status for direkte melding i rommet",
+ "Favourite": "Favoritt",
+ "Fetching third party location failed": "Kunne ikke hente tredjeparts lokalisering",
+ "Files": "Filer",
+ "Filter room names": "Filtrer romnavn",
+ "Forget": "Glem",
+ " from room": " fra rommet",
+ "Guests can join": "Gjester kan bli med",
+ "Guest users can't invite users. Please register to invite.": "Gjester kan ikke invitere brukere. Vennligst registrer deg for å invitere.",
+ "I understand the risks and wish to continue": "Jeg forstår risikoen og ønsker å fortsette",
+ "Invite to this room": "Inviter til dette rommet",
+ "Keywords": "Nøkkelord",
+ "Leave": "Forlat",
+ "Low Priority": "Lav Prioritet",
+ "Members": "Medlemmer",
+ "Messages containing my display name": "Meldinger som inneholder mitt visningsnavn",
+ "Messages containing my user name": "Meldinger som inneholder mitt brukernavn",
+ "Messages in group chats": "Meldinger i gruppesamtaler",
+ "Messages in one-to-one chats": "Meldinger i en-til-en samtaler",
+ "Messages sent by bot": "Meldinger sendt av bot",
+ "more": "mer",
+ "No rooms to show": "Ingen rom å vise",
+ "Noisy": "Bråkete",
+ "Notification targets": "Mål for varsel",
+ "Notifications": "Varsler",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Varsler på de følgende nøkkelordene følger regler som ikke kan vises her:",
+ "Notify for all other messages/rooms": "Varsler om alle andre meldinger/rom",
+ "Notify me for anything else": "Varsle meg om alt annet",
+ "Off": "Av",
+ "On": "På",
+ "Permalink": "Permanent lenke",
+ "Please install Chrome or Firefox for the best experience.": "Vennligst installer Chrome eller Firefox for den beste opplevelsen.",
+ "Please Register": "Vennligst registrer deg",
+ "powered by Matrix": "benytter seg av Matrix",
+ "Quote": "Sitat",
+ "Redact": "Maskere",
+ "Reject": "Avvis",
+ "Remove %(name)s from the directory?": "Fjern %(name)s fra katalogen?",
+ "Remove": "Fjern",
+ "remove %(name)s from the directory.": "fjern %(name)s fra katalogen.",
+ "Remove from Directory": "Fjern fra katalogen",
+ "Resend": "Send på nytt",
+ "Riot does not know how to join a room on this network": "Riot vet ikke hvordan man kan komme inn på et rom på dette nettverket",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot benytter mange avanserte nettleserfunksjoner, og noen av disse er ikke tilgjengelige eller er eksperimentelle på din nåværende nettleser.",
+ "Room directory": "Rom katalog",
+ "Room not found": "Rommet ble ikke funnet",
+ "Search for a room": "Søk etter et rom",
+ "Settings": "Innstillinger",
+ "Source URL": "Kilde URL",
+ "Sorry, your browser is not able to run Riot.": "Beklager, din nettleser er ikke i stand til å kjøre Riot.",
+ "Start chat": "Start chat",
+ "The Home Server may be too old to support third party networks": "Hjemme-serveren kan være for gammel til å støtte tredjeparts-nettverk",
+ "There are advanced notifications which are not shown here": "Det er avanserte varsler som ikke vises her",
+ "The server may be unavailable or overloaded": "Serveren kan være utilgjengelig eller overbelastet",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Dette rommet er ikke tilgjengelig for gjester. Du kan kanskje komme inn om du registrerer deg.",
+ " to room": " til rom",
+ "Unable to fetch notification target list": "Kunne ikke hente varsel-mål liste",
+ "Unable to join network": "Kunne ikke bli med i nettverket",
+ "Unable to look up room ID from server": "Kunne ikke slå opp rom-ID fra serveren",
+ "Unhide Preview": "Vis forhåndsvisning",
+ "unknown error code": "ukjent feilkode",
+ "Unnamed room": "Rom uten navn",
+ "Uploaded on %(date)s by %(user)s": "Lastet opp den %(date)s av %(user)s",
+ "View Decrypted Source": "Vis dekryptert kilde",
+ "View Source": "Vis kilde",
+ "When I'm invited to a room": "Når jeg blir invitert til et rom",
+ "World readable": "Verden lesbar",
+ "You cannot delete this image. (%(code)s)": "Du kan ikke slette dette bildet. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Du kan ikke slette denne meldingen. (%(code)s)",
+ "You are not receiving desktop notifications": "Du mottar ikke skrivebords varsler",
+ "Messages containing keywords": "Meldinger som inneholder nøkkelord",
+ "Sunday": "Søndag",
+ "Monday": "Mandag",
+ "Tuesday": "Tirsdag",
+ "Wednesday": "Onsdag",
+ "Thursday": "Torsdag",
+ "Friday": "Fredag",
+ "Saturday": "Lørdag",
+ "Today": "I dag",
+ "Yesterday": "I går",
+ "Welcome page": "Velkomst side"
+}
diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json
new file mode 100644
index 00000000..d3d9483c
--- /dev/null
+++ b/src/i18n/strings/nl.json
@@ -0,0 +1,202 @@
+{
+ "Add an email address above to configure email notifications": "Voeg een e-mailadres toe om e-mailmeldingen te ontvangen",
+ "Advanced notification settings": "Geavanceerde meldingsinstellingen",
+ "All messages": "Alle berichten",
+ "All messages (loud)": "Alle berichten (luid)",
+ "All notifications are currently disabled for all targets.": "Alle meldingen zijn momenteel uitgeschakeld voor alle doelen.",
+ "An error occurred whilst saving your email notification preferences.": "Er is een fout opgetreden tijdens het opslaan van uw e-mailmeldingsvoorkeuren.",
+ "Call invitation": "Oproep-uitnodiging",
+ "Cancel Sending": "Versturen annuleren",
+ "Can't update user notification settings": "Het is niet gelukt om de meldingsinstellingen van de gebruiker bij te werken",
+ "Close": "Sluiten",
+ "Create new room": "Een nieuwe kamer maken",
+ "Couldn't find a matching Matrix room": "Het is niet gelukt om een bijbehorende Matrix-kamer te vinden",
+ "Custom Server Options": "Aangepaste serverinstellingen",
+ "customServer_text": "U kunt de aangepaste serverinstellingen gebruiken om in te loggen bij andere Matrix-servers door een andere homeserver-URL in te voeren. Dit maakt het mogelijk om Riot te gebruiken met een bestaand Matrix-account op een andere homeserver.
U kunt ook een aangepaste identiteitsserver instellen, maar het is dan niet mogelijk om gebruikers uit te nodigen met behulp van een e-mailadres of zelf uitgenodigd te worden met een e-mailadres.",
+ "delete the alias.": "verwijder de alias.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "De alias %(alias)s verwijderen en %(name)s uit de kamerlijst verwijderen?",
+ "Direct Chat": "Privégesprek",
+ "Directory": "Kamerlijst",
+ "Dismiss": "Afwijzen",
+ "Download this file": "Download dit bestand",
+ "Enable audible notifications in web client": "Geluidsmeldingen in de webclient aanzetten",
+ "Enable desktop notifications": "Desktopmeldingen aanzetten",
+ "Enable email notifications": "E-mailmeldingen aanzetten",
+ "Enable notifications for this account": "Meldingen voor dit account aanzetten",
+ "Enable them now": "Deze nu aanzetten",
+ "Enter keywords separated by a comma:": "Voeg trefwoorden toe, gescheiden door een komma:",
+ "Error": "Fout",
+ "Error saving email notification preferences": "Fout bij het opslaan van de meldingsvoorkeuren voor e-mail",
+ "#example": "#voorbeeld",
+ "Failed to": "Mislukt om",
+ "Failed to add tag %(tagName)s to room": "Mislukt om de label %(tagName)s aan de kamer toe te voegen",
+ "Failed to change settings": "Instellingen wijzigen mislukt",
+ "Failed to forget room %(errCode)s": "Ruimte vergeten mislukt %(errCode)s",
+ "Failed to update keywords": "Trefwoorden bijwerken mislukt",
+ "Failed to get protocol list from Home Server": "Protocollijst ophalen van de homeserver mislukt",
+ "Failed to get public room list": "Lijst met publieke kamers ophalen mislukt",
+ "Failed to join the room": "Kamer binnengaan mislukt",
+ "Failed to remove tag %(tagName)s from room": "Label %(tagName)s van de kamer verwijderen mislukt",
+ "Failed to set direct chat tag": "Het is mislukt om het privéchatlabel weg te halen",
+ "Favourite": "Favoriet",
+ "Fetching third party location failed": "Het ophalen van de locatie van de derde partij is mislukt",
+ "Files": "Bestanden",
+ "Filter room names": "Filter kamernamen",
+ "Forget": "Vergeten",
+ " from room": " van kamer",
+ "Guests can join": "Gasten kunnen deelnemen",
+ "Guest users can't invite users. Please register to invite.": "Gasten kunnen geen gebruikers uitnodigen. Om anderen uit te nodigen zult u zich moeten registreren.",
+ "Invite to this room": "Uitnodigen voor deze kamer",
+ "Keywords": "Trefwoorden",
+ "Leave": "Verlaten",
+ "Low Priority": "Lage prioriteit",
+ "Members": "Leden",
+ "Mentions only": "Alleen vermeldingen",
+ "Messages containing my display name": "Berichten die mijn weergavenaam bevatten",
+ "Messages containing my user name": "Berichten die mijn gebruikersnaam bevatten",
+ "Messages in group chats": "Berichten in groepsgesprekken",
+ "Messages in one-to-one chats": "Berichten in één-op-één-gesprekken",
+ "Messages sent by bot": "Berichten verzonden door een bot",
+ "more": "meer",
+ "Mute": "Dempen",
+ "No rooms to show": "Geen kamers om te laten zien",
+ "Noisy": "Luidruchtig",
+ "Notification targets": "Meldingsdoelen",
+ "Notifications": "Meldingen",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Meldingen op de volgende trefwoorden volgen regels die hier niet kunnen worden getoond:",
+ "Notify for all other messages/rooms": "Stuur een melding voor alle andere berichten/kamers",
+ "Notify me for anything else": "Stuur een melding voor al het andere",
+ "Off": "Uit",
+ "On": "Aan",
+ "Operation failed": "Actie mislukt",
+ "Permalink": "Permanente link",
+ "Please Register": "Registreer Alstublieft",
+ "powered by Matrix": "mogelijk gemaakt door Matrix",
+ "Quote": "Citeer",
+ "Reject": "Afwijzen",
+ "Remove %(name)s from the directory?": "%(name)s uit de kamerlijst verwijderen?",
+ "Remove": "Verwijderen",
+ "remove %(name)s from the directory.": "verwijder %(name)s uit de kamerlijst.",
+ "Remove from Directory": "Uit de kamerlijst verwijderen",
+ "Resend": "Opnieuw verzenden",
+ "Riot does not know how to join a room on this network": "Riot weet niet hoe het moet deelnemen in een kamer op dit netwerk",
+ "Room directory": "Kamerlijst",
+ "Room not found": "De kamer is niet gevonden",
+ "Search for a room": "Een kamer opzoeken",
+ "Settings": "Instellingen",
+ "Source URL": "Bron-URL",
+ "Start chat": "Gesprek starten",
+ "The Home Server may be too old to support third party networks": "De home server is misschien te oud om netwerken van derde partijen te ondersteunen",
+ "There are advanced notifications which are not shown here": "Er zijn geavanceerde notificaties die hier niet getoond worden",
+ "The server may be unavailable or overloaded": "De server is misschien niet beschikbaar of overbelast",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Deze kamer is niet toegankelijk voor gasten. Je zou misschien kunnen deelnemen als je geregistreerd bent.",
+ " to room": " naar kamer",
+ "Unable to fetch notification target list": "Het is mislukt om de lijst van notificatiedoelen op te halen",
+ "Unable to join network": "Het is mislukt om toe te treden tot dit netwerk",
+ "Unable to look up room ID from server": "Het is mislukt om de kamer-ID op te halen van de server",
+ "Unhide Preview": "Zichtbaar maken preview",
+ "unknown error code": "onbekende foutcode",
+ "Unnamed room": "Kamer zonder naam",
+ "Uploaded on %(date)s by %(user)s": "Geüpload op %(date)s door %(user)s",
+ "View Decrypted Source": "Bekijk ontsleutelde bron",
+ "View Source": "Bekijk bron",
+ "When I'm invited to a room": "Wanneer ik uitgenodigd word voor een kamer",
+ "World readable": "Door iedereen leesbaar",
+ "You cannot delete this image. (%(code)s)": "Je kunt deze afbeelding niet verwijderen. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Je kunt dit bericht niet verwijderen. (%(code)s)",
+ "You are not receiving desktop notifications": "Je ontvangt momenteel geen desktopmeldingen",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Je hebt ze mogelijk ingesteld in een andere client dan Riot. Je kunt ze niet aanpassen in Riot maar ze zijn wel actief",
+ "Sunday": "Zondag",
+ "Monday": "Maandag",
+ "Tuesday": "Dinsdag",
+ "Wednesday": "Woensdag",
+ "Thursday": "Donderdag",
+ "Friday": "Vrijdag",
+ "Saturday": "Zaterdag",
+ "Today": "Vandaag",
+ "Yesterday": "Gisteren",
+ "Welcome page": "Welkomstpagina",
+ "Drop here %(toAction)s": "%(toAction)s hier naartoe verplaatsen",
+ "Failed to set Direct Message status of room": "Het is mislukt om de directe-berichtenstatus van de kamer in te stellen",
+ "Redact": "Redigeren",
+ "A new version of Riot is available.": "Er is een nieuwe versie van Riot beschikbaar.",
+ "All Rooms": "Alle kamers",
+ "Cancel": "Annuleren",
+ "Safari and Opera work too.": "Safari en Opera werken ook.",
+ "Changelog": "Logboek van wijzigingen",
+ "Collapse panel": "Paneel inklappen",
+ "Collecting app version information": "App-versieinformatie verzamelen",
+ "Collecting logs": "Logboeken verzamelen",
+ "Describe your problem here.": "Beschrijf uw probleem hier.",
+ "Expand panel": "Paneel uitklappen",
+ "Failed to send report: ": "Rapport verzenden mislukt: ",
+ "Forward Message": "Bericht doorsturen",
+ "Hide panel": "Paneel verbergen",
+ "(HTTP status %(httpStatus)s)": "(HTTP-status %(httpStatus)s)",
+ "I understand the risks and wish to continue": "Ik begrijp de risico's en wil graag verder gaan",
+ "Login": "Aanmelden",
+ "Loading bug report module": "Bugrapporteermodule laden",
+ "Messages containing keywords": "Berichten die trefwoorden bevatten",
+ "Please install Chrome or Firefox for the best experience.": "Installeer Chrome of Firefox voor de beste ervaring.",
+ "Report a bug": "Een bug rapporteren",
+ "Riot Desktop on %(platformName)s": "Riot Desktop op %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot wordt niet ondersteund op het mobiele web. Wil je de app installeren?",
+ "Search": "Zoeken",
+ "Search…": "Zoeken…",
+ "Send": "Versturen",
+ "Send logs": "Logboeken versturen",
+ "Sorry, your browser is not able to run Riot.": "Sorry, uw browser werkt niet met Riot.",
+ "This Room": "Deze kamer",
+ "Unavailable": "Niet beschikbaar",
+ "Unknown device": "Onbekend apparaat",
+ "Update": "Bijwerken",
+ "Uploading report": "Rapport uploaden",
+ "What's New": "Wat is er nieuw",
+ "What's new?": "Wat is er nieuw?",
+ "Waiting for response from server": "Wachten op antwoord van de server",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "U gebruikt Riot als gast. Registreren of aanmelden om voor meer kamers en functies!",
+ "OK": "OK",
+ "You need to be using HTTPS to place a screen-sharing call.": "U moet HTTPS gebruiken om een oproep met schermdelen te kunnen starten.",
+ "Welcome to Riot.im": "Welkom bij Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Gedecentaliseerd en versleuteld chatten & samenwerken mogelijk gemaakt door [matrix]",
+ "Search the room directory": "De kamerlijst doorzoeken",
+ "Chat with Riot Bot": "Met Riot Bot chatten",
+ "Get started with some tips from Riot Bot!": "Begin met enkele tips van Riot Bot!",
+ "General discussion about Matrix and Riot": "Algemene discussie over Matrix en Riot",
+ "Discussion of all things Matrix!": "Discussie over alles wat met Matrix te maken heeft!",
+ "Riot/Web & Desktop chat": "Riot/Web & Desktop-chat",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/iOS & matrix-ios-sdk-chat",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Android & matrix-android-sdk-chat",
+ "Matrix technical discussions": "Technische discussies over Matrix",
+ "Running Matrix services": "Matrixdiensten beheren",
+ "Community-run support for Synapse": "Synapse-ondersteuning vanuit de gemeenschap",
+ "Admin support for Dendrite": "Beheerondersteuning voor Dendrite",
+ "Announcements about Synapse releases": "Aankondigingen over Synapse-uitgaven",
+ "Support for those using and running matrix-appservice-irc": "Ondersteuning voor gebruikers en beheerders van matrix-appservice-irc",
+ "Building services on Matrix": "Diensten op Matrix bouwen",
+ "Support for those using the Matrix spec": "Ondersteuning voor gebruikers van Matrix-specificatie",
+ "Contributing code to Matrix and Riot": "Code bijdragen aan Matrix en Riot",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Veel kamers bestaan al in Matrix, gelinkt aan bestaande netwerken (Slack, IRC, Gitter, enz.) of onafhankelijk. Bekijk de kamerlijst!",
+ "Failed to change password. Is your password correct?": "Wachtwoord wijzigen mislukt. Is uw wachtwoord juist?",
+ "You have successfully set a password!": "U heeft met succes een wachtwoord ingesteld!",
+ "You can now return to your account after signing out, and sign in on other devices.": "U kunt nu terugkeren naar uw account nadat u bent afgemeld, en u aanmelden op andere apparaten.",
+ "Continue": "Doorgaan",
+ "Please set a password!": "Stel een wachtwoord in!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Hiermee kunt u naar uw account terugkeren nadat u zich heeft afgemeld, en u aanmelden op andere apparaten.",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s op %(osName)s",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Beschrijf de bug. Wat deed u? Wat verwachtte u? Wat gebeurde er daadwerkelijk?",
+ "Please describe the bug and/or send logs.": "Beschrijf de bug en/of verstuur logboeken.",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot gebrukt veel geavanceerde browserfuncties, waarvan enkele niet (of experimenteel) in uw webbrowser beschikbaar zijn.",
+ "Co-ordination for Riot/Web translators": "Coördinatie voor Riot/Web-vertalers",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Om diagnose van het probleem mogelijk te maken worden logboeken van deze client met het bugrapport meegestuurd. Schakel dit vinkje uit als u slechts de bovenstaande tekst mee wil sturen:",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Met uw huidige browser kan de applicatie er volledig incorrect uitzien. Tevens is het mogelijk dat niet alle functies naar behoren werken. U kunt doorgaan als u het toch wil proberen, maar bij problemen bent u volledig op uzelf aangewezen!",
+ "Design and implementation of E2E in Matrix": "Ontwerp en implementatie van E2E in Matrix",
+ "Implementing VR services with Matrix": "Implementatie van VR-diensten met Matrix",
+ "Implementing VoIP services with Matrix": "Implementatie van VoIP-diensten met Matrix",
+ "Discussion of the Identity Service API": "Discussie over de Identity Service API",
+ "Support for those using, running and writing other bridges": "Ondersteuning voor het gebruiken, draaien en ontwikkelen aan andere bruggen",
+ "Dev chat for the Riot/Web dev team": "Dev-chat voor het Riot/Web ontwikkelteam",
+ "Dev chat for the Dendrite dev team": "Dev-chat voor het Dendrite ontwikkelteam",
+ "You have successfully set a password and an email address!": "Het instellen van een wachtwoord en e-mailadres is geslaagd!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Onthoud dat u altijd een e-mailadres in kan stellen in de gebruikersinstellingen als u zich bedenkt."
+}
diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json
new file mode 100644
index 00000000..2941f4b5
--- /dev/null
+++ b/src/i18n/strings/pl.json
@@ -0,0 +1,202 @@
+{
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s przez %(browserName)s na %(osName)s",
+ "Safari and Opera work too.": "Safari i Opera też działają.",
+ "A new version of Riot is available.": "Dostępna jest nowa wersja Riot.",
+ "Add an email address above to configure email notifications": "Dodaj adres e-mail powyżej, aby skonfigurować powiadomienia e-mailowe",
+ "Advanced notification settings": "Zaawansowane ustawienia powiadomień",
+ "All messages": "Wszystkie wiadomości",
+ "All messages (loud)": "Wszystkie wiadomości (głośno)",
+ "All Rooms": "Wszystkie pokoje",
+ "All notifications are currently disabled for all targets.": "Wszystkie powiadomienia są obecnie wyłączone dla wszystkich celów.",
+ "An error occurred whilst saving your email notification preferences.": "Podczas zapisywania ustawień powiadomień e-mail wystąpił błąd.",
+ "Call invitation": "Zaproszenie do rozmowy",
+ "Cancel": "Anuluj",
+ "Cancel Sending": "Anuluj wysyłanie",
+ "Can't update user notification settings": "Nie można zaktualizować ustawień powiadomień użytkownika",
+ "Changelog": "Dziennik zmian",
+ "Close": "Blisko",
+ "Collecting app version information": "Zbieranie informacji o wersji aplikacji",
+ "Collecting logs": "Zbieranie dzienników",
+ "Create new room": "Utwórz nowy pokój",
+ "Couldn't find a matching Matrix room": "Nie można znaleźć pasującego pokoju Matrix",
+ "Custom Server Options": "Niestandardowe opcje serwera",
+ "delete the alias.": "usunąć alias.",
+ "Describe your problem here.": "Opisz swój problem tutaj.",
+ "Directory": "Księga adresowa",
+ "Download this file": "Pobierz plik",
+ "Welcome page": "Strona powitalna",
+ "Riot is not supported on mobile web. Install the app?": "Riot nie jest obsługiwany przez przeglądarki mobilne. Zainstaluj aplikację?",
+ "Room directory": "Spis pokojów",
+ "Search": "Szukaj",
+ "Search…": "Szukaj…",
+ "Search for a room": "Szukaj pokoju",
+ "Send": "Wyślij",
+ "Settings": "Ustawienia",
+ "Collapse panel": "Ukryj panel",
+ "customServer_text": "Możesz używać opcji serwera niestandardowego do logowania się na inne serwery Matrix, określając inny adres URL serwera domowego. Pozwala to na wykorzystanie Riot z istniejącym kontem Matrix na innym serwerze domowym.
Można również ustawić niestandardowy serwer tożsamości, ale nie będzie można zapraszać użytkowników adresem e-mail, ani być zaproszony przez adres e-mailowy.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Usuń alias %(alias)s i usuń %(name)s z katalogu?",
+ "Dismiss": "Zdymisjonować",
+ "Drop here %(toAction)s": "Upuść tutaj %(toAction)s",
+ "Enable audible notifications in web client": "Włącz dźwiękowe powiadomienia w kliencie internetowym",
+ "Enable email notifications": "Włącz powiadomienia e-mailowe",
+ "Enable notifications for this account": "Włącz powiadomienia na tym koncie",
+ "Enable them now": "Włącz je teraz",
+ "Enter keywords separated by a comma:": "Wpisz słowa kluczowe oddzielone przecinkami:",
+ "Error": "Błąd",
+ "Error saving email notification preferences": "Wystąpił błąd podczas zapisywania ustawień powiadomień e-mailowych",
+ "#example": "#przykład",
+ "Expand panel": "Rozwiń panel",
+ "Failed to": "Nie udało się",
+ "Failed to add tag %(tagName)s to room": "Nie można dodać tagu %(tagName)s do pokoju",
+ "Failed to change settings": "Nie udało się zmienić ustawień",
+ "Failed to forget room %(errCode)s": "Nie mogłem zapomnieć o pokoju %(errCode)s",
+ "Failed to update keywords": "Nie udało się zaktualizować słów kluczowych",
+ "Failed to get protocol list from Home Server": "Nie można pobrać listy protokołów z serwera domowego",
+ "Failed to get public room list": "Nie udało się uzyskać publicznej listy pokojowej",
+ "Failed to join the room": "Nie udało się dołączyć do pokoju",
+ "Failed to remove tag %(tagName)s from room": "Nie udało się usunąć tagu %(tagName)s z pokoju",
+ "Failed to send report: ": "Nie udało się wysłać raportu: ",
+ "Favourite": "Ulubiony",
+ "Files": "Pliki",
+ "Filter room names": "Filtruj nazwy pokojów",
+ "Forget": "Zapomnij",
+ "Forward Message": "Przekaż wiadomość",
+ " from room": " z pokoju",
+ "Guests can join": "Goście mogą dołączyć",
+ "Hide panel": "Ukryj panel",
+ "I understand the risks and wish to continue": "Rozumiem ryzyko i chęć kontynuować",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "W celu zdiagnozowania problemów logi z tego klienta zostaną wysłane wraz z tym raportem o błędzie. Jeśli wolisz wysłać tylko tekst powyżej, proszę odznacz:",
+ "Invite to this room": "Zaproś do tego pokoju",
+ "Keywords": "Słowa kluczowe",
+ "Loading bug report module": "Ładowanie modułu raportu błędów",
+ "Low Priority": "Niski priorytet",
+ "Messages containing keywords": "Wiadomości zawierające słowa kluczowe",
+ "Messages containing my user name": "Wiadomości zawierające moją nazwę użytkownika",
+ "Messages in group chats": "Wiadomości w czatach grupowych",
+ "Messages sent by bot": "Wiadomości wysłane przez bota",
+ "more": "więcej",
+ "Enable desktop notifications": "Włącz powiadomienia",
+ "Guest users can't invite users. Please register to invite.": "Gość nie ma uprawnień dow wysyłania zaproszeń. Proszę się zarejestrować.",
+ "(HTTP status %(httpStatus)s)": "(status HTTP %(httpStatus)s)",
+ "Leave": "Opuść",
+ "Login": "Logowanie",
+ "Members": "Członkowie",
+ "Messages containing my display name": "Wiadomości zawierające moją wyświetlaną nazwę",
+ "Direct Chat": "Rozmowa bezpośrednia",
+ "Mute": "Wycisz",
+ "No rooms to show": "Brak pokoi do wyświetlenia",
+ "Notifications": "Powiadomienia",
+ "Failed to set direct chat tag": "Nie udało się ustawić znacznika rozmów bezpośrednich",
+ "Failed to set Direct Message status of room": "Nie udało się ustawić statusu Rozmów Bezpośrednich dla pokoju",
+ "Notification targets": "Cele powiadomień",
+ "Operation failed": "Operacja nieudana",
+ "Permalink": "Odnośnik bezpośredni",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Proszę opisz problem (w miarę możliwości po angielsku). Co doprowadziło do błędu? Jakie było Twoje oczekiwanie, a co stało się zamiast tego?",
+ "Please describe the bug and/or send logs.": "Proszę opisz błąd i/lub wyślij logi.",
+ "Please install Chrome or Firefox for the best experience.": "Zainstaluj proszę Chrome lub Firefox.",
+ "Please Register": "Proszę się zarejestrować",
+ "Quote": "Cytat",
+ "Remove %(name)s from the directory?": "Usunąć %(name)s z katalogu?",
+ "Remove from Directory": "Usuń z katalogu",
+ "Report a bug": "Zgłoś błąd",
+ "Resend": "Wyślij jeszcze raz",
+ "Riot Desktop on %(platformName)s": "Riot Desktop na %(platformName)s",
+ "Riot does not know how to join a room on this network": "Riot nie wie, jak dołączyć do pokoju w tej sieci",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot używa wiele zaawansowanych technologii, które nie są dostępne lub są w fazie testów w Twojej przeglądarce.",
+ "Room not found": "Pokój nie znaleziony",
+ "Send logs": "Wyślij logi",
+ "Sorry, your browser is not able to run Riot.": "Przepraszamy, Twoja przeglądarka nie jest w stanie uruchomić Riot.",
+ "Start chat": "Rozpocznij rozmowę",
+ "powered by Matrix": "zbudowane na Matrix",
+ "Redact": "Zredaguj",
+ "Reject": "Odrzuć",
+ "Remove": "Usuń",
+ "remove %(name)s from the directory.": "usuń %(name)s z katalogu.",
+ "The Home Server may be too old to support third party networks": "Serwer domowy może być za stary dla innych sieci",
+ "There are advanced notifications which are not shown here": "Masz zaawansowane powiadomienia, nie pokazane tutaj",
+ "The server may be unavailable or overloaded": "Serwer jest nieosiągalny lub jest przeciążony",
+ "This Room": "Ten pokój",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Ten pokój jest niedostępny dla gości. Możliwe, że będziesz mógł dołączyć po rejestracji.",
+ "Unable to join network": "Nie można dołączyć do sieci",
+ "Unable to look up room ID from server": "Nie można wyszukać ID pokoju na serwerze",
+ "Unavailable": "Niedostępny",
+ "Unhide Preview": "Odkryj podgląd",
+ "Unknown device": "Nieznane urządzenie",
+ "unknown error code": "nieznany kod błędu",
+ "Unnamed room": "Pokój bez nazwy",
+ "Update": "Uaktualnienie",
+ "Uploaded on %(date)s by %(user)s": "Wysłane %(date)s przez %(user)s",
+ "Uploading report": "Raport wysyłania",
+ "Messages in one-to-one chats": "Wiadomości w rozmowach jeden-na-jeden",
+ "Noisy": "Głośny",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Powiadomienia o słowach kluczowych spełniają reguły, które nie mogą być tu wyświetlone:",
+ "Notify for all other messages/rooms": "Powiadamiaj o wszystkich innych wiadomośsciach/pokojach",
+ "Notify me for anything else": "Powiadom mnie o całej reszcie",
+ "Off": "Wyłącz",
+ "On": "Włącz",
+ "Source URL": "Źródłowy URL",
+ " to room": " do pokoju",
+ "Unable to fetch notification target list": "Nie można pobrać listy docelowej dla powiadomień",
+ "View Decrypted Source": "Pokaż zdeszyfrowane źródło",
+ "View Source": "Pokaż źródło",
+ "What's New": "Co nowego",
+ "What's new?": "Co nowego?",
+ "Waiting for response from server": "Czekam na odpowiedź serwera",
+ "When I'm invited to a room": "Kiedy zostanę zaproszony do pokoju",
+ "World readable": "Całkowicie publiczne",
+ "You cannot delete this image. (%(code)s)": "Nie możesz usunąć tego obrazka. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Nie możesz usunąć tej wiadomości. (%(code)s)",
+ "You are not receiving desktop notifications": "Nie otrzymujesz powiadomień na pulpit",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "You are Rioting jako gość. Zarejestruj się albo zaloguj się aby uzyskać dostęp do pokojów lub dodatkowych możliwości!",
+ "Sunday": "Niedziela",
+ "Monday": "Poniedziałek",
+ "Tuesday": "Wtorek",
+ "Wednesday": "Środa",
+ "Thursday": "Czwartek",
+ "Friday": "Piątek",
+ "Saturday": "Sobota",
+ "Today": "Dzisiaj",
+ "Yesterday": "Wczoraj",
+ "OK": "OK",
+ "You need to be using HTTPS to place a screen-sharing call.": "Musisz używać bezpiecznego protokołu HTTPS aby użyć połączenia współdzielenia ekranu.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Z Twoją obecną przeglądarką, wygląd oraz wrażenia z używania aplikacji mogą być niepoprawne, a niektóre funkcje wcale nie działać. Kontynuuj jeśli chcesz spróbować, jednak trudno będzie pomóc w przypadku błędów, które mogą nastąpić!",
+ "Welcome to Riot.im": "Witamy w Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Zdecentralizowany, szyfrowany czat & współpraca wspierana przez [matrix]",
+ "Search the room directory": "Wyszukaj katalog pokojów",
+ "Chat with Riot Bot": "Rozmowa z Botem Riota",
+ "Get started with some tips from Riot Bot!": "Rozpocznij z wskazówkami Riot Bota!",
+ "General discussion about Matrix and Riot": "Generalna rozmowa o Matrix i Riot",
+ "Discussion of all things Matrix!": "Rozmowa o wszystkim Matrixowym!",
+ "Matrix technical discussions": "Dyskusje techniczne Matrixa",
+ "Fetching third party location failed": "Pobranie lokalizacji zewnętrznej nie powiodło się",
+ "Mentions only": "Tylko, gdy wymienieni",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Możliwe, że skofigurowałeś je w innym kliencie, niż Riot. Nie możesz ich zmieniać w Riot, ale nadal mają zastosowanie",
+ "Riot/Web & Desktop chat": "Czat o Riot/Web i Desktop",
+ "Riot/iOS & matrix-ios-sdk chat": "Czat o Riot/iOS i matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Czat o Riot/Android i matrix-android-sdk",
+ "Running Matrix services": "Utrzymywanie usług Matrix",
+ "Community-run support for Synapse": "Wsparcie społeczności dla Synapse",
+ "Admin support for Dendrite": "Wsparcie administratorskie dla Dendrite",
+ "Announcements about Synapse releases": "Ogłoszenia na temat Synapse",
+ "Support for those using and running matrix-appservice-irc": "Wsparcie dla hostujących i korzystających z matrix-appservice-irc",
+ "Building services on Matrix": "Tworzenie usług w oparciu o Matrix",
+ "Support for those using the Matrix spec": "Wsparcie dla używających specyfikacji Matrix",
+ "Design and implementation of E2E in Matrix": "Projektowanie i implementacja szyfrowania klient-klient (end-to-end) w Matrix",
+ "Implementing VR services with Matrix": "Implementowanie usług wirtualnej rzeczywistości w oparciu o Matrix",
+ "Implementing VoIP services with Matrix": "Implementowanie usług telefonii internetowej VoIP w oparciu o Matrix",
+ "Discussion of the Identity Service API": "Dyskusja na temat API Identity Service",
+ "Support for those using, running and writing other bridges": "Wsparcie dla używających, zapewniających i piszących inne mosty",
+ "Contributing code to Matrix and Riot": "Dokładanie kodu do Matrix lub Riot",
+ "Dev chat for the Riot/Web dev team": "Czat deweloperów zespołu Riot/Web",
+ "Dev chat for the Dendrite dev team": "Czat deweloperów zespołu Dendrite",
+ "Co-ordination for Riot/Web translators": "Koordynacja tłumaczy Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Matrix ma wiele, już działających pokoi, połączonych z istniejącymi sieciami, takimi jak Slack, IRC lub Gitter, a także wiele zupełnie niezależnych. Możesz przejrzeć je wszystkie w spisie pokoi!",
+ "Failed to change password. Is your password correct?": "Zmiana hasła nie powiodła się. Czy Twoje hasło jest poprawne?",
+ "You have successfully set a password!": "Hasło zostało zmienione z powodzeniem!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Teraz możesz powrócić do swojego konta na innych urządzeniach po wylogowaniu i ponownym zalogowaniu się.",
+ "Continue": "Kontynuuj",
+ "Please set a password!": "Proszę, ustaw hasło!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "To pozwoli Ci powrócić do Twojego konta po wylogowaniu i ponownym zalogowaniu się na innych urządzeniach.",
+ "You have successfully set a password and an email address!": "Z powodzeniem ustawiono hasło i adres e-mail dla Twojego konta!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Pamiętaj, że zawsze możesz zmienić swój e-mail lub hasło w panelu ustawień użytkownika."
+}
diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json
new file mode 100644
index 00000000..63f8500c
--- /dev/null
+++ b/src/i18n/strings/pt.json
@@ -0,0 +1,166 @@
+{
+ "Add an email address above to configure email notifications": "Insira um endereço de email no campo acima para configurar as notificações por email",
+ "All messages": "Todas as mensagens",
+ "All messages (loud)": "Todas as mensagens (alto)",
+ "An error occurred whilst saving your email notification preferences.": "Ocorreu um erro ao guardar as suas preferências de notificação por email.",
+ "Call invitation": "Convite para chamada",
+ "Cancel Sending": "Cancelar o envio",
+ "Can't update user notification settings": "Não é possível atualizar as preferências de notificação",
+ "Close": "Fechar",
+ "Create new room": "Criar nova sala",
+ "Couldn't find a matching Matrix room": "Não foi possível encontrar uma sala correspondente no servidor Matrix",
+ "Custom Server Options": "Opções para Servidor Personalizado",
+ "delete the alias.": "apagar o apelido da sala.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Apagar o apelido %(alias)s da sala e remover %(name)s da lista pública?",
+ "Direct Chat": "Conversa pessoal",
+ "Directory": "Diretório",
+ "Dismiss": "Descartar",
+ "Download this file": "Transferir este ficheiro",
+ "Drop here %(toAction)s": "Arraste aqui para %(toAction)s",
+ "Enable audible notifications in web client": "Ativar notificações de áudio no cliente web",
+ "Enable desktop notifications": "Ativar notificações no desktop",
+ "Enable email notifications": "Ativar notificações por e-mail",
+ "Enable notifications for this account": "Ativar notificações para esta conta",
+ "Enable them now": "Ativar agora",
+ "Enter keywords separated by a comma:": "Insira palavras-chave separadas por vírgula:",
+ "Error": "Erro",
+ "Error saving email notification preferences": "Erro ao guardar as preferências de notificação por e-mail",
+ "#example:": "#exemplo",
+ "Failed to": "Falha ao",
+ "Failed to add tag %(tagName)s to room": "Falha ao adicionar %(tagName)s à sala",
+ "Failed to change settings": "Falha ao alterar as configurações",
+ "Failed to forget room %(errCode)s": "Falha ao esquecer a sala %(errCode)s",
+ "Failed to update keywords": "Falha ao atualizar as palavras-chave",
+ "Failed to get protocol list from Home Server": "Falha ao obter a lista de protocolos do servidor padrão",
+ "Failed to get public room list": "Falha ao obter a lista de salas públicas",
+ "Failed to join the room": "Falha ao entrar na sala",
+ "Failed to remove tag %(tag)s from room": "Falha ao remover a palavra-chave %(tag)s da sala",
+ "Failed to set direct chat tag": "Falha ao definir conversa como pessoal",
+ "Failed to set Direct Message status of room": "Falha em definir a mensagem de status da sala",
+ "Favourite": "Favorito",
+ "Fetching third party location failed": "Falha ao obter localização de terceiros",
+ "Files": "Ficheiros",
+ "Filter room names": "Filtrar salas por título",
+ "Forget": "Esquecer",
+ "Forward Message": "Encaminhar",
+ " from room": " da sala",
+ "Guests can join": "Convidados podem entrar",
+ "Guest users can't invite users. Please register to invite.": "Utilizadores convidados não podem convidar utilizadores. Por favor registe-se para convidar.",
+ "Invite to this room": "Convidar para esta sala",
+ "Keywords": "Palavras-chave",
+ "Leave": "Sair",
+ "Low Priority": "Baixa prioridade",
+ "Members": "Membros",
+ "Mentions only": "Apenas menções",
+ "Messages containing my display name": "Mensagens contendo o meu nome público",
+ "Messages containing my user name": "Mensagens contendo o meu nome de utilizador",
+ "Messages in group chats": "Mensagens em salas",
+ "Messages in one-to-one chats": "Mensagens em conversas pessoais",
+ "Messages sent by bot": "Mensagens enviadas por bots",
+ "more": "mais",
+ "Mute": "Silenciar",
+ "No rooms to show": "Não existem salas a serem exibidas",
+ "Noisy": "Barulhento",
+ "Notification targets": "Alvos de notificação",
+ "Notifications": "Notificações",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Notificações sobre as seguintes palavras-chave seguem regras que não podem ser exibidas aqui:",
+ "Notify for all other messages/rooms": "Notificar para todas as outras mensagens/salas",
+ "Notify me for anything else": "Notificar-me sobre qualquer outro evento",
+ "Off": "Desativado",
+ "On": "Ativado",
+ "Operation failed": "A operação falhou",
+ "Permalink": "Link permanente",
+ "Please Register": "Por favor registe-se",
+ "powered by Matrix": "rodando a partir do Matrix",
+ "Quote": "Citar",
+ "Redact": "Remover",
+ "Reject": "Rejeitar",
+ "Remove": "Remover",
+ "Remove %(name)s from the directory?": "Remover %(name)s da lista pública de salas?",
+ "remove %(name)s from the directory.": "remover %(name)s da lista pública de salas.",
+ "Remove from Directory": "Remover da lista pública de salas",
+ "Resend": "Reenviar",
+ "Riot does not know how to join a room on this network": "O Riot não sabe como entrar numa sala nesta rede",
+ "Room directory": "Lista de salas públicas",
+ "Room not found": "Sala não encontrada",
+ "Search for a room": "Pesquisar por uma sala",
+ "Settings": "Configurações",
+ "Source URL": "URL fonte",
+ "Start chat": "Iniciar conversa",
+ "The Home Server may be too old to support third party networks": "O servidor pode ser muito antigo para suportar redes de terceiros",
+ "There are advanced notifications which are not shown here": "Existem notificações avançadas que não são exibidas aqui",
+ "The server may be unavailable or overloaded": "O servidor pode estar inacessível ou sobrecarregado",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Esta sala é inacessível para convidados. Poderá conseguir entrar caso se registe.",
+ " to room": " para sala",
+ "Unable to fetch notification target list": "Não foi possível obter a lista de alvos de notificação",
+ "Unable to join network": "Não foi possível juntar-se à rede",
+ "Unable to look up room ID from server": "Não foi possível obter a identificação da sala do servidor",
+ "Unhide Preview": "Mostrar a pré-visualização novamente",
+ "unknown error code": "código de erro desconhecido",
+ "Unnamed room": "Sala sem nome",
+ "Uploaded on %(date)s by %(user)s": "Enviada em %(date)s por %(user)s",
+ "View Decrypted Source": "Ver a fonte decifrada",
+ "View Source": "Ver a fonte",
+ "When I'm invited to a room": "Quando sou convidado para uma sala",
+ "World readable": "Público",
+ "You cannot delete this image. (%(code)s)": "Não pode apagar esta imagem. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Não pode apagar esta mensagem. (%(code)s)",
+ "You are not receiving desktop notifications": "Não está a receber notificações de desktop",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Pode ter configurado num outro cliente sem ser o Riot. Não pode ajustá-las no Riot, mas ainda assim elas aplicam-se",
+ "Sunday": "Domingo",
+ "Monday": "Segunda-feira",
+ "Tuesday": "Terça-feira",
+ "Wednesday": "Quarta-feira",
+ "Thursday": "Quinta-feira",
+ "Friday": "Sexta-feira",
+ "Saturday": "Sábado",
+ "Today": "Hoje",
+ "Yesterday": "Ontem",
+ "#example": "#exemplo",
+ "Failed to remove tag %(tagName)s from room": "Não foi possível remover a marcação %(tagName)s desta sala",
+ "Welcome page": "Página de boas-vindas",
+ "Advanced notification settings": "Configurações avançadas de notificação",
+ "customServer_text": "Pode usar as opções de servidor personalizado para entrar noutros servidores Matrix especificando para isso um URL de outro Servidor de Base. Isto permite que use o Riot com uma conta Matrix que exista noutro Servidor de Base.
Também pode configurar um servidor de Identidade personalizado mas não poderá convidar utilizadores através do endereço de e-mail, ou ser convidado pelo seu endereço de e-mail.",
+ "Safari and Opera work too.": "Safari e Opera também funcionam.",
+ "All notifications are currently disabled for all targets.": "Todas as notificações estão atualmente desativadas para todos os casos.",
+ "Collapse panel": "Colapsar o painel",
+ "Expand panel": "Expandir o painel",
+ "I understand the risks and wish to continue": "Entendo os riscos e pretendo continuar",
+ "Messages containing keywords": "Mensagens contendo palavras-chave",
+ "Please install Chrome or Firefox for the best experience.": "Por favor instale Chrome ou Firefox para ter a melhor experiência.",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "O Riot usa muitas funcionalidades avançadas do navegador, algumas das quais não estão disponíveis ou ainda são experimentais no seu navegador atual.",
+ "Sorry, your browser is not able to run Riot.": "Desculpe, o seu navegador não é capaz de executar o Riot.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Com o seu navegador atual, a aparência e sensação de uso da aplicação podem estar completamente incorretas, e algumas das funcionalidades poderão não funcionar. Se quiser tentar de qualquer maneira pode continuar, mas está por sua conta com algum problema que possa encontrar!",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s em %(osName)s",
+ "A new version of Riot is available.": "Uma nova versão do Riot está disponível.",
+ "All Rooms": "Todas as salas",
+ "Cancel": "Cancelar",
+ "Changelog": "Histórico de alterações",
+ "Collecting app version information": "A recolher informação da versão da app",
+ "Collecting logs": "A recolher logs",
+ "Describe your problem here.": "Descreva o seu problema aqui.",
+ "Failed to send report: ": "Falha ao enviar o relatório: ",
+ "Hide panel": "Ocultar o painel",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Para diagnosticar problemas, relatórios deste cliente serão enviados juntamente com esta notificação de falha. Se preferir enviar apenas o texto acima, por favor remova a seleção:",
+ "Loading bug report module": "A carregar o módulo de relato de erros",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Por favor descreva a falha encontrada. O que fez? O que esperava que acontecesse? O que realmente aconteceu?",
+ "Please describe the bug and/or send logs.": "Por favor descreva a falha e/ou envie os logs de erro.",
+ "Report a bug": "Reportar uma falha",
+ "Riot Desktop on %(platformName)s": "Riot para computadores desktop em %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "O Riot não é suportado na web para dispositivos móveis. Quer instalar a app?",
+ "Search": "Pesquisar",
+ "Search…": "Pesquisar…",
+ "Send": "Enviar",
+ "Send logs": "Enviar relatórios de erro",
+ "This Room": "Esta sala",
+ "Unavailable": "Indisponível",
+ "Unknown device": "Dispositivo desconhecido",
+ "Update": "Atualizar",
+ "Uploading report": "A enviar o relatório",
+ "What's New": "Novidades",
+ "What's new?": "O que há de novo?",
+ "Waiting for response from server": "À espera de resposta do servidor",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Está a usar o Riot como convidado. Registe-se ou faça login para aceder a mais salas e funcionalidades!",
+ "OK": "Ok",
+ "You need to be using HTTPS to place a screen-sharing call.": "Necessita de estar a usar HTTPS para poder iniciar uma chamada com partilha de ecrã."
+}
diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json
new file mode 100644
index 00000000..17e3eaa7
--- /dev/null
+++ b/src/i18n/strings/pt_BR.json
@@ -0,0 +1,203 @@
+{
+ "Add an email address above to configure email notifications": "Insira um endereço de email no campo acima para configurar suas notificações por email",
+ "All messages": "Todas as mensagens",
+ "All messages (loud)": "Todas as mensagens (alto)",
+ "An error occurred whilst saving your email notification preferences.": "Um erro ocorreu enquanto o sistema estava salvando suas preferências de notificação por email.",
+ "Call invitation": "Convite para chamada",
+ "Cancel Sending": "Cancelar o envio",
+ "Can't update user notification settings": "Não é possível atualizar as preferências de notificação",
+ "Close": "Fechar",
+ "Create new room": "Criar nova sala",
+ "Couldn't find a matching Matrix room": "Não foi possível encontrar uma sala correspondente no servidor Matrix",
+ "Custom Server Options": "Opções para Servidor Personalizado",
+ "delete the alias.": "apagar o apelido da sala.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Apagar o apelido %(alias)s da sala e remover %(name)s da lista pública?",
+ "Direct Chat": "Conversa pessoal",
+ "Directory": "Diretório",
+ "Dismiss": "Descartar",
+ "Download this file": "Baixar este arquivo",
+ "Drop here %(toAction)s": "Arraste aqui %(toAction)s",
+ "Enable audible notifications in web client": "Ativar notificações de áudio no cliente web",
+ "Enable desktop notifications": "Ativar notificações no desktop",
+ "Enable email notifications": "Ativar notificações por email",
+ "Enable notifications for this account": "Ativar notificações para esta conta",
+ "Enable them now": "Habilitar agora",
+ "Enter keywords separated by a comma:": "Coloque cada palavras-chave separada por vírgula:",
+ "Error": "Erro",
+ "Error saving email notification preferences": "Erro ao salvar as preferências de notificação por email",
+ "#example:": "#exemplo",
+ "Failed to": "Falha ao",
+ "Failed to add tag %(tagName)s to room": "Falha ao adicionar %(tagName)s à sala",
+ "Failed to change settings": "Falhou ao mudar as preferências",
+ "Failed to forget room %(errCode)s": "Falhou ao esquecer a sala %(errCode)s",
+ "Failed to update keywords": "Falhou ao alterar as palavras-chave",
+ "Failed to get protocol list from Home Server": "Falha em acessar a lista de protocolos do servidor padrão",
+ "Failed to get public room list": "Falha ao acessar a lista pública de salas",
+ "Failed to join the room": "Falhou ao entrar na sala",
+ "Failed to remove tag %(tag)s from room": "Falha ao remover a palavra-chave %(tag)s da sala",
+ "Failed to set direct chat tag": "Falha ao definir conversa como pessoal",
+ "Failed to set Direct Message status of room": "Falha em definir a mensagem de status da sala",
+ "Favourite": "Favorito",
+ "Fetching third party location failed": "Falha ao acessar localização de terceiros",
+ "Files": "Arquivos",
+ "Filter room names": "Filtrar salas por título",
+ "Forget": "Esquecer",
+ "Forward Message": "Encaminhar",
+ " from room": " da sala",
+ "Guests can join": "Convidados podem entrar",
+ "Guest users can't invite users. Please register to invite.": "Usuários convidados não podem convidar outros usuários. Por gentileza se registre para enviar convites.",
+ "Invite to this room": "Convidar para esta sala",
+ "Keywords": "Palavras-chave",
+ "Leave": "Sair",
+ "Low Priority": "Baixa prioridade",
+ "Members": "Membros",
+ "Mentions only": "Apenas menções",
+ "Messages containing my display name": "Mensagens contendo meu nome público",
+ "Messages containing my user name": "Mensagens contendo meu nome de usuário",
+ "Messages in group chats": "Mensagens em salas",
+ "Messages in one-to-one chats": "Mensagens em conversas pessoais",
+ "Messages sent by bot": "Mensagens enviadas por bots",
+ "more": "ver mais",
+ "Mute": "Mudo",
+ "No rooms to show": "Não existem salas a serem exibidas",
+ "Noisy": "Barulhento",
+ "Notification targets": "Alvos de notificação",
+ "Notifications": "Notificações",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Notificações sobre as seguintes palavras-chave seguem regras que não podem ser exibidas aqui:",
+ "Notify for all other messages/rooms": "Notificar para todas as outras mensagens e salas",
+ "Notify me for anything else": "Notificar-me sobre qualquer outro evento",
+ "Off": "Desativado",
+ "On": "Ativado",
+ "Operation failed": "A operação falhou",
+ "Permalink": "Link permanente",
+ "Please Register": "Por favor, cadastre-se",
+ "powered by Matrix": "rodando a partir do Matrix",
+ "Quote": "Citar",
+ "Redact": "Remover",
+ "Reject": "Rejeitar",
+ "Remove": "Remover",
+ "Remove %(name)s from the directory?": "Remover %(name)s da lista pública de salas?",
+ "remove %(name)s from the directory.": "remover %(name)s da lista pública de salas.",
+ "Remove from Directory": "Remover da lista pública de salas",
+ "Resend": "Reenviar",
+ "Riot does not know how to join a room on this network": "O sistema não sabe como entrar na sala desta rede",
+ "Room directory": "Lista pública de salas",
+ "Room not found": "Sala não encontrada",
+ "Search for a room": "Procurar por uma sala",
+ "Settings": "Configurações",
+ "Source URL": "URL fonte",
+ "Start chat": "Iniciar conversa pessoal",
+ "The Home Server may be too old to support third party networks": "O servidor pode ser muito antigo para suportar redes de terceiros",
+ "There are advanced notifications which are not shown here": "Existem opções avançadas que não são exibidas aqui",
+ "The server may be unavailable or overloaded": "O servidor pode estar inacessível ou sobrecarregado",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Esta sala é inacessível para convidados. Você poderá entrar caso se registre.",
+ " to room": " para sala",
+ "Unable to fetch notification target list": "Não foi possível obter a lista de alvos de notificação",
+ "Unable to join network": "Não foi possível conectar na rede",
+ "Unable to look up room ID from server": "Não foi possível buscar identificação da sala no servidor",
+ "Unhide Preview": "Mostrar a pré-visualização novamente",
+ "unknown error code": "código de erro desconhecido",
+ "Unnamed room": "Sala sem nome",
+ "Uploaded on %(date)s by %(user)s": "Enviada em %(date)s por %(user)s",
+ "View Decrypted Source": "Ver a fonte descriptografada",
+ "View Source": "Ver a fonte",
+ "When I'm invited to a room": "Quando sou convidada(o) a uma sala",
+ "World readable": "Público",
+ "You cannot delete this image. (%(code)s)": "Você não pode apagar esta imagem. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Você não pode apagar esta mensagem. (%(code)s)",
+ "You are not receiving desktop notifications": "Você não está recebendo notificações desktop",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Você pode te-las configurado em outro cliente além do Riot. Você não pode ajustá-las no Riot, mas ainda assim elas se aplicam aqui",
+ "Sunday": "Domingo",
+ "Monday": "Segunda",
+ "Tuesday": "Terça",
+ "Wednesday": "Quarta",
+ "Thursday": "Quinta",
+ "Friday": "Sexta",
+ "Saturday": "Sábado",
+ "Today": "Hoje",
+ "Yesterday": "Ontem",
+ "#example": "#exemplo",
+ "Failed to remove tag %(tagName)s from room": "Não foi possível remover a marcação %(tagName)s desta sala",
+ "Welcome page": "Página de boas vindas",
+ "Advanced notification settings": "Configurações avançadas de notificação",
+ "customServer_text": "Você pode usar as opções de servidor personalizado para entrar em outros servidores Matrix, especificando uma URL de outro Servidor de Base. Isso permite que você use Riot com uma conta Matrix que exista em outro Servidor de Base.
Você também pode configurar um servidor de Identidade personalizado, mas neste caso não poderá convidar usuárias(os) pelo endereço de e-mail, ou ser convidado(a) pelo seu endereço de e-mail.",
+ "Safari and Opera work too.": "Safari e Opera funcionam também.",
+ "All notifications are currently disabled for all targets.": "Todas as notificações estão atualmente desabilitadas para todos os casos.",
+ "Collapse panel": "Colapsar o painel",
+ "Expand panel": "Expandir o painel",
+ "I understand the risks and wish to continue": "Entendo os riscos e desejo continuar",
+ "Messages containing keywords": "Mensagens contendo palavras-chave",
+ "Please install Chrome or Firefox for the best experience.": "Por favor instale Chrome ou Firefox para ter a melhor experiência de uso.",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "O Riot usa muitas funcionalidades avançadas do navegador, algumas das quais não estão disponíveis ou ainda são experimentais no seu navegador atual.",
+ "Sorry, your browser is not able to run Riot.": "Perdão. O seu navegador não é capaz de rodar o Riot.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Com o seu navegador atual, a aparência e sensação de uso da aplicação podem estar completamente incorretas, e algumas das funcionalidades poderão não funcionar. Se você quiser tentar de qualquer maneira, pode continuar, mas aí vai ter que se virar sozinho(a) com os problemas que porventura encontrar!",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s em %(osName)s",
+ "A new version of Riot is available.": "Uma nova versão do Riot está disponível.",
+ "All Rooms": "Todas as salas",
+ "Cancel": "Cancelar",
+ "Changelog": "Histórico de alterações",
+ "Collecting app version information": "Coletando informação sobre a versão do app",
+ "Collecting logs": "Coletando logs",
+ "Describe your problem here.": "Descreva o seu problema aqui.",
+ "Failed to send report: ": "Falha ao enviar o relatório: ",
+ "Hide panel": "Ocultar o painel",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Para diagnosticar problemas, relatórios deste cliente serão enviados junto a esta notificação de falha. Se você prefere apenas enviar o seu texto acima, por favor des-selecione:",
+ "Loading bug report module": "Carregando o módulo de relatórios de erros",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Por favor, descreva a falha encontrada. O que você estava fazendo? O que você esperava que devia ocorrer? E o que aconteceu efetivamente?",
+ "Please describe the bug and/or send logs.": "Por favor, descreva as falhas e/ou envie os logs de erro.",
+ "Report a bug": "Reportar uma falha",
+ "Riot Desktop on %(platformName)s": "Riot para computadores desktop em %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot versão web não é suportado a partir de celular. Quer instalar o app para celular?",
+ "Search": "Buscar",
+ "Search…": "Buscar…",
+ "Send": "Enviar",
+ "Send logs": "Enviar relatórios de erro",
+ "This Room": "Esta sala",
+ "Unavailable": "Indisponível",
+ "Unknown device": "Dispositivo desconhecido",
+ "Update": "Atualizar",
+ "Uploading report": "Enviando o relatório",
+ "What's New": "Novidades",
+ "What's new?": "O que há de novidades?",
+ "Waiting for response from server": "Esperando por resposta do servidor",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Você está usando o Riot como visitante. Registre-se ou faça login para acessar mais salas e funcionalidades!",
+ "OK": "Ok",
+ "You need to be using HTTPS to place a screen-sharing call.": "Você precisa estar usando HTTPS para poder iniciar uma chamada com compartilhamento de tela.",
+ "Login": "Fazer login",
+ "Welcome to Riot.im": "Seja bem-vinda(o) a Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by": "Colaboração descentralizada e criptografada impulsada por",
+ "Search the room directory": "Buscar na lista pública de salas",
+ "Chat with Riot Bot": "Conversar com o Bot do Riot",
+ "Get started with some tips from Riot Bot!": "Comece com algumas dicas do Bot do Riot!",
+ "General discussion about Matrix and Riot": "Discussão geral sobre o Matrix e o Riot",
+ "Discussion of all things Matrix!": "Discussão sobre todas as coisas do Matrix!",
+ "Riot/Web & Desktop chat": "Riot/chat da web e do computador desktop",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/chat do iOS e do matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Chat do Android e do matrix-android-sdk",
+ "Matrix technical discussions": "Discussões técnicas do Matrix",
+ "Running Matrix services": "Rodando serviços Matrix",
+ "Community-run support for Synapse": "Apoio ao Synapse gerido pela comunidade",
+ "Admin support for Dendrite": "Suporte de administração para Dendrite",
+ "Announcements about Synapse releases": "Anúncios sobre lançamentos do Synapse",
+ "Support for those using and running matrix-appservice-irc": "Apoio para as pessoas usando e rodando matrix-appservice-irc",
+ "Building services on Matrix": "Construindo serviços no Matrix",
+ "Support for those using the Matrix spec": "Apoio para as pessoas que estão usando as especificações Matrix",
+ "Design and implementation of E2E in Matrix": "Design e implementação de criptografia ponta-a-ponta (E2E) no Matrix",
+ "Implementing VR services with Matrix": "Implementando serviços de Realidade Virtual (VR) com Matrix",
+ "Implementing VoIP services with Matrix": "Implementando serviços VoIP com Matrix",
+ "Discussion of the Identity Service API": "Discussão do API do Serviço de Identidades",
+ "Support for those using, running and writing other bridges": "Apoio para as pessoas que estejam usando, rodando e escrevendo outras pontes (bridges)",
+ "Contributing code to Matrix and Riot": "Contribuindo com código para o Matrix e o Riot",
+ "Dev chat for the Riot/Web dev team": "Chat de desenvolvimento para o time devel do Riot/Web",
+ "Dev chat for the Dendrite dev team": "Chat de desenvolvimento para o time devel do Dendrite",
+ "Co-ordination for Riot/Web translators": "Coordenação para tradutoras(es) do Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Muitas salas já existem no Matrix, algumas independentes, e outras relacionadas a redes existentes (tais como Slack, IRC, Gitter, entre outras). Dê uma olhada na lista de salas públicas!",
+ "Failed to change password. Is your password correct?": "Não foi possível mudar a senha. A sua senha está correta?",
+ "You have successfully set a password!": "Você definiu sua senha com sucesso!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Você pode retornar agora para a sua conta depois de fazer logout, e então fazer login em outros dispositivos.",
+ "Continue": "Continuar",
+ "Please set a password!": "Por favor, defina uma senha!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Isso permitirá que você possa retornar à sua conta após fazer logout, e também fazer login em outros dispositivos.",
+ "(HTTP status %(httpStatus)s)": "(Status HTTP %(httpStatus)s)",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Chat descentralizado, criptografado e colaborativo impulsionado por [matrix]"
+}
diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json
new file mode 100644
index 00000000..aac71dfd
--- /dev/null
+++ b/src/i18n/strings/ru.json
@@ -0,0 +1,209 @@
+{
+ "Add an email address above to configure email notifications": "Добавьте email адрес для оповещений",
+ "All notifications are currently disabled for all targets.": "Все оповещения отключены.",
+ "An error occurred whilst saving your email notification preferences.": "Возникла ошибка при сохранении настроек оповещения по электронной почте.",
+ "and remove": "и удалить",
+ "Can't update user notification settings": "Не возможно обновить пользовательские настройки оповещения",
+ "Create new room": "Создать новую комнату",
+ "Couldn't find a matching Matrix room": "Не возможно найти подходящую комнату Matrix",
+ "Custom Server Options": "Собственные настройки сервера",
+ "delete the alias.": "удалить псевдоним.",
+ "Delete the room alias": "Удалить привязку комнаты",
+ "Direct Chat": "Приватный чат",
+ "Directory": "Каталог",
+ "Dismiss": "Отказ",
+ "Drop here to": "Перетащите сюда",
+ "Enable audible notifications in web client": "Включить звуковые оповещения в веб клиенте",
+ "Enable desktop notifications": "Включить оповещения на рабочем столе",
+ "Enable email notifications": "Включить оповещения по электронной почте",
+ "Enable notifications for this account": "Включить оповещения для этого аккаунта",
+ "Enable them now": "Включить сейчас",
+ "Enter keywords separated by a comma:": "Введите ключевые слова, разделенные запятой:",
+ "Error": "Ошибка",
+ "Error saving email notification preferences": "Ошибка сохранения настроек оповещений по электронной почте",
+ "#example": "#пример",
+ "Failed to": "Не удалось",
+ "Failed to add tag ": "Не удалось добавить тег ",
+ "Failed to change settings": "Не удалось изменить настройки",
+ "Failed to update keywords": "Не удалось обновить ключевые слова",
+ "Failed to get protocol list from Home Server": "Не удалось получить список протоколов с Пользовательского Сервера",
+ "Failed to get public room list": "Не удалось получить список открытых комнат",
+ "Failed to join the room": "Не удалось войти в комнату",
+ "Failed to remove tag ": "Не удалось удалить тег ",
+ "Failed to set Direct Message status of room": "Не удалось установить статус прямого сообщения в комнате",
+ "Favourite": "Избранное",
+ "Fetching third party location failed": "Не удалось получить другую локацию",
+ "Files": "Файлы",
+ "Filter room names": "Фильтр по названию комнат",
+ "Forget": "Удалить",
+ "from the directory": "из каталога",
+ " from room": " из комнаты",
+ "Guests can join": "Гость может присоединиться",
+ "Guest users can't invite users. Please register to invite.": "Гость не может приглашать пользователей. Пожалуйста зарегистрируйтесь.",
+ "Invite to this room": "Пригласить",
+ "Keywords": "Ключевые слова",
+ "Leave": "Покинуть",
+ "Low Priority": "Низкий приоритет",
+ "Members": "Пользователи",
+ "No rooms to show": "Нет комнат для отображения",
+ "Noisy": "Звук",
+ "Notification targets": "Цели уведомления",
+ "Notifications": "Уведомления",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Уведомления по следующим ключевым словам соответствуют правилам, которые нельзя отобразить здесь:",
+ "Notify for all other messages/rooms": "Уведомить обо всех других сообщениях/комнатах",
+ "Notify me for anything else": "Уведомить меня о чем либо еще",
+ "Off": "Выключить",
+ "On": "Включить",
+ "Operation failed": "Действие не удалось",
+ "Please Register": "Пожалуйста, зарегистрируйтесь",
+ "powered by Matrix": "Основано на Matrix",
+ "Reject": "Отклонить",
+ "Remove": "Удалить",
+ "remove": "удалить",
+ "Remove from Directory": "Удалить из каталога",
+ "Riot does not know how to join a room on this network": "Riot не знает как войти в комнату в этой сети",
+ "Room directory": "Каталог комнат",
+ "Room not found": "Комната не найдена",
+ "Search for a room": "Искать комнату",
+ "Settings": "Настройки",
+ "Start chat": "Начать чат",
+ "The Home Server may be too old to support third party networks": "Home Server может быть слишком старым для поддержки сторонних сетей",
+ "There are advanced notifications which are not shown here": "Существуют расширенные уведомления, которые здесь не показаны",
+ "The server may be unavailable or overloaded": "Возможно сервер недоступен или перегружен",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Эта комната недоступна для гостей. Вы можете присоединиться, если зарегистрируетесь.",
+ " to room": " к комнате",
+ "Unable to fetch notification target list": "Не удалось получить список целей уведомления",
+ "Unable to join network": "Не возможно присоединиться к сети",
+ "Unable to look up room ID from server": "Не возможно найти ID комнаты на сервере",
+ "unknown error code": "неизвестная ошибка",
+ "Unnamed room": "Комната без названия",
+ "World readable": "Доступно всем",
+ "You are not receiving desktop notifications": "Вы не получаете уведомления на рабочем столе",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Вы могли настроить их в клиенте, отличном от Riot. Вы не можете настроить их в Riot, но они все еще применяются",
+ "All messages": "Все сообщения",
+ "All messages (loud)": "Все сообщения (громко)",
+ "Cancel Sending": "Отмена отправки",
+ "Close": "Закрыть",
+ "Download this file": "Скачать этот файл",
+ "Drop here %(toAction)s": "Вставить сюда: %(toAction)s",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Удалить псевдоним комнаты %(alias)s и удалить %(name)s из каталога?",
+ "Failed to add tag %(tagName)s to room": "Не удалось добавить тег %(tagName)s в комнату",
+ "Failed to forget room %(errCode)s": "Не удалось удалить комнату %(errCode)s",
+ "Failed to remove tag %(tagName)s from room": "Не удалось убрать пометку %(tagName)s из комнаты",
+ "Failed to set direct chat tag": "Не удалось установить тег прямого чата",
+ "Unhide Preview": "Показать анонс",
+ "Uploaded on %(date)s by %(user)s": "Загружено %(date)s %(user)s",
+ "View Decrypted Source": "Просмотр расшифрованного источника",
+ "View Source": "Просмотр источника",
+ "You cannot delete this image. (%(code)s)": "Вы не можете удалить это изображение. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Вы не можете удалить это сообщение. (%(code)s)",
+ "Sunday": "Воскресенье",
+ "Monday": "Понедельник",
+ "Tuesday": "Вторник",
+ "Wednesday": "Среда",
+ "Thursday": "Четверг",
+ "Friday": "Пятница",
+ "Saturday": "Суббота",
+ "Today": "Сегодня",
+ "Yesterday": "Вчера",
+ "Mentions only": "Только упоминание",
+ "Mute": "Беззвучный",
+ "Permalink": "Постоянная ссылка",
+ "Quote": "Цитата",
+ "Redact": "Удалить",
+ "Remove %(name)s from the directory?": "Удалить %(name)s из каталога?",
+ "remove %(name)s from the directory.": "удалить %(name)s из каталога.",
+ "Resend": "Отправить снова",
+ "Source URL": "Исходный URL",
+ "Welcome page": "Домашняя страница",
+ "Advanced notification settings": "Настройки уведомлений",
+ "Call invitation": "Пригласительный звонок",
+ "customServer_text": "Вы можете войти с помощью вашего сервера. Это позволяет вам использовать Riot с уже существующей учетной записью на другом сервере.
Вы также можете задать свой сервер идентификации, но тогда вы не можете приглашать пользователей с помощью email-адреса и не можете быть приглашены по нему.",
+ "Messages containing my display name": "Сообщения, содержащие мое имя",
+ "Messages containing my user name": "Сообщение, содержащие мое имя пользователя",
+ "Messages in group chats": "Сообщения в групповых чатах",
+ "Messages in one-to-one chats": "Сообщения в приватных чатах",
+ "Messages sent by bot": "Сообщения, отправленные ботом",
+ "more": "больше",
+ "When I'm invited to a room": "Когда я приглашен в комнату",
+ "A new version of Riot is available.": "Доступна новая версия Riot.",
+ "All Rooms": "Все комнаты",
+ "Cancel": "Отмена",
+ "Changelog": "История изменений",
+ "Collapse panel": "Свернуть панель",
+ "Collecting app version information": "Сбор информации о версии приложения",
+ "Collecting logs": "Сбор протоколов",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s с %(browserName)s на %(osName)s",
+ "Safari and Opera work too.": "Safari и Opera работают тоже.",
+ "Describe your problem here.": "Опиши здесь свою проблему.",
+ "Expand panel": "Развернуть панель",
+ "Failed to send report: ": "Не удалось отослать отчет: ",
+ "Forward Message": "Переслать сообщение",
+ "Hide panel": "Скрыть панель",
+ "I understand the risks and wish to continue": "Я понимаю риск и хочу продолжить",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Чтобы диагностировать проблемы, логи этого клиента будут отправляться с этим сообщением об ошибке. Если вы предпочитаете отправить только текст выше, пожалуйста, отключите:",
+ "Loading bug report module": "Загрузка Модуля отчета об ошибках",
+ "Messages containing keywords": "Сообщения, которые содержат определенные ключевые слова",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Пожалуйста опишите (на Английском) ошибку. Что Вы делали? Что Вы ожидали получить? Что произошло?",
+ "Please describe the bug and/or send logs.": "Пожалуйста опишите ошибку и/или перешлите логи.",
+ "Please install Chrome or Firefox for the best experience.": "Пожалуйста установите Chrome или Firefox для корректной работы чата.",
+ "Report a bug": "Отчет об ошибке",
+ "Riot Desktop on %(platformName)s": "Riot Desktop на %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot может некорректно работать в мобильном браузере. Установить мобильное приложение?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot использует много расширенных функции интернет-браузера - некоторые из них отсутствуют или экспериментальные в этом браузере.",
+ "Search": "Поиск",
+ "Search…": "Поиск.…",
+ "Send": "Отослать",
+ "Send logs": "Отослать логи",
+ "Sorry, your browser is not able to run Riot.": "Извините, ваш браузер не может запустить Riot.",
+ "This Room": "Эта комната",
+ "Unavailable": "Недоступен",
+ "Unknown device": "Неизвестное устройство",
+ "Update": "Обновление",
+ "Uploading report": "Отчет загружается",
+ "What's New": "Что нового",
+ "What's new?": "Что нового?",
+ "Waiting for response from server": "Подождите ответа от сервера",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Вы вошли в Riot как гость. Зарегистрируйтесь или войдите в систему и получите доступ к огромному количеству комнат и функций!",
+ "OK": "ОК",
+ "You need to be using HTTPS to place a screen-sharing call.": "Используйте протокол HTTPS чтобы совершать видео вызов.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Если Ваш браузер не корректно отображает информацию и все или некоторые функции отключены, Вы можете и дальше этим браузером пользоваться но ваши проблемы останутся с вами!",
+ "Login": "Войти",
+ "Welcome to Riot.im": "Добро пожаловать в Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Децентрализованное, шифрованное общение и сотрудничество на основе [matrix]",
+ "Search the room directory": "Поиск по директории комнат",
+ "Chat with Riot Bot": "Пообщаться с ботом Riot",
+ "Get started with some tips from Riot Bot!": "Начните с некоторых советов от Riot бота!",
+ "General discussion about Matrix and Riot": "Общая дискуссия о Matrix и Riot",
+ "Discussion of all things Matrix!": "Дискуссия обо всем Matrix!",
+ "Riot/Web & Desktop chat": "Riot-Web & Desktop чат",
+ "Matrix technical discussions": "Техническая дискуссия о Matrix",
+ "Running Matrix services": "Запуск сервиса Matrix",
+ "Community-run support for Synapse": "Поддержка Synapse от сообщества",
+ "Admin support for Dendrite": "Админ. помощь для Dendrite",
+ "Building services on Matrix": "Разработка сервисов на Matrix",
+ "Implementing VoIP services with Matrix": "Внедрение услуги VoIP с Matrix",
+ "(HTTP status %(httpStatus)s)": "(HTTP-статус %(httpStatus)s)",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot-iOS & matrix-ios-sdk чат",
+ "Riot/Android & matrix-android-sdk chat": "Riot-Android & matrix-android-sdk чат",
+ "Announcements about Synapse releases": "Объявления релизов Synapse",
+ "Support for those using and running matrix-appservice-irc": "Поддержка тех, кто использует matrix-appservice-irc",
+ "You have successfully set a password!": "Вы успешно установили пароль!",
+ "Continue": "Продолжить",
+ "Please set a password!": "Задайте пароль!",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "В Matrix существует множество комнат, связанных с существующими сетями (Slack, IRC, Gitter и т.д.) Или независимыми. Ищите в каталоге!",
+ "Failed to change password. Is your password correct?": "Не удалось сменить пароль. Вы правильно ввели текущий пароль?",
+ "You can now return to your account after signing out, and sign in on other devices.": "Теперь Вы можете вернуться в свою учетную запись после выхода из системы, и войти в систему на других устройствах.",
+ "Support for those using the Matrix spec": "Поддержка для тех, кто использует спецификацию Matrix",
+ "Design and implementation of E2E in Matrix": "Разработка и внедрение E2E в Matrix",
+ "Implementing VR services with Matrix": "Внедрение служб VR с помощью Matrix",
+ "Discussion of the Identity Service API": "Обсуждение службы идентификации API",
+ "Support for those using, running and writing other bridges": "Поддержка тех, кто использует, работает и пишет другие мосты (bridges)",
+ "Contributing code to Matrix and Riot": "Взаимодействующий код для Matrix и Riot",
+ "Dev chat for the Riot/Web dev team": "Dev chat для группы разработчиков Riot/Web",
+ "Dev chat for the Dendrite dev team": "Dev chat для группы разработчиков Dendrite",
+ "Co-ordination for Riot/Web translators": "Координирование для переводчиков Riot / Web",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Это позволит Вам вернуться в свою учетную запись после выхода, и войти в систему на других устройствах.",
+ "You have successfully set a password and an email address!": "Пароль и адрес электронной почты успешно сохранены!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Помните, Вы всегда можете указать адрес электронной почты в пользовательских настройках, если передумаете."
+}
diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json
new file mode 100644
index 00000000..146e237d
--- /dev/null
+++ b/src/i18n/strings/sv.json
@@ -0,0 +1,161 @@
+{
+ "Add an email address above to configure email notifications": "Lägg till en epostadress här för att konfigurera epostaviseringar",
+ "Advanced notification settings": "Avancerade aviseringsinställingar",
+ "All messages": "Alla meddelanden",
+ "All messages (loud)": "Alla meddelanden (högljudd)",
+ "All notifications are currently disabled for all targets.": "Alla aviseringar är för tillfället avstängda för alla mål.",
+ "An error occurred whilst saving your email notification preferences.": "Ett fel uppstod då epostaviseringsinställningarna sparades.",
+ "Call invitation": "Inbjudan till samtal",
+ "Cancel Sending": "Avbryt sändning",
+ "Can't update user notification settings": "Kan inte uppdatera aviseringsinställningarna",
+ "Close": "Stäng",
+ "Create new room": "Nytt rum",
+ "Couldn't find a matching Matrix room": "Kunde inte hitta ett matchande Matrix-rum",
+ "Custom Server Options": "Egna serverinställningar",
+ "customServer_text": "Du kan använda serverinställningarna för att logga in i en annan Matrix-server genom att specifiera en URL till en annan hemserver. Så här kan du använda Riot med ett existerande Matrix-konto på en annan hemserver.
Du kan också specifiera en egen identitetsserver, men du kommer inte att kunna bjuda in andra via epostadress, eller bli inbjuden via epostadress.",
+ "delete the alias.": "radera adressen.",
+ "Direct Chat": "Direkt-chatt",
+ "Directory": "Katalog",
+ "Dismiss": "Avvisa",
+ "Download this file": "Ladda ner filen",
+ "Drop here %(toAction)s": "Dra hit för att %(toAction)s",
+ "Enable audible notifications in web client": "Sätt på högljudda aviseringar i webbklienten",
+ "Enable desktop notifications": "Sätt på skrivbordsaviseringar",
+ "Enable email notifications": "Sätt på epostaviseringar",
+ "Enable notifications for this account": "Sätt på aviseringar för det här kontot",
+ "Enable them now": "Sätt på nu",
+ "Enter keywords separated by a comma:": "Skriv in nyckelord, separerade med kommatecken:",
+ "Error": "Fel",
+ "Error saving email notification preferences": "Ett fel uppstod då epostaviseringsinställningarna sparades",
+ "Failed to": "Det gick inte att",
+ "Failed to add tag %(tagName)s to room": "Det gick inte att lägga till \"%(tagName)s\" till rummet",
+ "Failed to change settings": "Det gick inte att spara inställningarna",
+ "Failed to forget room %(errCode)s": "Det gick inte att glömma bort rummet %(errCode)s",
+ "Failed to update keywords": "Det gick inte att uppdatera nyckelorden",
+ "Failed to get protocol list from Home Server": "Det gick inte att hämta protokollistan från hemservern",
+ "Failed to get public room list": "Det gick inte att hämta listan över offentliga rum",
+ "Failed to join the room": "Det gick inte att gå med i rummet",
+ "Failed to remove tag %(tagName)s from room": "Det gick inte att radera taggen %(tagName)s från rummet",
+ "Failed to set direct chat tag": "Det gick inte att markera rummet som direkt chatt",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s på %(osName)s",
+ "Safari and Opera work too.": "Safari och Opera fungerar också.",
+ "A new version of Riot is available.": "En ny version av Riot är tillgänglig.",
+ "All Rooms": "Alla rum",
+ "Cancel": "Avbryt",
+ "Changelog": "Ändringslogg",
+ "Collapse panel": "Kollapsa panel",
+ "Describe your problem here.": "Beskriv problemet här.",
+ "Expand panel": "Öppna panel",
+ "Failed to send report: ": "Det gick inte att sända rapporten: ",
+ "Failed to set Direct Message status of room": "Det gick inte att sätta Direkt meddelande-status på rummet",
+ "Favourite": "Favorit",
+ "Files": "Filer",
+ "Filter room names": "Filtrera rumsnamn",
+ "Forget": "Glöm bort",
+ "Forward Message": "Vidarebefordra meddelande",
+ " from room": " från rum",
+ "Guests can join": "Gäster kan bli medlem i rummet",
+ "Guest users can't invite users. Please register to invite.": "Gäster kan inte skicka inbjudningar. Registrera dig för att bjuda in andra.",
+ "Hide panel": "Göm panel",
+ "I understand the risks and wish to continue": "Jag förstår riskerna och vill fortsätta",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "För att diagnostisera problem kommer loggar från den här klienten att sändas med rapporten. Om du bara vill sända texten ovan, kryssa av rutan:",
+ "Invite to this room": "Bjud in i rummet",
+ "Keywords": "Nyckelord",
+ "Leave": "Lämna",
+ "Loading bug report module": "Laddar buggrapportsmodul",
+ "Low Priority": "Låg prioritet",
+ "Members": "Medlemmar",
+ "Mentions only": "Endast omnämnande",
+ "Messages containing my display name": "Meddelanden som innehåller mitt namn",
+ "Messages containing keywords": "Meddelanden som innehåller nyckelord",
+ "Messages containing my user name": "Meddelanden som innehåller mitt användarnamn",
+ "Messages in group chats": "Meddelanden i gruppchattar",
+ "Messages in one-to-one chats": "Meddelanden i privata chattar",
+ "Messages sent by bot": "Meddelanden från bottar",
+ "more": "mera",
+ "Mute": "Dämpa",
+ "No rooms to show": "Inga fler rum att visa",
+ "Noisy": "Högljudd",
+ "Notification targets": "Aviseringsmål",
+ "Notifications": "Aviseringar",
+ "Notify for all other messages/rooms": "Avisera för alla andra meddelanden/rum",
+ "Notify me for anything else": "Avisera för allt annat",
+ "Off": "Av",
+ "On": "På",
+ "Permalink": "Permalink",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Beskriv buggen. Vad gjorde du? Vad förväntade du dig att ska hända? Vad hände?",
+ "Please describe the bug and/or send logs.": "Beskriv buggen och/eller sänd loggar.",
+ "Please install Chrome or Firefox for the best experience.": "Installera Chrome eller Firefox för den bästa upplevelsen.",
+ "Please Register": "Registrera dig",
+ "powered by Matrix": "drivs av Matrix",
+ "Quote": "Citera",
+ "Redact": "Dra tillbaka",
+ "Reject": "Avvisa",
+ "Remove %(name)s from the directory?": "Ta bort %(name)s från katalogen?",
+ "Remove": "Ta bort",
+ "remove %(name)s from the directory.": "ta bort %(name)s från katalogen.",
+ "Remove from Directory": "Ta bort från katalogen",
+ "Report a bug": "Rapportera en bugg",
+ "Resend": "Sänd igen",
+ "Riot Desktop on %(platformName)s": "Riot Desktop på %(platformName)s",
+ "Riot does not know how to join a room on this network": "Riot kan inte gå med i ett rum på det här nätverket",
+ "Riot is not supported on mobile web. Install the app?": "Riot stöds inte på mobil-webb. Installera appen?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot använder flera avancerade webbläsaregenskaper, av vilka alla inte stöds eller är experimentella i din nuvarande webbläsare.",
+ "Room directory": "Rumskatalog",
+ "Room not found": "Rummet hittades inte",
+ "Search": "Sök",
+ "Search…": "Sök…",
+ "Search for a room": "Sök efter rum",
+ "Send": "Sänd",
+ "Send logs": "Sänd loggar",
+ "Settings": "Inställningar",
+ "Source URL": "Käll-URL",
+ "Sorry, your browser is not able to run Riot.": "Beklagar, din webbläsare kan inte köra Riot.",
+ "Start chat": "Starta chatt",
+ "The Home Server may be too old to support third party networks": "Hemservern kan vara för gammal för stöda tredje parters nätverk",
+ "There are advanced notifications which are not shown here": "Det finns avancerade aviseringar som inte visas här",
+ "The server may be unavailable or overloaded": "Servern kan vara överbelastad eller inte tillgänglig",
+ "This Room": "Det här rummet",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Det här rummet är inte tillgängligt till gäster. Du kan möjligtvis gå med i rummet om du registrerar dig.",
+ " to room": " till rum",
+ "Unable to fetch notification target list": "Det gick inte att hämta aviseringsmållistan",
+ "Unable to join network": "Det gick inte att ansluta till nätverket",
+ "Unable to look up room ID from server": "Det gick inte att hämta rums-ID:t från servern",
+ "Unavailable": "Inte tillgänglig",
+ "Unhide Preview": "Visa förhandsvisning",
+ "Unknown device": "Okänd enhet",
+ "unknown error code": "okänd felkod",
+ "Unnamed room": "Namnlöst rum",
+ "Update": "Uppdatera",
+ "Uploaded on %(date)s by %(user)s": "%(user)s laddade upp %(date)s",
+ "Uploading report": "Laddar upp rapport",
+ "View Decrypted Source": "Visa dekrypterad källa",
+ "View Source": "Visa källa",
+ "What's New": "Vad är nytt",
+ "What's new?": "Vad är nytt?",
+ "Waiting for response from server": "Väntar på svar från servern",
+ "When I'm invited to a room": "När jag bjuds in till ett rum",
+ "World readable": "Alla kan läsa",
+ "You cannot delete this image. (%(code)s)": "Du kan inte radera den här bilden. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Du kan inte radera det här meddelandet. (%(code)s)",
+ "You are not receiving desktop notifications": "Du får inte skrivbordsaviseringar",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Du använder Riot som en gäst. Registrera dig eller logga in för att få tillgång till flera rum och egenskaper!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Du kan ha konfigurerat dem i en annan klient än Riot. Du kan inte ändra dem i Riot men de tillämpas ändå",
+ "Sunday": "söndag",
+ "Monday": "måndag",
+ "Tuesday": "tisdag",
+ "Wednesday": "onsdag",
+ "Thursday": "torsdag",
+ "Friday": "fredag",
+ "Saturday": "lördag",
+ "Today": "idag",
+ "Yesterday": "igår",
+ "OK": "OK",
+ "You need to be using HTTPS to place a screen-sharing call.": "Du måste använda HTTPS för att dela din skärm.",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Med din nuvarande webbläsare kan appens utseende vara helt fel, och vissa eller alla egenskaper kommer nödvändigtvis inte att fungera. Om du ändå vill försöka så kan du fortsätta, men gör det på egen risk!",
+ "Welcome page": "Välkomstsida",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Radera rumsadressen %(alias)s och ta bort %(name)s från katalogen?",
+ "Collecting logs": "Samlar in loggar",
+ "Collecting app version information": "Samlar in appversionsinformation",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Aviseringar för följande nyckelord följer regler som inte kan visas här:"
+}
diff --git a/src/i18n/strings/te.json b/src/i18n/strings/te.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/src/i18n/strings/te.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/src/i18n/strings/th.json b/src/i18n/strings/th.json
new file mode 100644
index 00000000..27483243
--- /dev/null
+++ b/src/i18n/strings/th.json
@@ -0,0 +1,203 @@
+{
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s ผ่านทาง %(browserName)s บน %(osName)s",
+ "All messages": "ทุกข้อความ",
+ "Cancel": "ยกเลิก",
+ "Close": "ปิด",
+ "Error": "ข้อผิดพลาด",
+ "#example": "#example",
+ "Files": "ไฟล์",
+ "Forward Message": "ส่งต่อข้อความ",
+ " from room": " จากห้อง",
+ "Low Priority": "ความสำคัญต่ำ",
+ "Members": "สมาชิก",
+ "more": "เพิ่มเติม",
+ "Off": "ปิด",
+ "Report a bug": "รายงานจุดบกพร่อง",
+ "powered by Matrix": "ใช้เทคโนโลยี Matrix",
+ "Quote": "อ้างอิง",
+ "Resend": "ส่งใหม่",
+ "Safari and Opera work too.": "Safari หรือ Opera ก็ใช้ได้",
+ "A new version of Riot is available.": "มี Riot เวอร์ชั่นใหม่",
+ "All Rooms": "ทุกห้อง",
+ "Cancel Sending": "ยกเลิกการส่ง",
+ "Changelog": "บันทึกการเปลี่ยนแปลง",
+ "Create new room": "สร้างห้องใหม่",
+ "Describe your problem here.": "อธิบายปัญหาที่นี่",
+ "Download this file": "ดาวน์โหลดไฟล์นี้",
+ "Dismiss": "ไม่สนใจ",
+ "Messages sent by bot": "ข้อความจากบอท",
+ "Mute": "เงียบ",
+ "No rooms to show": "ไม่มีห้องที่จะแสดง",
+ "Notifications": "การแจ้งเตือน",
+ "On": "เปิด",
+ "Permalink": "ลิงก์ถาวร",
+ "Operation failed": "การดำเนินการล้มเหลว",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "กรุณาอธิบายจุดบกพร่อง คุณทำอะไร? ควรจะเกิดอะไรขึ้น? แล้วอะไรคือสิ่งที่เกิดขึ้นจริง?",
+ "Please describe the bug and/or send logs.": "กรุณาอธิบายจุดบกพร่อง และ/หรือ ส่งล็อก",
+ "Please install Chrome or Firefox for the best experience.": "กรุณาติดตั้ง Chrome หรือ Firefox เพื่อประสบการณ์ที่ดีที่สุด",
+ "Please Register": "กรุณาลงทะเบียน",
+ "Redact": "ลบ",
+ "Reject": "ปฏิเสธ",
+ "Remove": "ลบ",
+ "Messages containing keywords": "ข้อความที่มีคีย์เวิร์ด",
+ "Messages containing my user name": "ข้อความที่มีชื่อผู้ใช้ของฉัน",
+ "Search": "ค้นหา",
+ "Search…": "ค้นหา…",
+ "Room not found": "ไม่พบห้อง",
+ "Search for a room": "ค้นหาห้อง",
+ "Send": "ส่ง",
+ "Send logs": "ส่งล็อก",
+ "Settings": "การตั้งค่า",
+ "Sorry, your browser is not able to run Riot.": "ขออภัย เบราว์เซอร์ของคุณไม่สามารถ run Riot ได้",
+ "This Room": "ห้องนี้",
+ " to room": " ไปยังห้อง",
+ "Unavailable": "ไม่มี",
+ "Unknown device": "อุปกรณ์ที่ไม่รู้จัก",
+ "unknown error code": "รหัสข้อผิดพลาดที่ไม่รู้จัก",
+ "Update": "อัปเดต",
+ "Uploaded on %(date)s by %(user)s": "อัปโหลดเมื่อ %(date)s โดย %(user)s",
+ "Yesterday": "เมื่อวานนี้",
+ "Today": "วันนี้",
+ "Saturday": "วันเสาร์",
+ "Friday": "วันศุกร์",
+ "Thursday": "วันพฤหัสบดี",
+ "Wednesday": "วันพุธ",
+ "Tuesday": "วันอังคาร",
+ "Monday": "วันจันทร์",
+ "Sunday": "วันอาทิตย์",
+ "You cannot delete this image. (%(code)s)": "คุณไม่สามารถลบรูปนี้ได้ (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "คุณไม่สามารถลบข้อความนี้ได้ (%(code)s)",
+ "What's New": "มีอะไรใหม่",
+ "What's new?": "มีอะไรใหม่?",
+ "View Source": "ดูซอร์ส",
+ "Uploading report": "กำลังอัปโหลดรายงาน",
+ "Advanced notification settings": "ตั้งค่าการแจ้งเตือนขั้นสูง",
+ "Can't update user notification settings": "ไม่สามารถอัปเดตการตั้งค่าการแจ้งเตือนของผู้ใช้",
+ "Collecting logs": "กำลังรวบรวมล็อก",
+ "Collapse panel": "ซ่อนหน้าต่าง",
+ "Collecting app version information": "กำลังรวบรวมข้อมูลเวอร์ชันแอป",
+ "OK": "ตกลง",
+ "Welcome page": "หน้าต้อนรับ",
+ "You need to be using HTTPS to place a screen-sharing call.": "คุณต้องใช้ HTTPS เพื่อเริ่มติดต่อแบบแบ่งปันหน้าจอ",
+ "You are not receiving desktop notifications": "การแจ้งเตือนบนเดสก์ทอปถูกปิดอยู่",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "คุณกำลังใช้ Riot ในฐานะแขก ลงทะเบียนหรือเข้าสู่ระบบเพื่อเข้าถึงห้องและคุณสมบัติอื่น ๆ เพิ่มเติม!",
+ "Waiting for response from server": "กำลังรอการตอบสนองจากเซิร์ฟเวอร์",
+ "View Decrypted Source": "ดูซอร์สที่ถอดรหัสแล้ว",
+ "Unnamed room": "ห้องที่ไม่มีชื่อ",
+ "Source URL": "URL ต้นฉบับ",
+ "Start chat": "เริ่มแชท",
+ "Riot Desktop on %(platformName)s": "Riot เดสก์ทอปบน %(platformName)s",
+ "Riot is not supported on mobile web. Install the app?": "Riot ไม่รองรับเว็บบนอุปกรณ์พกพา ติดตั้งแอป?",
+ "Riot does not know how to join a room on this network": "Riot ไม่รู้วิธีเข้าร่วมห้องในเครือข่ายนี้",
+ "Direct Chat": "แชทโดยตรง",
+ "All messages (loud)": "ทุกข้อความ (เสียงดัง)",
+ "Custom Server Options": "กำหนดเซิร์ฟเวอร์เอง",
+ "Directory": "ไดเรกทอรี",
+ "Enable audible notifications in web client": "เปิดใช้งานเสียงแจ้งเตือนบนเว็บไคลเอนต์",
+ "Enable desktop notifications": "เปิดใช้งานการแจ้งเตือนบนเดสก์ทอป",
+ "Enable email notifications": "เปิดใช้งานการแจ้งเตือนทางอีเมล",
+ "Enable notifications for this account": "เปิดใช้งานการแจ้งเตือนสำหรับบัญชีนี้",
+ "Enable them now": "เปิดใช้งานเดี๋ยวนี้",
+ "Enter keywords separated by a comma:": "กรอกคีย์เวิร์ดทั้งหมด คั่นด้วยเครื่องหมายจุลภาค:",
+ "Expand panel": "ขยายหน้าต่าง",
+ "Failed to update keywords": "การอัปเดตคีย์เวิร์ดล้มเหลว",
+ "Failed to join the room": "การเข้าร่วมห้องล้มเหลว",
+ "Failed to remove tag %(tagName)s from room": "การลบแท็ก %(tagName)s จากห้องล้มเหลว",
+ "Failed to send report: ": "การส่งรายงานล้มเหลว: ",
+ "Filter room names": "กรองชื่อห้อง",
+ "Guests can join": "แขกเข้าร่วมได้",
+ "Hide panel": "ซ่อนหน้าต่าง",
+ "I understand the risks and wish to continue": "ฉันเข้าใจความเสี่ยงและต้องการดำเนินการต่อ",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "ล็อกจากไคลเอนต์จะถูกแนบพร้อมกับรายงานนี้เพื่อวินิจฉัยปัญหา หากคุณต้องการส่งเฉพาะข้อความด้านบน กรุณาเอาเครื่องหมายออก:",
+ "Invite to this room": "เชิญเข้าห้องนี้",
+ "Keywords": "คีย์เวิร์ด",
+ "Leave": "ออกจากห้อง",
+ "Loading bug report module": "กำลังโหลดโมดูลรายงานจุดบกพร่อง",
+ "Mentions only": "เมื่อถูกกล่าวถึงเท่านั้น",
+ "Messages containing my display name": "ข้อความที่มีชื่อของฉัน",
+ "Messages in group chats": "ข้อความในแชทกลุ่ม",
+ "Messages in one-to-one chats": "ข้อความในแชทตัวต่อตัว",
+ "Noisy": "เสียงดัง",
+ "Notification targets": "เป้าหมายการแจ้งเตือน",
+ "Notify for all other messages/rooms": "แจ้งเตือนจากห้อง/ข้อความอื่น ๆ ทั้งหมด",
+ "Notify me for anything else": "แจ้งเตือนสำหรับอย่างอื่นทั้งหมด",
+ "Remove %(name)s from the directory?": "ถอด %(name)s ออกจากไดเรกทอรี?",
+ "remove %(name)s from the directory.": "ถอด %(name)s ออกจากไดเรกทอรี",
+ "Remove from Directory": "ถอดออกจากไดเรกทอรี",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot ใช้คุณสมบัติขั้นสูงในเบราว์เซอร์หลายประการ คุณสมบัติบางอย่างอาจยังไม่พร้อมใช้งานหรืออยู่ในขั้นทดลองในเบราว์เซอร์ปัจจุบันของคุณ",
+ "Room directory": "ไดเรกทอรีห้อง",
+ "There are advanced notifications which are not shown here": "มีการแจ้งเตือนขั้นสูงที่ไม่ได้แสดงที่นี่",
+ "This room is inaccessible to guests. You may be able to join if you register.": "แขกไม่มีสิทธิ์เข้าถึงห้องนี้ หากคุณลงทะเบียนคุณอาจเข้าร่วมได้",
+ "Unable to join network": "ไม่สามารถเข้าร่วมเครือข่ายได้",
+ "Unable to look up room ID from server": "ไม่สามารถหา ID ห้องจากเซิร์ฟเวอร์ได้",
+ "Unhide Preview": "แสดงตัวอย่าง",
+ "World readable": "ทุกคนอ่านได้",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "คุณอาจมีการตั้งค่าจากไคลเอนต์อื่นนอกจาก Riot การตั้งต่าเหล่านั้นยังถูกใช้งานอยู่แต่คุณจะปรับแต่งจากใน Riot ไม่ได้",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "การแสดงผลของโปรแกรมอาจผิดพลาด ฟังก์ชันบางอย่างหรือทั้งหมดอาจไม่ทำงานในเบราว์เซอร์ปัจจุบันของคุณ หากคุณต้องการลองดำเนินการต่อ คุณต้องรับมือกับปัญหาที่อาจจะเกิดขึ้นด้วยตัวคุณเอง!",
+ "Add an email address above to configure email notifications": "เพิ่มที่อยู่อีเมลข้างบนเพื่อตั้งค่าการแจ้งเตือนทางอีเมล",
+ "All notifications are currently disabled for all targets.": "การแจ้งเตือนทั้งหมดถูกปิดใช้งานสำหรับทุกอุปกรณ์",
+ "An error occurred whilst saving your email notification preferences.": "เกิดข้อผิดพลาดระหว่างบันทึกการตั้งค่าการแจ้งเตือนทางอีเมล",
+ "Couldn't find a matching Matrix room": "ไม่พบห้อง Matrix ที่ตรงกับคำค้นหา",
+ "customServer_text": "คุณสามารถกำหนดเซิร์ฟเวอร์บ้านเองได้โดยใส่ URL ของเซิร์ฟเวอร์นั้น เพื่อเข้าสู่ระบบของเซิร์ฟเวอร์ Matrix อื่น ทั้งนี่เพื่อให้คุณสามารถใช้ Riot กับบัญชี Matrix ที่มีอยู่แล้วบนเซิร์ฟเวอร์บ้านอื่น ๆ ได้
คุณอาจเลือกเซิร์ฟเวอร์ระบุตัวตนเองด้วยก็ได้ แต่คุณจะไม่สามารถเชิญผู้ใช้อื่นด้วยที่อยู่อีเมล หรือรับคำเชิญจากผู้ใช้อื่นทางที่อยู่อีเมลได้",
+ "delete the alias.": "ลบนามแฝง",
+ "Drop here %(toAction)s": "ปล่อยที่นี่%(toAction)s",
+ "Error saving email notification preferences": "การบันทึกการตั้งค่าการแจ้งเตือนทางอีเมลผิดพลาด",
+ "Failed to add tag %(tagName)s to room": "การเพิ่มแท็ก %(tagName)s ของห้องนี้ล้มเหลว",
+ "Failed to change settings": "การแก้ไขการตั้งค่าล้มเหลว",
+ "Failed to get protocol list from Home Server": "การขอรายชื่อโปรโตคอลจากเซิร์ฟเวอร์บ้านล้มเหลว",
+ "Failed to get public room list": "การขอรายชื่อห้องสาธารณะล้มเหลว",
+ "Failed to set direct chat tag": "การติดแท็กแชทตรงล้มเหลว",
+ "Failed to set Direct Message status of room": "การตั้งสถานะข้อความตรงของห้องล้มเหลว",
+ "Favourite": "รายการโปรด",
+ "Failed to": "ล้มเหลวในการ",
+ "Fetching third party location failed": "การเรียกข้อมูลตำแหน่งจากบุคคลที่สามล้มเหลว",
+ "Guest users can't invite users. Please register to invite.": "แขกไม่สามารถเชิญผู้ใช้ได้ กรุณาลงทะเบียนเพื่อเชิญผู้อื่น",
+ "The Home Server may be too old to support third party networks": "เซิร์ฟเวอร์บ้านอาจเก่าเกินกว่าจะรองรับเครือข่ายของบุคคลที่สาม",
+ "The server may be unavailable or overloaded": "เซิร์ฟเวอร์อาจไม่พร้อมใช้งานหรือทำงานหนักเกินไป",
+ "Unable to fetch notification target list": "ไม่สามารถรับรายชื่ออุปกรณ์แจ้งเตือน",
+ "When I'm invited to a room": "เมื่อฉันได้รับคำเชิญเข้าห้อง",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "ลบนามแฝง %(alias)s ของห้องและถอด %(name)s ออกจากไดเรกทอรี?",
+ "Call invitation": "คำเชิญเข้าร่วมการโทร",
+ "Failed to forget room %(errCode)s": "การลืมห้องล้มเหลว %(errCode)s",
+ "Forget": "ลืม",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "การแจ้งเตือนจากคีย์เวิร์ดเหล่านี้ เป็นไปตามกฏที่ไม่สามารถแสดงที่นี่ได้:",
+ "Login": "เข้าสู่ระบบ",
+ "Welcome to Riot.im": "ยินดีต้อนรับสู่ Riot.im",
+ "Search the room directory": "ค้นหาในไดเรกทอรีห้อง",
+ "Chat with Riot Bot": "แชทกับบอท Riot",
+ "Get started with some tips from Riot Bot!": "มาเริ่มกันด้วยเคล็ดลับเล็กน้อยจากบอท Riot!",
+ "General discussion about Matrix": "พูดคุยเรื่องทั่วไปเกี่ยวกับ Matrix",
+ "Discussion of all things Matrix!": "พูดคุยทุกเรื่อง เรื่อง Matrix!",
+ "Riot/Web & Desktop chat": "แชทเกี่ยวกับ Riot บนเว็บและเดสก์ทอป",
+ "Riot/iOS & matrix-ios-sdk chat": "แชทเกี่ยวกับ Riot บน iOS และ matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "แชทเกี่ยวกับ Riot บน Android และ matrix-android-sdk",
+ "Matrix technical discussions": "พูดคุยเรื่อง Matrix ทางเทคนิค",
+ "Running Matrix services": "การติดตั้งบริการ Matrix",
+ "Community-run support for Synapse": "ฝ่ายสนับสนุน Synapse โดยชุมชนผู้ใช้",
+ "Admin support for Dendrite": "ฝ่ายสนับสนุน Dendrite จากผู้ดูแล",
+ "Announcements about Synapse releases": "ประกาศเกี่ยวกับ Synapse รุ่นใหม่",
+ "Support for those using and running matrix-appservice-irc": "ฝ่ายสนับสนุนสำหรับผู้ใช้ matrix-appservice-irc",
+ "Building services on Matrix": "การพัฒนาบริการบน Matrix",
+ "Support for those using the Matrix spec": "ฝ่ายสนับสนุนสำหรับผู้ใช้สเปค Matrix",
+ "Implementing VR services with Matrix": "การอิมพลีเมนต์บริการ VR ด้วย Matrix",
+ "Implementing VoIP services with Matrix": "การอิมพลีเมนต์บริการ VoIP ด้วย Matrix",
+ "Support for those using, running and writing other bridges": "ฝ่ายสนับสนุนสำหรับผู้ใช้หรือพัฒนาตัวเชื่อมอื่น ๆ",
+ "Contributing code to Matrix and Riot": "สมทบโค๊ดกับ Matrix และ Riot",
+ "Dev chat for the Riot/Web dev team": "แชทสำหรับทีมพัฒนา Riot บนเว็บ",
+ "Dev chat for the Dendrite dev team": "แชทสำหรับทีมพัฒนา Dendrite",
+ "Co-ordination for Riot/Web translators": "แชทสำหรับประสานงานการแปล Riot บนเว็บ",
+ "Failed to change password. Is your password correct?": "การเปลี่ยนรหัสผ่านล้มเหลว รหัสผ่านของคุณถูกต้องหรือไม่?",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "มีห้องอยู่มากมายใน Matrix ทั้งห้องที่เชื่อมไปยังเครือข่ายอื่น (Slack, IRC, Gitter ฯลฯ) และห้องที่อยู่ด้วยตัวเอง ลองดูไดเรกทอรีสิ!",
+ "You have successfully set a password!": "การตั้งรหัสผ่านเสร็จสมบูรณ์!",
+ "You can now return to your account after signing out, and sign in on other devices.": "คุณสามารถกลับไปยังบัญชีของคุณหลังจากออกจากระบบ แล้วกลับเขาสู่ระบบบนอุปกรณ์อื่น ๆ",
+ "Continue": "ดำเนินการต่อ",
+ "Please set a password!": "กรุณาตั้งรหัสผ่าน!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "เพื่อคุณจะได้กลับมายังบัญชีเดิมของคุณได้ หลังจากออกจากระบบ แล้วกลับเข้าสู่ระบบในอุปกรณ์อื่น ๆ",
+ "Design and implementation of E2E in Matrix": "การออกแบบและใช้งาน E2E ใน Matrix",
+ "Discussion of the Identity Service API": "พูดคุยเกี่ยวกับ Identity Service API",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "ระบบแชทและประสานงาน ไร้ศูนย์กลางและเข้ารหัสได้ โดยใช้เทคโนโลยีจาก [matrix]",
+ "General discussion about Matrix and Riot": "พูดคุยเรื่องทั่วไป ทั้ง Matrix และ Riot",
+ "(HTTP status %(httpStatus)s)": "(สถานะ HTTP %(httpStatus)s)",
+ "Remember, you can always set an email address in user settings if you change your mind.": "อย่าลืม คุณสามารถตั้งที่อยู่อีเมลในการตั้งค่าผู้ใช้ได้ทุกเมื่อหากคุณเปลี่ยนใจ",
+ "You have successfully set a password and an email address!": "ตั้งรหัสผ่านและที่อยู่อีเมลสำเร็จแล้ว!"
+}
diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json
new file mode 100644
index 00000000..9d97d7cb
--- /dev/null
+++ b/src/i18n/strings/tr.json
@@ -0,0 +1,202 @@
+{
+ "%(appName)s via %(browserName)s on %(osName)s": "%(osName)s işletim sisteminde %(browserName)s ile %(appName)s",
+ "Safari and Opera work too.": " Safari ve Opera da çalışıyor.",
+ "A new version of Riot is available.": "Riot'un yeni bir versiyonu mevcuttur.",
+ "Add an email address above to configure email notifications": "E-posta bildirimlerini yapılandırmak için yukarıya bir e-posta adresi ekleyin",
+ "Advanced notification settings": "Gelişmiş bildirim ayarları",
+ "All messages": "Tüm mesajlar",
+ "All messages (loud)": "Tüm mesajlar (uzun)",
+ "All Rooms": "Tüm Odalar",
+ "All notifications are currently disabled for all targets.": "Tüm bildirimler şu anda tüm hedefler için devre dışı bırakılmıştır.",
+ "An error occurred whilst saving your email notification preferences.": "E-posta bildirim tercihlerinizi kaydetme işlemi sırasında bir hata oluştu.",
+ "Call invitation": "Arama davetiyesi",
+ "Cancel": "İptal Et",
+ "Cancel Sending": "Göndermeyi İptal Et",
+ "Can't update user notification settings": "Kullanıcı bildirim ayarları güncellenemiyor",
+ "Changelog": "Değişiklikler",
+ "Close": "Kapat",
+ "Collapse panel": "Katlanır panel",
+ "Collecting app version information": "Uygulama sürümü bilgileri toplanıyor",
+ "Collecting logs": "Kayıtlar toplanıyor",
+ "Create new room": "Yeni oda oluştur",
+ "Couldn't find a matching Matrix room": "Eşleşen bir Matrix odası bulunamadı",
+ "Custom Server Options": "Özel Sunucu Seçenekleri",
+ "customServer_text": "Farklı bir Ana Sunucu URL'si belirleyerek başka bir Matrix sunucusunda oturum açmak için Özel Sunucu Seçeneklerini kullanabilirsiniz. Bu , Riot'u mevcut Matrix hesabı ile farklı bir Ana Sunucuda kullanmanıza olanak tanır.
Ayrıca Özel Kimlik Sunucu'da ayarlayabilirsiniz ama kullanıcıları e-posta adresleriyle veya kendi e-posta adresinizle davet edemezsiniz.",
+ "delete the alias.": "Tüm rumuzları sil.",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "%(alias)s oda rumuzu silinsin ve %(name)s dizinden kaldırılsın mı ?",
+ "Describe your problem here.": "Probleminizi burada açıklayın.",
+ "Direct Chat": "Doğrudan Sohbet",
+ "Directory": "Dizin",
+ "Dismiss": "Reddet",
+ "Download this file": "Bu dosyayı indir",
+ "Drop here %(toAction)s": "Burayı terket %(toAction)s",
+ "Enable audible notifications in web client": "Web istemcisinde sesli bildirimleri etkinleştir",
+ "Enable desktop notifications": "Masaüstü bildirimlerini etkinleştir",
+ "Enable email notifications": "E-posta bildirimlerini etkinleştir",
+ "Enable notifications for this account": "Bu hesap için bildirimleri etkinleştir",
+ "Enable them now": "Onları şimdi etkinleştir",
+ "Enter keywords separated by a comma:": "Anahtar kelimeleri virgül ile ayırarak girin:",
+ "Error": "Hata",
+ "Error saving email notification preferences": "E-posta bildirim tercihlerini kaydetme hatası",
+ "#example": "örnek",
+ "Expand panel": "Genişletme paneli",
+ "Failed to": "Başaramadı",
+ "Failed to add tag %(tagName)s to room": "%(tagName)s etiketi odaya eklenemedi",
+ "Failed to change settings": "Ayarlar değiştirilemedi",
+ "Failed to forget room %(errCode)s": "Odayı unutma başarısız oldu %(errCode)s",
+ "Failed to update keywords": "Anahtar kelimeler güncellenemedi",
+ "Failed to get protocol list from Home Server": "Ana Sunucu'dan protokol listesi alınamadı",
+ "Failed to get public room list": "Genel odalar listesi alınamadı",
+ "Failed to join the room": "Odaya girilemedi",
+ "Failed to remove tag %(tagName)s from room": "Odadan %(tagName)s etiketi kaldırılamadı",
+ "Failed to send report: ": "Rapor gönderilemedi: ",
+ "Failed to set direct chat tag": "Direkt sohbet etiketi ayarlanamadı",
+ "Failed to set Direct Message status of room": "Odanın Direkt Mesaj durumu ayarlanamadı",
+ "Favourite": "Favori",
+ "Fetching third party location failed": "Üçüncü parti konumunu çekemedi",
+ "Files": "Dosyalar",
+ "Filter room names": "Oda isimlerini filtrele",
+ "Forget": "Unut",
+ "Forward Message": "Mesajı İlet",
+ " from room": " Odadan",
+ "Guests can join": "Misafirler katılabilirler",
+ "Guest users can't invite users. Please register to invite.": "Misafir kullanıcılar kullanıcıları davet edemezler . Davet etmek için lütfen kayıt olun.",
+ "Hide panel": "Paneli gizle",
+ "(HTTP status %(httpStatus)s)": "(HTTP durumu %(httpStatus)s)",
+ "I understand the risks and wish to continue": "Riskleri anlıyorum ve devam etmek istiyorum",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "Sorunları teşhis etmek için , bu istemciden kayıtlar hata raporu ile beraber gönderilecek . Yalnızca yukarıdaki metni göndermek isterseniz , lütfen işareti kaldırın:",
+ "Invite to this room": "Bu odaya davet et",
+ "Keywords": "Anahtar kelimeler",
+ "Leave": "Ayrıl",
+ "Login": "Oturum aç",
+ "Loading bug report module": "Hata raporlama modülü yükleniyor",
+ "Low Priority": "Düşük Öncelikli",
+ "Members": "Üyeler",
+ "Mentions only": "Sadece Mention'lar",
+ "Messages containing my display name": "İsmimi içeren mesajlar",
+ "Messages containing keywords": " anahtar kelimeleri içeren mesajlar",
+ "Messages containing my user name": "Kullanıcı ismimi içeren mesajlar",
+ "Messages in group chats": "Grup sohbetlerindeki mesajlar",
+ "Messages in one-to-one chats": "Bire bir sohbetlerdeki mesajlar",
+ "Messages sent by bot": "Bot tarafından gönderilen mesajlar",
+ "more": "Daha",
+ "Mute": "Sessiz",
+ "No rooms to show": "Gösterilecek oda yok",
+ "Noisy": "Gürültülü",
+ "Notification targets": "Bildirim hedefleri",
+ "Notifications": "Bildirimler",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "Aşağıdaki anahtar kelimeleri ile ilgili bildirimler burada gösterilemeyen kuralları takip eder:",
+ "Notify for all other messages/rooms": "Diğer tüm mesajlar / odalar için bildirim yapın",
+ "Notify me for anything else": "Başka herhangi bir şey için bana bildirim yap",
+ "Off": "Kapalı",
+ "On": "Açık",
+ "Operation failed": "Operasyon başarısız",
+ "Permalink": "Kalıcı Bağlantı(permalink)",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Lütfen hatayı tanımlayın. Ne yaptınız ? Ne gerçekleşmesini beklediniz ? Ne gerçekleşti ?",
+ "Please describe the bug and/or send logs.": "Lütfen hatayı tanımlayın ve/veya kayıtları gönderin.",
+ "Please install Chrome or Firefox for the best experience.": "Lütfen Chrome ya da Firefox 'u en iyi deneyim için yükleyin.",
+ "Please Register": "Lütfen Kaydolun",
+ "powered by Matrix": "Matrix tarafından desteklenmektedir",
+ "Quote": "Alıntı",
+ "Redact": "Yazıya Dökme",
+ "Reject": "Reddet",
+ "Remove %(name)s from the directory?": "%(name)s'i dizinden kaldırılsın mı ?",
+ "Remove": "Kaldır",
+ "remove %(name)s from the directory.": "%(name)s'i dizinden kaldır.",
+ "Remove from Directory": "Dizinden Kaldır",
+ "Report a bug": "Hata Bildir",
+ "Resend": "Yeniden Gönder",
+ "Riot Desktop on %(platformName)s": "%(platformName)s platformunda Riot Masaüstü",
+ "Riot does not know how to join a room on this network": "Riot bu ağdaki bir odaya nasıl gireceğini bilmiyor",
+ "Riot is not supported on mobile web. Install the app?": "Riot mobil web'de desteklenmiyor . Uygulamayı yükle ?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot geçerli tarayıcınızda mevcut olmayan veya denemelik olan birçok gelişmiş tarayıcı özelliği kullanıyor.",
+ "Room directory": "Oda dizini",
+ "Room not found": "Oda bulunamadı",
+ "Search": "Ara",
+ "Search…": "Arama…",
+ "Search for a room": "Oda ara",
+ "Send": "Gönder",
+ "Send logs": "Kayıtları gönder",
+ "Settings": "Ayarlar",
+ "Source URL": "Kaynak URL",
+ "Sorry, your browser is not able to run Riot.": "Üzgünüz , tarayıcınız Riot'u çalıştıramıyor .",
+ "Start chat": "Sohbet başlat",
+ "The Home Server may be too old to support third party networks": "Ana Sunucu 3. parti ağları desteklemek için çok eski olabilir",
+ "There are advanced notifications which are not shown here": "Burada gösterilmeyen gelişmiş bildirimler var",
+ "The server may be unavailable or overloaded": "Sunucu kullanılamıyor veya aşırı yüklenmiş olabilir",
+ "This Room": "Bu Oda",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Bu odaya misafirler tarafından erişilemez . Kaydolursanız katılabilirsiniz.",
+ " to room": " odasına",
+ "Unable to fetch notification target list": "Bildirim hedef listesi çekilemedi",
+ "Unable to join network": "Ağa bağlanılamıyor",
+ "Unable to look up room ID from server": "Sunucudan oda ID'si aranamadı",
+ "Unavailable": "Kullanım dışı",
+ "Unhide Preview": "Önizlemeyi Göster",
+ "Unknown device": "Bilinmeyen aygıt",
+ "unknown error code": "Bilinmeyen hata kodu",
+ "Unnamed room": "İsimsiz oda",
+ "Update": "Güncelleştirme",
+ "Uploaded on %(date)s by %(user)s": "%(user)s tarafında %(date)s e yüklendi",
+ "Uploading report": "Rapor yükleniyor",
+ "View Decrypted Source": "Şifresi Çözülmüş(Decrypted) Kaynağı Görüntüle",
+ "View Source": "Kaynağı Görüntüle",
+ "What's New": "Yenilikler",
+ "What's new?": "Yeni olan ne ?",
+ "Waiting for response from server": "Sunucudan yanıt bekleniyor",
+ "When I'm invited to a room": "Bir odaya davet edildiğimde",
+ "World readable": "Okunabilir dünya",
+ "You cannot delete this image. (%(code)s)": "Bu resmi silemezsiniz. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Bu mesajı silemezsiniz (%(code)s)",
+ "You are not receiving desktop notifications": "Masaüstü bildirimleri almıyorsunuz",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Konuk olarak Riotluyorsunuz. Daha fazla odaya ve özelliğe erişmek için Kayıt Ol ya da Oturum Aç !",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Onları Riot dışında bir istemciden yapılandırmış olabilirsiniz . Onları Riot içersinide ayarlayamazsınız ama hala geçerlidirler",
+ "Sunday": "Pazar",
+ "Monday": "Pazartesi",
+ "Tuesday": "Salı",
+ "Wednesday": "Çarşamba",
+ "Thursday": "Perşembe",
+ "Friday": "Cuma",
+ "Saturday": "Cumartesi",
+ "Today": "Bugün",
+ "Yesterday": "Dün",
+ "OK": "Tamam",
+ "You need to be using HTTPS to place a screen-sharing call.": "Ekran paylaşımlı arama yapmak için HTTPS kullanıyor olmalısınız.",
+ "Welcome page": "Karşılama sayfası",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Geçerli tarayıcınız ile birlikte , uygulamanın görünüş ve kullanım hissi tamamen hatalı olabilir ve bazı ya da tüm özellikler çalışmayabilir. Yine de denemek isterseniz devam edebilirsiniz ancak karşılaşabileceğiniz sorunlar karşısında kendi başınasınız !",
+ "Welcome to Riot.im": "Riot.im'e Hoş Geldiniz",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Dağıtık , şifreli sohbet & işbirliği ile Matrix tarafından desteklenmektedir",
+ "Search the room directory": "Oda dizinini ara",
+ "Chat with Riot Bot": "Riot Bot ile Sohbet Et",
+ "Get started with some tips from Riot Bot!": "Bazı Riot Bot ipuçları ile başlayın !",
+ "General discussion about Matrix and Riot": "Matrix ve Riot hakkında genel tartışma",
+ "Discussion of all things Matrix!": "Matrix'in tüm tartışması!",
+ "Riot/Web & Desktop chat": "Riot/Web & Masaüstü sohbet",
+ "Riot/iOS & matrix-ios-sdk chat": "Riot/iOS & matrix-ios-sdk sohbet",
+ "Riot/Android & matrix-android-sdk chat": "Riot/Android & matrix-android-sdk sohbet",
+ "Matrix technical discussions": "Matrix teknik tartışmalar",
+ "Running Matrix services": "Çalışan Matrix hizmetleri",
+ "Community-run support for Synapse": "Synapse için topluluk tarafından işlenen destek",
+ "Admin support for Dendrite": "Dendrite için Admin desteği",
+ "Announcements about Synapse releases": "Synapse sürümleri hakkında duyurular",
+ "Support for those using and running matrix-appservice-irc": "matrix-appservice-irc kullanan ve çalıştıran kullanıcılar için destek",
+ "Building services on Matrix": "Matrix üzerinde Yapı hizmetleri",
+ "Support for those using the Matrix spec": "Matrix teknik özelliklerini kullananlar için destek",
+ "Design and implementation of E2E in Matrix": "Matrix'te E2E ' nin Tasarım ve İmplementasyonu",
+ "Implementing VR services with Matrix": "Matrix'te VR hizmetlerini implement etmek",
+ "Implementing VoIP services with Matrix": "Matrix'te VoIP hizmetlerini implement etmek",
+ "Discussion of the Identity Service API": "Kimlik Hizmet API ( Identity Service API ) Tartışması",
+ "Support for those using, running and writing other bridges": "Diğer köprüleri kullanan , çalıştıran ve yazanlar için destek",
+ "Contributing code to Matrix and Riot": "Matrix ve Riot'a kod katkısı (contribution) sağla",
+ "Dev chat for the Riot/Web dev team": "Riot/Web Geliştirici takımı için Geliştirici sohbeti",
+ "Dev chat for the Dendrite dev team": "Dendrite Geliştirici Takımı için Geliştirici sohbeti",
+ "Co-ordination for Riot/Web translators": "Riot/Web çevirmenleri için koordinasyon",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "Matrix'te varolan ağlara (Slack , IRC , Gitter vb.) bağlı ya da bağımsız bir çok oda var . Dizini kontrol edin!",
+ "Failed to change password. Is your password correct?": "Şifre değiştirme başarısız oldu . Şifreniz doğru mu ?",
+ "You have successfully set a password!": "Başarıyla bir şifre ayarladınız!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Şimdi oturumunuzu iptal ettikten sonra başka cihazda oturum açarak hesabınıza dönebilirsiniz.",
+ "Continue": "Devam",
+ "Please set a password!": "Lütfen bir şifre ayarlayın !",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Bu oturumunuzu kapattıktan sonra hesabınıza dönmenizi ve diğer cihazlarda oturum açmanızı sağlar.",
+ "You have successfully set a password and an email address!": "Başarıyla bir şifre ve e-posta adresi ayarladın !",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Unutmayın , fikrinizi değiştirirseniz her zaman bir şifre ve e-posta adresi ayarlayabilirsiniz."
+}
diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json
new file mode 100644
index 00000000..59852cf1
--- /dev/null
+++ b/src/i18n/strings/uk.json
@@ -0,0 +1,198 @@
+{
+ "A new version of Riot is available.": "Доступне оновлення для Riot.",
+ "All messages": "Усі повідомлення",
+ "All messages (loud)": "Усі повідомлення (гучно)",
+ "All Rooms": "Усі кімнати",
+ "All notifications are currently disabled for all targets.": "Сповіщення для усіх цілей на даний момент вимкнені.",
+ "An error occurred whilst saving your email notification preferences.": "Під час збереження налаштувань сповіщень е-поштою трапилася помилка.",
+ "Cancel": "Скасувати",
+ "Cancel Sending": "Скасувати надсилання",
+ "Can't update user notification settings": "Неможливо оновити налаштування користувацьких сповіщень",
+ "Changelog": "Журнал змін",
+ "Close": "Закрити",
+ "Collapse panel": "Згорнути панель",
+ "Collecting app version information": "Збір інформації про версію застосунка",
+ "Collecting logs": "Збір журналів",
+ "Create new room": "Створити нову кімнату",
+ "Couldn't find a matching Matrix room": "Неможливо знайти відповідну кімнату",
+ "Custom Server Options": "Нетипові параметри сервера",
+ "customServer_text": "Ви можете скористатись нетиповими параметрами сервера щоб увійти в інші сервери Matrix, зазначивши посилання на окремий Домашній сервер Це дозволяє вам використовувати Riot із вже існуючою обліковкою Matrix на іншому Домашньому сервері.
Ви також можете зазначити нетиповий сервер ідентифікації, але ви не матимете змоги ані запрошувати користувачів за е-поштою, ані бути запрошеними за е-поштою самі.",
+ "delete the alias.": "видалити псевдонім.",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s через %(browserName)s на %(osName)s",
+ "Safari and Opera work too.": "Safari та Opera також підтримуються.",
+ "Add an email address above to configure email notifications": "Додайте вище адресу е-пошти щоб налаштувати сповіщення е-поштою",
+ "Advanced notification settings": "Додаткові налаштування сповіщень",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "Видалити псевдонім %(alias)s та прибрати з каталогу %(name)s?",
+ "Describe your problem here.": "Опишіть вашу проблему тут.",
+ "Direct Chat": "Прямий чат",
+ "Directory": "Каталог",
+ "Dismiss": "Відхилити",
+ "Download this file": "Звантажити цей файл",
+ "Enable audible notifications in web client": "Увімкнути звукові сповіщення у мережевому застосунку",
+ "Enable desktop notifications": "Увімкнути сповіщення на стільниці",
+ "Enable email notifications": "Увімкнути сповіщення е-поштою",
+ "Enable notifications for this account": "Увімкнути сповіщення для цієї обліковки",
+ "Enable them now": "Увімкнути їх зараз",
+ "Enter keywords separated by a comma:": "Введіть ключові слова через кому:",
+ "Error": "Помилка",
+ "Error saving email notification preferences": "Помилка при збереженні параметрів сповіщень е-поштою",
+ "#example": "#зразок",
+ "Expand panel": "Розгорнути панель",
+ "Failed to": "Не вдалось",
+ "Failed to add tag %(tagName)s to room": "Не вдалось додати до кімнати мітку %(tagName)s",
+ "Failed to change settings": "Не вдалось змінити налаштування",
+ "Failed to forget room %(errCode)s": "Не вдалось забути кімнату %(errCode)s",
+ "Failed to update keywords": "Не вдалось оновити ключові слова",
+ "Failed to get protocol list from Home Server": "Не вдалось отримати перелік протоколів з Домашнього серверу",
+ "Failed to get public room list": "Не вдалось отримати перелік прилюдних кімнат",
+ "Failed to join the room": "Не вдалося приєднатись до кімнати",
+ "Failed to remove tag %(tagName)s from room": "Не вдалося прибрати з кімнати мітку %(tagName)s",
+ "Failed to send report: ": "Не вдалося надіслати звіт: ",
+ "Failed to set direct chat tag": "Не вдалося встановити мітку прямого чату",
+ "Favourite": "Вибране",
+ "Fetching third party location failed": "Не вдалось отримати стороннє місцеперебування",
+ "Files": "Файли",
+ "Filter room names": "Відфільтрувати назви кімнат",
+ "Forget": "Забути",
+ "Forward Message": "Переслати повідомлення",
+ " from room": " з кімнати",
+ "Guests can join": "Гості можуть приєднуватися",
+ "Guest users can't invite users. Please register to invite.": "Гості не можуть запрошувати користувачів. Зареєструйтесь, будь ласка, для видачі запрошень.",
+ "Hide panel": "Сховати панель",
+ "(HTTP status %(httpStatus)s)": "(статус HTTP %(httpStatus)s)",
+ "I understand the risks and wish to continue": "Я ознайомлений з ризиками і хочу продовжити",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "З метою діагностики проблем журнали з цього застосунку будуть надіслані разом зі звітом про вади. Якщо ви бажаєте надіслати лише вищенаведений текст, відозначте, будь ласка:",
+ "Invite to this room": "Запросити до цієї кімнати",
+ "Keywords": "Ключові слова",
+ "Leave": "Вийти",
+ "Login": "Зайти",
+ "Loading bug report module": "Завантаження модуля звітів про вади",
+ "Low Priority": "Неважливі",
+ "Members": "Члени",
+ "Mentions only": "Тільки згадки",
+ "Messages containing keywords": "Повідомлення, що містять ключові слова",
+ "Messages containing my user name": "Повідомлення, що містять моє ім'я користувача",
+ "Messages in group chats": "Повідомлення у групових чатах",
+ "Messages sent by bot": "Повідомлення, надіслані ботом",
+ "more": "докладніше",
+ "Mute": "Стишити",
+ "Notification targets": "Цілі сповіщень",
+ "Notifications": "Сповіщення",
+ "Notify for all other messages/rooms": "Сповіщати щодо всіх повідомлень/кімнат",
+ "Notify me for anything else": "Сповіщати мене про будь-що інше",
+ "Off": "Вимкнено",
+ "On": "Увімкнено",
+ "Operation failed": "Не вдалося виконати дію",
+ "Permalink": "Постійне посилання",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "Опишіть, будь ласка, ваду. Що ви зробили? На що ви очікували? Що трапилось натомість?",
+ "Please describe the bug and/or send logs.": "Опишіть, будь ласка, ваду та/або надішліть журнали.",
+ "Please install Chrome or Firefox for the best experience.": "Для більшої зручності у використанні встановіть, будь ласка, Chrome або Firefox.",
+ "Please Register": "Зареєструйтеся, будь ласка",
+ "powered by Matrix": "працює на Matrix",
+ "Quote": "Цитувати",
+ "Redact": "Видалити",
+ "Reject": "Відмовитись",
+ "Remove %(name)s from the directory?": "Прибрати %(name)s з каталогу?",
+ "Remove": "Прибрати",
+ "remove %(name)s from the directory.": "прибрати %(name)s з каталогу.",
+ "Remove from Directory": "Прибрати з каталогу",
+ "Report a bug": "Звітувати про вади",
+ "Resend": "Перенадіслати",
+ "Riot Desktop on %(platformName)s": "Riot Desktop на %(platformName)s",
+ "Call invitation": "Запрошення до виклику",
+ "Drop here %(toAction)s": "Кидайте сюди %(toAction)s",
+ "Riot does not know how to join a room on this network": "Riot не знає як приєднатись до кімнати у цій мережі",
+ "Riot is not supported on mobile web. Install the app?": "Riot не працює через оглядач на мобільних пристроях. Встановити застосунок?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot використовує багато новітніх функцій, деякі з яких не доступні або є експериментальними у вашому оглядачі.",
+ "Room directory": "Каталог кімнат",
+ "Room not found": "Кімнату не знайдено",
+ "Search": "Пошук",
+ "Search…": "Пошук…",
+ "Search for a room": "Пошук кімнати",
+ "Send": "Надіслати",
+ "Send logs": "Надіслати журнали",
+ "Settings": "Налаштування",
+ "Source URL": "Джерельне посилання",
+ "Sorry, your browser is not able to run Riot.": "Вибачте, ваш оглядач не спроможний запустити Riot.",
+ "Start chat": "Почати розмову",
+ "The Home Server may be too old to support third party networks": "Домашній сервер може бути застарим для підтримки сторонніх мереж",
+ "There are advanced notifications which are not shown here": "Є додаткові сповіщення, що не показуються тут",
+ "The server may be unavailable or overloaded": "Сервер може бути недосяжним або перевантаженим",
+ "This Room": "Ця кімната",
+ "This room is inaccessible to guests. You may be able to join if you register.": "Ця кімната є недосяжною для гостей. Напевно ви матимете змогу приєднатись, якщо зареєструєтесь.",
+ " to room": " до кімнати",
+ "Unable to fetch notification target list": "Неможливо отримати перелік цілей сповіщення",
+ "Unable to join network": "Неможливо приєднатись до мережі",
+ "Unable to look up room ID from server": "Неможливо знайти ID кімнати на сервері",
+ "Unknown device": "Невідомий пристрій",
+ "unknown error code": "невідомий код помилки",
+ "Unnamed room": "Неназвана кімната",
+ "Update": "Оновити",
+ "Uploaded on %(date)s by %(user)s": "Завантажено %(date)s користувачем %(user)s",
+ "Uploading report": "Завантаження звіту",
+ "View Decrypted Source": "Переглянути розшифроване джерело",
+ "View Source": "Переглянути джерело",
+ "What's New": "Що нового",
+ "What's new?": "Що нового?",
+ "Waiting for response from server": "Очікується відповідь від сервера",
+ "When I'm invited to a room": "Коли мене запрошено до кімнати",
+ "World readable": "Відкрито для світу",
+ "You cannot delete this image. (%(code)s)": "Ви не можете видалити це зображення. (%(code)s)",
+ "You cannot delete this message. (%(code)s)": "Ви не можете видалити це повідомлення. (%(code)s)",
+ "You are not receiving desktop notifications": "Ви не отримуєте сповіщення на стільниці",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "Ви Riot'уєте як гість. Зареєструйтеся або увійдіть щоб мати ширший доступ до кімнат та функцій!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "Можливо, ви налаштували їх не у Riot, а у іншому застосунку. Ви не можете регулювати їх у Riot, але вони все ще мають силу",
+ "Sunday": "Неділя",
+ "Monday": "Понеділок",
+ "Tuesday": "Вівторок",
+ "Wednesday": "Середа",
+ "Thursday": "Четвер",
+ "Friday": "П'ятниця",
+ "Saturday": "Субота",
+ "Today": "Сьогодні",
+ "Yesterday": "Вчора",
+ "OK": "Гаразд",
+ "You need to be using HTTPS to place a screen-sharing call.": "Ви маєте використовувати HTTPS щоб зробити виклик із поширенням екрану.",
+ "Welcome page": "Ласкаво просимо",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "У вашому оглядачі вигляд застосунку може бути повністю іншим, а деякі або навіть усі функції можуть не працювати. Якщо ви наполягаєте, то можете продовжити користування, але ви маєте впоратись з усіма можливими проблемами власноруч!",
+ "Welcome to Riot.im": "Ласкаво просимо до Riot.im",
+ "Decentralised, encrypted chat & collaboration powered by [matrix]": "Децентралізований, шифрований чат та засіб для співробітництва, що працює на [matrix]",
+ "Search the room directory": "Шукати у каталозі кімнат",
+ "Chat with Riot Bot": "Розмовляти з Riot-ботом",
+ "Get started with some tips from Riot Bot!": "Розпочніть за допомогою декількох підказок від Riot-боту!",
+ "General discussion about Matrix and Riot": "Загальне обговорення Matrix та Riot",
+ "Discussion of all things Matrix!": "Обговорення усіх деталей про Matrix!",
+ "Riot/Web & Desktop chat": "Обговорення Riot для оглядачів та стільниці",
+ "Riot/iOS & matrix-ios-sdk chat": "Обговорення Riot/iOS та matrix-ios-sdk",
+ "Riot/Android & matrix-android-sdk chat": "Обговорення Riot/Android та matrix-android-sdk",
+ "Matrix technical discussions": "Технічні обговорення Matrix",
+ "Community-run support for Synapse": "Спільнота підтримки Synapse",
+ "Admin support for Dendrite": "Адміністрування Dendrite",
+ "Announcements about Synapse releases": "Оголошення випусків Synapse",
+ "Support for those using and running matrix-appservice-irc": "Підтримка користувачів matrix-appservice-irc",
+ "Building services on Matrix": "Створення служб на основі Matrix",
+ "Support for those using the Matrix spec": "Підтримка користувачів специфікацій Matrix",
+ "Design and implementation of E2E in Matrix": "Планування та впровадження E2E шифрування у Matrix",
+ "Implementing VR services with Matrix": "Впровадження служб віртуальної реальності в рамках Matrix",
+ "Implementing VoIP services with Matrix": "Впровадження служб VoIP через Matrix",
+ "Discussion of the Identity Service API": "Обговорення Identity Service API",
+ "Support for those using, running and writing other bridges": "Підтримка користувачів, адміністраторів та розробників інших Matrix-мостів",
+ "Contributing code to Matrix and Riot": "Тим, хто хоче долучитись до розробки Matrix та Riot",
+ "Dev chat for the Riot/Web dev team": "Чат команди розробників Riot/Web",
+ "Dev chat for the Dendrite dev team": "Чат команди розробників Dendrite",
+ "Co-ordination for Riot/Web translators": "Координація для перекладачів Riot/Web",
+ "Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "У мережі Matrix вже існує багато кімнат, що з'єднані як з існуючими мережами (Slack, IRC, Gitter тощо), так і незалежними. Подивіться у каталозі кімнат!",
+ "Failed to change password. Is your password correct?": "Не вдалось змінити пароль. Ви впевнені, що пароль введено правильно?",
+ "You have successfully set a password!": "Пароль успішно встановлено!",
+ "You can now return to your account after signing out, and sign in on other devices.": "Тепер ви можете повернутися до своєї обліковки після виходу з неї, та зайти з інших пристроїв.",
+ "Continue": "Продовжити",
+ "Please set a password!": "Встановіть пароль, будь ласка!",
+ "This will allow you to return to your account after signing out, and sign in on other devices.": "Це дозволить вам повернутися до своєї обліковки після виходу з неї, та заходити з інших пристроїв.",
+ "You have successfully set a password and an email address!": "Пароль та адресу е-пошти успішно встановлено!",
+ "Remember, you can always set an email address in user settings if you change your mind.": "Пам'ятайте, що ви завжди можете встановити адресу е-пошти у налаштуваннях, якщо передумаєте.",
+ "Messages in one-to-one chats": "Повідомлення у чатах \"сам на сам\"",
+ "No rooms to show": "Кімнати відсутні",
+ "Noisy": "Шумний",
+ "Unavailable": "Нема в наявності",
+ "Unhide Preview": "Відкрити попередній перегляд"
+}
diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json
new file mode 100644
index 00000000..646cfc68
--- /dev/null
+++ b/src/i18n/strings/zh_Hans.json
@@ -0,0 +1,34 @@
+{
+ "Close": "关闭",
+ "Mute": "静音",
+ "Notifications": "通知",
+ "OK": "确定",
+ "Operation failed": "操作失败",
+ "%(appName)s via %(browserName)s on %(osName)s": "应用%(appName)s通过%(osName)s上的%(browserName)s浏览器运行",
+ "Safari and Opera work too.": "Safari和Opera均可运行。",
+ "A new version of Riot is available.": "Riot 有更新可用。",
+ "Add an email address above to configure email notifications": "请在上方输入电子邮件地址以接收邮件通知",
+ "Advanced notification settings": "通知高级设置",
+ "All messages": "全部消息",
+ "All messages (loud)": "全部消息(高亮)",
+ "All Rooms": "全部房间",
+ "All notifications are currently disabled for all targets.": "当前所有目标的通知均已禁用。",
+ "An error occurred whilst saving your email notification preferences.": "保存邮件通知偏好设定时出现错误。",
+ "Call invitation": "语音邀请",
+ "Cancel": "取消",
+ "Cancel Sending": "取消发送",
+ "Can't update user notification settings": "不能更新用户通知设置",
+ "Changelog": "变更日志",
+ "Collecting app version information": "正在收集应用版本信息",
+ "Collecting logs": "正在收集日志",
+ "Create new room": "创建新房间",
+ "Couldn't find a matching Matrix room": "未找到符合的 Matrix 房间",
+ "Custom Server Options": "自定义服务器选项",
+ "customServer_text": "你可以通过指定自定义服务器选项中的其他 Home server URL 来登录其他 Matrix 服务器。 该选项允许你在 Riot 上使用其他 Home server 上的帐号。
你也可以自定义身份验证服务器,但你将不能通过邮件邀请其他用户,同样的,你也不能通过邮件被其他用户邀请。",
+ "delete the alias.": "删除别名。",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "确定要删除房间别名 %(alias)s 并将 %(name)s 从列表中删除吗?",
+ "Describe your problem here.": "在这里描述你的问题。",
+ "Directory": "房间列表",
+ "Dismiss": "设为已读",
+ "Download this file": "下载该文件"
+}
diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json
new file mode 100644
index 00000000..5b22640d
--- /dev/null
+++ b/src/i18n/strings/zh_Hant.json
@@ -0,0 +1,164 @@
+{
+ "Direct Chat": "私聊",
+ "Drop here %(toAction)s": "拖拽到這里 %(toAction)s",
+ "Error": "錯誤",
+ "Failed to forget room %(errCode)s": "無法忘記聊天室 %(errCode)s",
+ "Failed to join the room": "無法加入此聊天室",
+ "Favourite": "收藏",
+ "Search": "搜索",
+ "Settings": "設置",
+ "%(appName)s via %(browserName)s on %(osName)s": "%(appName)s 透過 %(browserName)s 在 %(osName)s",
+ "Safari and Opera work too.": "Safari 與 Opera 也能使用。",
+ "Advanced notification settings": "進階通知設定",
+ "All messages": "所有訊息",
+ "All messages (loud)": "所有訊息 (loud)",
+ "All Rooms": "所有的聊天室",
+ "Call invitation": "通話邀請",
+ "Cancel": "取消",
+ "Cancel Sending": "取消傳送",
+ "Can't update user notification settings": "無法更新用戶的通知設定",
+ "Changelog": "變更記錄",
+ "Close": "關閉",
+ "Collapse panel": "閤上面版",
+ "Collecting logs": "收集記錄",
+ "Create new room": "開設新聊天室",
+ "Couldn't find a matching Matrix room": "不能找到符合 Matrix 的聊天室",
+ "Custom Server Options": "自定伺服器選項",
+ "delete the alias.": "刪除別名",
+ "Describe your problem here.": "在此描述你的問題",
+ "Directory": "目錄",
+ "Dismiss": "無視",
+ "Download this file": "下載這個檔案",
+ "Enable desktop notifications": "啟用桌面通知",
+ "Enable email notifications": "啟用電郵通知",
+ "Enable notifications for this account": "本帳號啟用通知",
+ "Enable them now": "現在啟用它們",
+ "#example": "#例子",
+ "Expand panel": "擴充面版",
+ "Failed to": "失敗於",
+ "Failed to change settings": "變更設定失敗",
+ "Failed to update keywords": "無法更新關鍵字",
+ "Members": "成員",
+ "Mentions only": "只有提到",
+ "Messages containing my display name": "訊息中有包含我的顯示名稱",
+ "Messages containing keywords": "訊息包含 關鍵字",
+ "Messages containing my user name": "訊息中有我的用戶名",
+ "Messages in group chats": "在群組聊天中的訊息",
+ "Messages in one-to-one chats": "在一對一聊天中的訊息",
+ "Messages sent by bot": "由機器人送出的訊息",
+ "more": "更多",
+ "Mute": "靜音",
+ "No rooms to show": "無聊天室可顯示",
+ "Noisy": "吵鬧",
+ "Notifications": "通知",
+ "Off": "關閉",
+ "On": "開啟",
+ "Operation failed": "操作失敗",
+ "powered by Matrix": "由Matrix架設",
+ "Quote": "引述",
+ "Remove": "移除",
+ "Resend": "重新送出",
+ "Room directory": "聊天室目錄",
+ "Room not found": "未找到聊天室",
+ "Search…": "搜尋...",
+ "Search for a room": "搜尋聊天室",
+ "Send": "送出",
+ "Send logs": "送出記錄",
+ "Source URL": "來源網址",
+ "Start chat": "開始聊天",
+ "This Room": "這個聊天室",
+ "This room is inaccessible to guests. You may be able to join if you register.": "這個聊天室不對訪客開放,要加入須先註冊。",
+ " to room": "到聊天室",
+ "Unable to join network": "無法加入網路",
+ "Unable to look up room ID from server": "無法從伺服器找到聊天室 ID",
+ "Unavailable": "無法取得",
+ "Unhide Preview": "不隱藏預覽",
+ "Unknown device": "不知名的設備",
+ "unknown error code": "未知的錯誤代碼",
+ "Unnamed room": "無名的聊天室",
+ "Update": "更新",
+ "Uploaded on %(date)s by %(user)s": "由 %(user)s 在 %(date)s 更新",
+ "Uploading report": "上傳報告",
+ "View Decrypted Source": "檢示解密的來源",
+ "View Source": "檢示來源",
+ "What's New": "新鮮事",
+ "What's new?": "有什麼新聞?",
+ "Waiting for response from server": "等候來自伺服器的回應",
+ "When I'm invited to a room": "當我被邀請加入聊天室",
+ "You cannot delete this message. (%(code)s)": "你不能刪除這個訊息 (%(code)s)",
+ "Sunday": "星期日",
+ "Monday": "星期一",
+ "Tuesday": "星期二",
+ "Wednesday": "星期三",
+ "Thursday": "星期四",
+ "Friday": "星期五",
+ "Saturday": "星期六",
+ "Today": "今天",
+ "Yesterday": "昨天",
+ "OK": "OK",
+ "You need to be using HTTPS to place a screen-sharing call.": "你需要使用 HTTPS 來置放畫面分享的通話。",
+ "Welcome page": "歡迎頁",
+ "A new version of Riot is available.": "Riot 發佈了新版本",
+ "Add an email address above to configure email notifications": "在上面新增電子郵件以設定電郵通知",
+ "All notifications are currently disabled for all targets.": "目前所有的通知功能已取消",
+ "An error occurred whilst saving your email notification preferences.": "在儲存你的電郵通知偏好時發生錯誤",
+ "Collecting app version information": "收集應用程式版本資訊",
+ "Delete the room alias %(alias)s and remove %(name)s from the directory?": "刪除聊天室別名 %(alias)s並從目錄移除 %(name)s",
+ "Enable audible notifications in web client": "在網頁客戶端設定聲音通知",
+ "Enter keywords separated by a comma:": "輸入關鍵字以逼號,區隔",
+ "Error saving email notification preferences": "儲存電郵通知偏好時出錯",
+ "Failed to add tag %(tagName)s to room": "無法為聊天室新增標籤 %(tagName)s",
+ "Failed to get protocol list from Home Server": "無法從主機伺服器取得協議清單",
+ "Failed to get public room list": "無法取得公開的聊天室清單",
+ "Failed to remove tag %(tagName)s from room": "移除聊天室的標籤 %(tagName)s 失敗",
+ "Failed to send report: ": "無法傳送報告:",
+ "Failed to set direct chat tag": "無法設定直接聊天標籤",
+ "Failed to set Direct Message status of room": "無法設定聊天室的私訊狀態",
+ "Fetching third party location failed": "抓取第三方位置失敗",
+ "Files": "檔案",
+ "Filter room names": "過濾聊天室名稱",
+ "Forget": "忘記",
+ "Forward Message": "轉寄訊息",
+ " from room": "來自聊天室",
+ "Guests can join": "訪客可以加入",
+ "Guest users can't invite users. Please register to invite.": "訪客不能邀請用戶,請先註冊再行邀請。",
+ "Hide panel": "隱藏面板",
+ "I understand the risks and wish to continue": "我了解這些風險並願意繼續",
+ "Invite to this room": "邀請加入這個聊天室",
+ "Keywords": "關鍵字",
+ "Leave": "離開",
+ "Loading bug report module": "載入程式臭蟲報告模組",
+ "Low Priority": "低度優先",
+ "Notify for all other messages/rooms": "通知所有其它的訊息/聊天室",
+ "Notify me for anything else": "所有消息都通知我",
+ "Permalink": "永久鏈接",
+ "Please install Chrome or Firefox for the best experience.": "諘安裝 Chrome 或 Firefox 來取得最佳體驗。",
+ "Please Register": "請註冊",
+ "Redact": "纂輯\t",
+ "Reject": "拒絕",
+ "Remove %(name)s from the directory?": "自目錄中移除 %(name)s?",
+ "remove %(name)s from the directory.": "自目錄中移除 %(name)s",
+ "Remove from Directory": "自目錄中移除",
+ "Report a bug": "回報程式臭蟲",
+ "Riot Desktop on %(platformName)s": "Riot 在 %(platformName)s 桌面",
+ "Riot does not know how to join a room on this network": "Riot 不知道如何在此網路中加入聊天室",
+ "Sorry, your browser is not able to run Riot.": "可惜你的瀏覽器 無法 執行 Riot.",
+ "The Home Server may be too old to support third party networks": "主機伺服器可能太老舊無法支援第三方網路",
+ "The server may be unavailable or overloaded": "伺服器可能過載或無法連取",
+ "Unable to fetch notification target list": "無法抓取通知的目標清單",
+ "customServer_text": "你可以使用自定伺服器選項來登入其它的 Matrix 伺服器,只要在在主機伺服器網址上指定其網址資料。 這可讓你透過已有的 Matrix 帳號在不同的主機伺服器上使用 Riot。
你也可以設定自定的識別伺服器但你將無法透過電子郵件來邀請用戶或是以自己的電子郵件來接受別人的邀請。",
+ "In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick:": "為了診斷問題,來自客戶的活動記錄會隨著這個程式臭蟲報告一起送出。如果你只想送出以上文字,請取消勾選:",
+ "Notification targets": "通知標的",
+ "Notifications on the following keywords follow rules which can’t be displayed here:": "以下關鍵字依照規則其通知將不會顯示在此:",
+ "Please describe the bug. What did you do? What did you expect to happen? What actually happened?": "請描述這個程式臭蟲,你作了什麼動作?你預期會發生什麼狀況?以及實際發生的狀況為何?",
+ "Please describe the bug and/or send logs.": "請描述這個程式臭蟲以及/或送出活動記錄。",
+ "Riot is not supported on mobile web. Install the app?": "Riot 不支援行動網頁,要下載應用程式嗎?",
+ "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Roit 使用了許多先進的瀏覽器功能,有些在你目前所用的瀏覽器上無法使用或僅為試驗效能。",
+ "There are advanced notifications which are not shown here": "有些進階的通知並未在此顯現",
+ "World readable": "全世界可讀",
+ "You cannot delete this image. (%(code)s)": "你不能刪除這個圖片(%(code)s)",
+ "You are not receiving desktop notifications": "你將不會收到桌面通知",
+ "You are Rioting as a guest. Register or sign in to access more rooms and features!": "你目前以訪客身份使用 Riot 註冊 或 登錄 來使用更多聊天室和功能!",
+ "You might have configured them in a client other than Riot. You cannot tune them in Riot but they still apply": "你也許不曾在其它Riot之外的客戶端設定它們,在 Riot底下你無法調它們但其仍然可用",
+ "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "你目前的瀏覽器,其應用程式的外觀和感覺可能完全不正確,有些或全部功能可以無法使用。如果你仍想試,可以繼續但得自負後果。"
+}
diff --git a/src/notifications/VectorPushRulesDefinitions.js b/src/notifications/VectorPushRulesDefinitions.js
index d696451d..df6db6c3 100644
--- a/src/notifications/VectorPushRulesDefinitions.js
+++ b/src/notifications/VectorPushRulesDefinitions.js
@@ -65,7 +65,7 @@ module.exports = {
// Messages containing user's display name
".m.rule.contains_display_name": new VectorPushRuleDefinition({
kind: "override",
- description: "Messages containing my display name",
+ description: "Messages containing my display name", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
on: StandardActions.ACTION_NOTIFY,
loud: StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND,
@@ -76,7 +76,7 @@ module.exports = {
// Messages containing user's username (localpart/MXID)
".m.rule.contains_user_name": new VectorPushRuleDefinition({
kind: "override",
- description: "Messages containing my user name",
+ description: "Messages containing my user name", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: { // The actions for each vector state, or null to disable the rule.
on: StandardActions.ACTION_NOTIFY,
loud: StandardActions.ACTION_HIGHLIGHT_DEFAULT_SOUND,
@@ -87,7 +87,7 @@ module.exports = {
// Messages just sent to the user in a 1:1 room
".m.rule.room_one_to_one": new VectorPushRuleDefinition({
kind: "underride",
- description: "Messages in one-to-one chats",
+ description: "Messages in one-to-one chats", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: {
on: StandardActions.ACTION_NOTIFY,
loud: StandardActions.ACTION_NOTIFY_DEFAULT_SOUND,
@@ -100,7 +100,7 @@ module.exports = {
// By opposition, all other room messages are from group chat rooms.
".m.rule.message": new VectorPushRuleDefinition({
kind: "underride",
- description: "Messages in group chats",
+ description: "Messages in group chats", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: {
on: StandardActions.ACTION_NOTIFY,
loud: StandardActions.ACTION_NOTIFY_DEFAULT_SOUND,
@@ -111,7 +111,7 @@ module.exports = {
// Invitation for the user
".m.rule.invite_for_me": new VectorPushRuleDefinition({
kind: "underride",
- description: "When I'm invited to a room",
+ description: "When I'm invited to a room", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: {
on: StandardActions.ACTION_NOTIFY,
loud: StandardActions.ACTION_NOTIFY_DEFAULT_SOUND,
@@ -122,7 +122,7 @@ module.exports = {
// Incoming call
".m.rule.call": new VectorPushRuleDefinition({
kind: "underride",
- description: "Call invitation",
+ description: "Call invitation", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: {
on: StandardActions.ACTION_NOTIFY,
loud: StandardActions.ACTION_NOTIFY_RING_SOUND,
@@ -133,7 +133,7 @@ module.exports = {
// Notifications from bots
".m.rule.suppress_notices": new VectorPushRuleDefinition({
kind: "override",
- description: "Messages sent by bot",
+ description: "Messages sent by bot", // passed through _t() translation in src/components/views/settings/Notifications.js
vectorStateToActions: {
// .m.rule.suppress_notices is a "negative" rule, we have to invert its enabled value for vector UI
on: StandardActions.ACTION_DISABLED,
diff --git a/src/skins/vector/css/_common.scss b/src/skins/vector/css/_common.scss
index a44a503e..5b1d1de6 100644
--- a/src/skins/vector/css/_common.scss
+++ b/src/skins/vector/css/_common.scss
@@ -65,7 +65,7 @@ input[type=text].error, input[type=password].error {
border: 1px solid $warning-color;
}
-input[type=text]:focus, textarea:focus {
+input[type=text]:focus, input[type=password]:focus, textarea:focus {
border: 1px solid $accent-color;
outline: none;
box-shadow: none;
@@ -225,6 +225,10 @@ textarea {
vertical-align: middle;
}
+.mx_Dialog button:focus, .mx_Dialog input[type="submit"]:focus {
+ filter: brightness($focus-brightness);
+}
+
.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary {
color: $accent-fg-color;
background-color: $accent-color;
diff --git a/src/skins/vector/css/_components.scss b/src/skins/vector/css/_components.scss
index c22fbc06..aef7f6db 100644
--- a/src/skins/vector/css/_components.scss
+++ b/src/skins/vector/css/_components.scss
@@ -3,6 +3,7 @@
@import "./matrix-react-sdk/structures/_ContextualMenu.scss";
@import "./matrix-react-sdk/structures/_CreateRoom.scss";
@import "./matrix-react-sdk/structures/_FilePanel.scss";
+@import "./matrix-react-sdk/structures/_LoginBox.scss";
@import "./matrix-react-sdk/structures/_MatrixChat.scss";
@import "./matrix-react-sdk/structures/_NotificationPanel.scss";
@import "./matrix-react-sdk/structures/_RoomStatusBar.scss";
@@ -17,8 +18,9 @@
@import "./matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_EncryptedEventDialog.scss";
-@import "./matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss";
+@import "./matrix-react-sdk/views/dialogs/_SetMxIdDialog.scss";
@import "./matrix-react-sdk/views/dialogs/_UnknownDeviceDialog.scss";
+@import "./matrix-react-sdk/views/elements/_AccessibleButton.scss";
@import "./matrix-react-sdk/views/elements/_AddressSelector.scss";
@import "./matrix-react-sdk/views/elements/_AddressTile.scss";
@import "./matrix-react-sdk/views/elements/_DirectorySearchBox.scss";
@@ -26,12 +28,14 @@
@import "./matrix-react-sdk/views/elements/_MemberEventListSummary.scss";
@import "./matrix-react-sdk/views/elements/_ProgressBar.scss";
@import "./matrix-react-sdk/views/elements/_RichText.scss";
+@import "./matrix-react-sdk/views/elements/_RoleButton.scss";
@import "./matrix-react-sdk/views/login/_InteractiveAuthEntryComponents.scss";
@import "./matrix-react-sdk/views/login/_ServerConfig.scss";
@import "./matrix-react-sdk/views/messages/_MEmoteBody.scss";
@import "./matrix-react-sdk/views/messages/_MImageBody.scss";
@import "./matrix-react-sdk/views/messages/_MNoticeBody.scss";
@import "./matrix-react-sdk/views/messages/_MTextBody.scss";
+@import "./matrix-react-sdk/views/messages/_RoomAvatarEvent.scss";
@import "./matrix-react-sdk/views/messages/_TextualEvent.scss";
@import "./matrix-react-sdk/views/messages/_UnknownBody.scss";
@import "./matrix-react-sdk/views/rooms/_Autocomplete.scss";
@@ -67,11 +71,13 @@
@import "./vector-web/views/context_menus/_MessageContextMenu.scss";
@import "./vector-web/views/context_menus/_RoomTileContextMenu.scss";
@import "./vector-web/views/dialogs/_ChangelogDialog.scss";
+@import "./vector-web/views/dialogs/_SetEmailDialog.scss";
+@import "./vector-web/views/dialogs/_SetPasswordDialog.scss";
@import "./vector-web/views/directory/_NetworkDropdown.scss";
@import "./vector-web/views/elements/_ImageView.scss";
@import "./vector-web/views/elements/_Spinner.scss";
-@import "./vector-web/views/globals/_GuestWarningBar.scss";
@import "./vector-web/views/globals/_MatrixToolbar.scss";
+@import "./vector-web/views/messages/_DateSeparator.scss";
@import "./vector-web/views/messages/_MessageTimestamp.scss";
@import "./vector-web/views/messages/_SenderProfile.scss";
@import "./vector-web/views/rooms/_RoomDropTarget.scss";
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss b/src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss
index 872085b6..58e09064 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_FilePanel.scss
@@ -112,4 +112,3 @@ limitations under the License.
.mx_FilePanel .mx_EventTile_selected .mx_EventTile_line {
padding-left: 0px;
}
-
diff --git a/src/skins/vector/css/vector-web/views/globals/_GuestWarningBar.scss b/src/skins/vector/css/matrix-react-sdk/structures/_LoginBox.scss
similarity index 62%
rename from src/skins/vector/css/vector-web/views/globals/_GuestWarningBar.scss
rename to src/skins/vector/css/matrix-react-sdk/structures/_LoginBox.scss
index f5bdbaf9..92d8833b 100644
--- a/src/skins/vector/css/vector-web/views/globals/_GuestWarningBar.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_LoginBox.scss
@@ -1,5 +1,5 @@
/*
-Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,23 +14,25 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-.mx_GuestWarningBar {
+.mx_LoginBox_loginButton_wrapper {
+ text-align: center;
+ width: 100%;
+}
+
+.mx_LoginBox_loginButton,
+.mx_LoginBox_registerButton {
+ margin-top: -8px;
+ height: 40px;
+ border: 0px;
+ border-radius: 40px;
+ margin-left: 4px;
+ margin-right: 4px;
+ width: 80px;
+
background-color: $accent-color;
- color: $accent-fg-color;
+ color: $primary-bg-color;
- display: flex;
- align-items: center;
-}
-
-.mx_GuestWarningBar_warning {
- margin-left: 16px;
- margin-right: 8px;
- margin-top: -2px;
-}
-
-.mx_GuestWarningBar a {
- color: $accent-fg-color ! important;
- text-decoration: underline ! important;
cursor: pointer;
-}
+ font-size: 15px;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss b/src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss
index 10528b36..156b1709 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_MatrixChat.scss
@@ -41,12 +41,6 @@ limitations under the License.
height: 40px;
}
-.mx_GuestWarningBar {
- order: 1;
-
- height: 40px;
-}
-
.mx_MatrixChat_toolbarShowing {
height: auto;
}
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss b/src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss
index f6ba2321..1ae2a47c 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_RoomStatusBar.scss
@@ -175,3 +175,22 @@ limitations under the License.
margin-top: -2px;
}
+.mx_MatrixChat_useCompactLayout {
+ .mx_RoomStatusBar {
+ min-height: 40px;
+ }
+
+ .mx_RoomStatusBar_indicator {
+ margin-top: 10px;
+ }
+
+ .mx_RoomStatusBar_callBar {
+ height: 40px;
+ line-height: 40px;
+ }
+
+ .mx_RoomStatusBar_typingBar {
+ height: 40px;
+ line-height: 40px;
+ }
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss
index 9c883caa..ae7735de 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_RoomView.scss
@@ -127,15 +127,6 @@ limitations under the License.
clear: both;
}
-.mx_RoomView_MessageList h2 {
- clear: both;
- margin-top: 32px;
- margin-bottom: 8px;
- margin-left: 63px;
- padding-bottom: 6px;
- border-bottom: 1px solid $primary-hairline-color;
-}
-
.mx_RoomView_invitePrompt {
order: 2;
@@ -160,7 +151,8 @@ hr.mx_RoomView_myReadMarker {
border-bottom: solid 1px $accent-color;
margin-top: 0px;
position: relative;
- top: 5px;
+ top: -1px;
+ z-index: 1;
}
.mx_RoomView_statusArea {
@@ -259,4 +251,14 @@ hr.mx_RoomView_myReadMarker {
.mx_RoomView_ongoingConfCallNotification a {
color: $accent-fg-color ! important;
-}
\ No newline at end of file
+}
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_RoomView_MessageList {
+ margin-bottom: 4px;
+ }
+
+ .mx_RoomView_statusAreaBox {
+ min-height: 42px;
+ }
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
index 099b5b51..9809a81a 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/_UserSettings.scss
@@ -131,6 +131,14 @@ limitations under the License.
position: absolute;
}
+.mx_UserSettings_language {
+ width: 200px;
+}
+
+.mx_UserSettings_webRtcDevices_dropdown{
+ width: 200px;
+}
+
.mx_UserSettings_profileTable
{
display: table;
@@ -176,6 +184,15 @@ limitations under the License.
cursor: pointer;
}
+.mx_UserSettings_phoneSection {
+ display:table;
+}
+
+.mx_UserSettings_phoneCountry {
+ width: 70px;
+ display: table-cell;
+}
+
input.mx_UserSettings_phoneNumberField {
margin-left: 3px;
width: 172px;
@@ -210,6 +227,17 @@ input.mx_UserSettings_phoneNumberField {
margin-top: 10px;
}
+.mx_UserSettings_avatarPicker_edit img {
+ cursor: pointer;
+}
+
.mx_UserSettings_avatarPicker_edit > input {
display: none;
}
+
+.mx_UserSettings_advanced_spoiler,
+.mx_UserSettings_link {
+ cursor: pointer;
+ color: $accent-color;
+ word-break: break-all;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss b/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss
index f21bb169..805c817a 100644
--- a/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss
+++ b/src/skins/vector/css/matrix-react-sdk/structures/login/_Login.scss
@@ -42,7 +42,8 @@ limitations under the License.
.mx_Login_logo {
text-align: center;
- height: 195px;
+ height: 150px;
+ margin-bottom: 45px;
}
.mx_Login_logo img {
@@ -66,10 +67,6 @@ limitations under the License.
margin-bottom: 14px;
}
-.mx_Login_username {
- margin-bottom: 0px;
-}
-
.mx_Login_fieldLabel {
margin-top: -10px;
margin-left: 8px;
@@ -167,16 +164,104 @@ limitations under the License.
margin-bottom: 12px;
}
-.mx_Login_phoneSection {
- display: table;
+.mx_Login_type_container {
+ display: flex;
+ margin-bottom: 14px;
}
-.mx_Login_phoneCountry {
- display: table-cell;
- width: 70px;
+.mx_Login_type_label {
+ flex-grow: 1;
+ line-height: 35px;
+}
+
+.mx_Login_type_dropdown {
+ display: inline-block;
+ min-width: 170px;
+ align-self: flex-end;
+ flex: 1 1 auto;
+}
+
+.mx_Login_field_group {
+ display: flex;
+}
+
+.mx_Login_field_prefix {
+ height: 34px;
+ padding: 0px 5px;
+ line-height: 33px;
+
+ background-color: #eee;
+ border: 1px solid #c7c7c7;
+ border-right: 0px;
+ border-radius: 3px 0px 0px 3px;
+
+ text-align: center;
+}
+
+.mx_Login_field_suffix {
+ height: 34px;
+ padding: 0px 5px;
+ line-height: 33px;
+
+ background-color: #eee;
+ border: 1px solid #c7c7c7;
+ border-left: 0px;
+ border-radius: 0px 3px 3px 0px;
+
+ text-align: center;
+ flex-grow: 1;
+}
+
+.mx_Login_username {
+ height: 16px;
+ flex-shrink: 1;
+ min-width: 0px;
+ border-radius: 3px;
}
.mx_Login_phoneNumberField {
- width: 210px;
- margin-left: 3px;
+ height: 16px;
+}
+
+.mx_Login_field_has_prefix {
+ border-top-left-radius: 0px;
+ border-bottom-left-radius: 0px;
+}
+
+.mx_Login_field_has_suffix {
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+.mx_Login_phoneSection {
+ display:flex;
+}
+
+.mx_Login_phoneCountry {
+ margin-bottom: 14px;
+ width: 150px;
+
+ /* To override mx_Login_field_prefix */
+ text-align: left;
+ padding: 0px;
+ background-color: $primary-bg-color;
+}
+
+.mx_Login_field_prefix .mx_Dropdown_input {
+ /* To use prefix border instead of dropdown border */
+ border: 0;
+}
+
+.mx_Login_phoneCountry .mx_Dropdown_option {
+ /*
+ To match height of mx_Login_field
+ 33px + 2px border from mx_Dropdown_option = 35px
+ */
+ height: 33px;
+ line-height: 33px;
+}
+
+.mx_Login_phoneCountry .mx_Dropdown_option img {
+ margin: 3px;
+ vertical-align: top;
}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatCreateOrReuseChatDialog.scss b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatCreateOrReuseChatDialog.scss
index 926e7411..0f358a58 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatCreateOrReuseChatDialog.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatCreateOrReuseChatDialog.scss
@@ -20,8 +20,22 @@ limitations under the License.
.mx_ChatCreateOrReuseDialog .mx_Dialog_content {
margin-bottom: 24px;
+
+ /*
+ To stop spinner that mx_ChatCreateOrReuseDialog_profile replaces from causing a
+ height change
+ */
+ min-height: 100px;
}
.mx_ChatCreateOrReuseDialog .mx_RoomTile_badge {
display: none;
}
+
+.mx_ChatCreateOrReuseDialog_profile {
+ display: flex;
+}
+
+.mx_ChatCreateOrReuseDialog_profile_name {
+ padding: 14px;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss
index 4a214b51..38bb4f01 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ChatInviteDialog.scss
@@ -34,6 +34,10 @@ limitations under the License.
word-wrap: nowrap;
}
+.mx_ChatInviteDialog .mx_Dialog_content {
+ min-height: 50px
+}
+
.mx_ChatInviteDialog_inputContainer {
border-radius: 3px;
border: solid 1px $input-border-color;
@@ -64,8 +68,3 @@ limitations under the License.
pointer-events: none;
}
-.mx_ChatInviteDialog_addressSelectHeader {
- font-weight: bold;
- line-height: 150%;
- text-indent: 4px;
-}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss
index abd4e9c1..d12bcd37 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_ConfirmUserActionDialog.scss
@@ -37,6 +37,7 @@ limitations under the License.
font-family: 'Open Sans', Arial, Helvetica, Sans-Serif;
font-size: 14px;
color: $primary-fg-color;
+ background-color: $primary-bg-color;
border-radius: 3px;
border: solid 1px $input-border-color;
diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetMxIdDialog.scss b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetMxIdDialog.scss
new file mode 100644
index 00000000..f7d8a3d0
--- /dev/null
+++ b/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetMxIdDialog.scss
@@ -0,0 +1,50 @@
+/*
+Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+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.
+*/
+
+.mx_SetMxIdDialog .mx_Dialog_title {
+ padding-right: 40px;
+}
+
+.mx_SetMxIdDialog_input_group {
+ display: flex;
+}
+
+.mx_SetMxIdDialog_input {
+ border-radius: 3px;
+ border: 1px solid $input-border-color;
+ padding: 9px;
+ color: $primary-fg-color;
+ background-color: $primary-bg-color;
+ font-size: 15px;
+ width: 100%;
+ max-width: 280px;
+}
+
+.mx_SetMxIdDialog_input.error,
+.mx_SetMxIdDialog_input.error:focus {
+ border: 1px solid $warning-color;
+}
+
+.mx_SetMxIdDialog_input_group .mx_Spinner {
+ height: 37px;
+ padding-left: 10px;
+ justify-content: flex-start;
+}
+
+.mx_SetMxIdDialog .success {
+ color: $accent-color;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_AccessibleButton.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_AccessibleButton.scss
new file mode 100644
index 00000000..edf45504
--- /dev/null
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_AccessibleButton.scss
@@ -0,0 +1,24 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_AccessibleButton:focus {
+ outline: 0;
+ filter: brightness($focus-brightness);
+}
+
+.mx_AccessibleButton {
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss
index b96290bd..637c5d12 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_Dropdown.scss
@@ -27,6 +27,15 @@ limitations under the License.
user-select: none;
}
+.mx_Dropdown_input:focus {
+ border-color: $accent-color;
+}
+
+/* Disable dropdown highlight on focus */
+.mx_Dropdown_input.mx_AccessibleButton:focus {
+ filter: none;
+}
+
.mx_Dropdown_arrow {
border-color: $primary-fg-color transparent transparent;
border-style: solid;
@@ -39,6 +48,14 @@ limitations under the License.
width: 0
}
+.mx_Dropdown.left_aligned .mx_Dropdown_arrow {
+ left: 10px;
+}
+
+.mx_Dropdown.left_aligned .mx_Dropdown_input > .mx_Dropdown_option {
+ padding-left: 25px;
+}
+
.mx_Dropdown_option {
height: 35px;
line-height: 35px;
@@ -46,9 +63,15 @@ limitations under the License.
padding-right: 8px;
}
+.mx_Dropdown_option div {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
.mx_Dropdown_option img {
margin: 5px;
- width: 25px;
+ width: 27px;
vertical-align: middle;
}
@@ -74,7 +97,7 @@ input.mx_Dropdown_option, input.mx_Dropdown_option:focus {
border: 1px solid $accent-color;
background-color: $primary-bg-color;
max-height: 200px;
- overflow-y: scroll;
+ overflow-y: auto;
}
.mx_Dropdown_menu .mx_Dropdown_option_highlight {
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss
index 18588659..1025052b 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_MemberEventListSummary.scss
@@ -20,6 +20,7 @@ limitations under the License.
.mx_TextualEvent.mx_MemberEventListSummary_summary {
font-size: 14px;
+ display: inline-flex;
}
.mx_MemberEventListSummary_avatars {
@@ -47,3 +48,13 @@ limitations under the License.
margin-left: 63px;
line-height: 30px;
}
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_MemberEventListSummary_line {
+ line-height: 22px;
+ }
+
+ .mx_MemberEventListSummary_toggle {
+ margin-top: 2px;
+ }
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
new file mode 100644
index 00000000..094e0b9b
--- /dev/null
+++ b/src/skins/vector/css/matrix-react-sdk/views/elements/_RoleButton.scss
@@ -0,0 +1,33 @@
+/*
+Copyright 2107 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_RoleButton {
+ margin-left: 4px;
+ margin-right: 4px;
+ cursor: pointer;
+ display: inline-block;
+}
+
+.mx_RoleButton object {
+ pointer-events: none;
+}
+
+.mx_RoleButton_tooltip {
+ display: inline-block;
+ position: relative;
+ top: -25px;
+ left: 6px;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss b/src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss
index 1ad195de..894ce198 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/login/_ServerConfig.scss
@@ -28,4 +28,9 @@ limitations under the License.
font-size: 13px;
font-weight: 300;
color: $primary-fg-color;
+}
+
+.mx_ServerConfig_selector {
+ text-align: center;
+ width: 302px; // for fr i18n
}
\ No newline at end of file
diff --git a/src/skins/vector/css/matrix-react-sdk/views/messages/_RoomAvatarEvent.scss b/src/skins/vector/css/matrix-react-sdk/views/messages/_RoomAvatarEvent.scss
new file mode 100644
index 00000000..9adce42e
--- /dev/null
+++ b/src/skins/vector/css/matrix-react-sdk/views/messages/_RoomAvatarEvent.scss
@@ -0,0 +1,26 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_RoomAvatarEvent {
+ opacity: 0.5;
+ overflow-y: hidden;
+}
+
+.mx_RoomAvatarEvent_avatar {
+ display: inline;
+ position: relative;
+ top: 5px;
+}
\ No newline at end of file
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
index 4f01aeee..7d8e4ba2 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_EventTile.scss
@@ -62,8 +62,10 @@ limitations under the License.
visibility: hidden;
white-space: nowrap;
color: $event-timestamp-color;
- font-size: 11px;
- left: 8px;
+ font-size: 10px;
+ left: 0px;
+ width: 46px; /* 8 + 30 (avatar) + 8 */
+ text-align: center;
position: absolute;
}
@@ -183,8 +185,13 @@ limitations under the License.
visibility: visible;
}
+.mx_MessagePanel_alwaysShowTimestamps .mx_MessageTimestamp {
+ visibility: visible;
+}
+
.mx_EventTile_selected .mx_MessageTimestamp {
left: 3px;
+ width: auto;
}
.mx_EventTile_editButton {
@@ -218,8 +225,8 @@ limitations under the License.
}
.mx_EventTile_continuation .mx_EventTile_readAvatars,
-.mx_EventTile_info .mx_EventTile_readAvatars
-{
+.mx_EventTile_info .mx_EventTile_readAvatars,
+.mx_EventTile_emote .mx_EventTile_readAvatars {
top: 7px;
}
@@ -263,6 +270,10 @@ limitations under the License.
cursor: pointer;
}
+.mx_EventTile_12hr .mx_EventTile_e2eIcon {
+ padding-left: 5px;
+}
+
.mx_EventTile:hover.mx_EventTile_verified .mx_EventTile_line,
.mx_EventTile:hover.mx_EventTile_unverified .mx_EventTile_line {
padding-left: 60px;
@@ -284,6 +295,7 @@ limitations under the License.
.mx_EventTile:hover.mx_EventTile_verified .mx_MessageTimestamp,
.mx_EventTile:hover.mx_EventTile_unverified .mx_MessageTimestamp {
left: 3px;
+ width: auto;
}
/*
@@ -320,6 +332,29 @@ limitations under the License.
.mx_EventTile_content .markdown-body code {
background-color: #f8f8f8;
}
+.mx_EventTile_copyButton {
+ position: absolute;
+ display: inline-block;
+ visibility: hidden;
+ cursor: pointer;
+ top: 6px;
+ right: 6px;
+ width: 19px;
+ height: 19px;
+ background-image: url($copy-button-url);
+}
+.mx_EventTile_body pre {
+ position: relative;
+ border: 1px solid transparent;
+}
+.mx_EventTile:hover .mx_EventTile_body pre
+{
+ border: 1px solid $primary-hairline-color;
+}
+.mx_EventTile_body pre:hover .mx_EventTile_copyButton
+{
+ visibility: visible;
+}
.mx_EventTile_content .markdown-body h1,
.mx_EventTile_content .markdown-body h2,
@@ -331,6 +366,14 @@ limitations under the License.
font-family: inherit ! important;
}
+
+/* Make h1 and h2 the same size as h3. */
+.mx_EventTile_content .markdown-body h1,
+.mx_EventTile_content .markdown-body h2
+{
+ font-size: 1.5em;
+}
+
.mx_EventTile_content .markdown-body a {
color: $accent-color;
}
@@ -340,3 +383,71 @@ limitations under the License.
}
/* end of overrides */
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_EventTile {
+ padding-top: 4px;
+ }
+
+ .mx_EventTile.mx_EventTile_info {
+ padding-top: 0px;
+ }
+
+ .mx_EventTile .mx_SenderProfile {
+ font-size: 13px;
+ }
+
+ .mx_EventTile.mx_EventTile_emote {
+ padding-top: 8px;
+ .mx_EventTile_avatar {
+ top: 2px;
+ }
+ .mx_EventTile_line {
+ padding-top: 0px;
+ padding-bottom: 1px;
+ }
+ }
+
+ .mx_EventTile.mx_EventTile_emote.mx_EventTile_continuation {
+ padding-top: 0;
+ .mx_EventTile_line {
+ padding-top: 0px;
+ padding-bottom: 0px;
+ }
+ }
+
+ .mx_EventTile_line {
+ padding-top: 0px;
+ padding-bottom: 0px;
+ }
+
+ .mx_EventTile_avatar {
+ top: 2px;
+ }
+
+ .mx_EventTile.mx_EventTile_info .mx_EventTile_avatar {
+ top: 5px;
+ }
+
+ .mx_EventTile_e2eIcon {
+ top: 7px;
+ }
+
+ .mx_EventTile_editButton {
+ top: 3px;
+ }
+
+ .mx_EventTile_readAvatars {
+ top: 27px;
+ }
+
+ .mx_EventTile_continuation .mx_EventTile_readAvatars,
+ .mx_EventTile_info .mx_EventTile_readAvatars,
+ .mx_EventTile_emote .mx_EventTile_readAvatars {
+ top: 5px;
+ }
+
+ .mx_RoomView_MessageList h2 {
+ margin-top: 6px;
+ }
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss
index 1d8261d7..4495b142 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_LinkPreviewWidget.scss
@@ -60,3 +60,10 @@ limitations under the License.
.mx_LinkPreviewWidget:hover .mx_LinkPreviewWidget_cancel {
visibility: visible;
}
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_LinkPreviewWidget {
+ margin-top: 6px;
+ margin-bottom: 6px;
+ }
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss
index 525cc1f6..85c0e2c7 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_MessageComposer.scss
@@ -200,3 +200,13 @@ limitations under the License.
padding: 4px 4px 4px 0;
opacity: 0.8;
}
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_MessageComposer_input {
+ min-height: 50px;
+ }
+
+ .mx_MessageComposer_noperm_error {
+ height: 50px;
+ }
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss
index 4affc994..bb80832d 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomHeader.scss
@@ -31,6 +31,7 @@ limitations under the License.
margin-left: -2px;
order: 1;
flex: 1;
+ overflow: hidden;
}
.mx_RoomHeader_spinner {
@@ -95,6 +96,12 @@ limitations under the License.
float: right;
}
+.mx_RoomHeader_simpleHeader .mx_RoomHeader_icon {
+ margin-left: 14px;
+ margin-right: 24px;
+ vertical-align: -4px;
+}
+
.mx_RoomHeader_name {
vertical-align: middle;
width: 100%;
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
index 110dcd5b..35787ca0 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomList.scss
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2107 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -37,3 +38,25 @@ limitations under the License.
.mx_RoomList_scrollbar .gm-scrollbar.-vertical {
z-index: 6;
}
+
+.mx_RoomList_emptySubListTip {
+ font-size: 13px;
+ margin-left: 18px;
+ margin-right: 18px;
+ margin-top: 8px;
+ margin-bottom: 7px;
+ padding: 5px;
+ border: 1px dashed $accent-color;
+ color: $primary-fg-color;
+ background-color: $droptarget-bg-color;
+ border-radius: 4px;
+}
+
+.mx_RoomList_emptySubListTip .mx_RoleButton {
+ vertical-align: -3px;
+}
+
+.mx_RoomList_headerButtons {
+ position: absolute;
+ right: 60px;
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss
index 08efa145..842228b9 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_RoomTile.scss
@@ -156,7 +156,7 @@ limitations under the License.
}
.mx_RoomTile:focus {
- outline: 0;
+ filter: none ! important;
background-color: $roomtile-focused-bg-color;
}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss b/src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss
index 6b0c8863..1ee56d95 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss
+++ b/src/skins/vector/css/matrix-react-sdk/views/rooms/_TopUnreadMessagesBar.scss
@@ -17,20 +17,15 @@ limitations under the License.
.mx_TopUnreadMessagesBar {
margin: auto; /* centre horizontally */
max-width: 960px;
- padding-top: 5px;
- padding-bottom: 5px;
+ padding-top: 10px;
+ padding-bottom: 10px;
border-bottom: 1px solid $primary-hairline-color;
-
- /* in absence of img */
- height: 24px;
}
.mx_TopUnreadMessagesBar_scrollUp {
display: inline;
cursor: pointer;
-
- /* in absence of img */
- padding-left: 65px;
+ text-decoration: underline;
}
.mx_TopUnreadMessagesBar_scrollUp img {
@@ -49,3 +44,10 @@ limitations under the License.
padding-top: 3px;
cursor: pointer;
}
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_TopUnreadMessagesBar {
+ padding-top: 4px;
+ padding-bottom: 4px;
+ }
+}
diff --git a/src/skins/vector/css/themes/_base.scss b/src/skins/vector/css/themes/_base.scss
index e105e7b4..fc24af93 100644
--- a/src/skins/vector/css/themes/_base.scss
+++ b/src/skins/vector/css/themes/_base.scss
@@ -15,6 +15,8 @@ $accent-color: #76CFA6;
$selection-fg-color: $primary-bg-color;
+$focus-brightness: 125%;
+
// red warning colour
$warning-color: #ff0064;
@@ -100,6 +102,7 @@ $event-redacted-img: url('../../img/redacted.jpg');
$event-timestamp-color: #acacac;
$edit-button-url: "../../img/icon_context_message.svg";
+$copy-button-url: "../../img/icon_copy_message.svg";
// e2e
$e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color
@@ -112,4 +115,4 @@ $lightbox-fg-color: #ffffff;
$lightbox-border-color: #ffffff;
// unused?
-$progressbar-color: #000;
\ No newline at end of file
+$progressbar-color: #000;
diff --git a/src/skins/vector/css/themes/_dark.scss b/src/skins/vector/css/themes/_dark.scss
index 6d435fab..fe2e7591 100644
--- a/src/skins/vector/css/themes/_dark.scss
+++ b/src/skins/vector/css/themes/_dark.scss
@@ -15,6 +15,8 @@ $accent-color: #76CFA6;
$selection-fg-color: $primary-fg-color;
+$focus-brightness: 200%;
+
// red warning colour
$warning-color: #ff0064;
@@ -100,6 +102,7 @@ $event-redacted-img: url('../../img/redacted-dark.jpg');
$event-timestamp-color: #acacac;
$edit-button-url: "../../img/icon_context_message_dark.svg";
+$copy-button-url: "../../img/icon_copy_message_dark.svg";
// e2e
$e2e-verified-color: #76cfa5; // N.B. *NOT* the same as $accent-color
diff --git a/src/skins/vector/css/vector-web/structures/_HomePage.scss b/src/skins/vector/css/vector-web/structures/_HomePage.scss
index e2af399d..cdac1bcc 100644
--- a/src/skins/vector/css/vector-web/structures/_HomePage.scss
+++ b/src/skins/vector/css/vector-web/structures/_HomePage.scss
@@ -19,16 +19,17 @@ limitations under the License.
max-width: 960px;
width: 100%;
height: 100%;
- overflow-y: hidden;
margin-left: auto;
margin-right: auto;
}
+
.mx_HomePage iframe {
+ display: block;
width: 100%;
- height: 90%;
+ height: 100%;
border: 0px;
}
.mx_HomePage_body {
- margin-left: 63px;
+// margin-left: 63px;
}
diff --git a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss
index d3bbce1b..418358dd 100644
--- a/src/skins/vector/css/vector-web/structures/_LeftPanel.scss
+++ b/src/skins/vector/css/vector-web/structures/_LeftPanel.scss
@@ -64,43 +64,43 @@ limitations under the License.
pointer-events: none;
}
-.mx_LeftPanel .mx_BottomLeftMenu_homePage,
-.mx_LeftPanel .mx_BottomLeftMenu_directory,
-.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
-.mx_LeftPanel .mx_BottomLeftMenu_people,
-.mx_LeftPanel .mx_BottomLeftMenu_settings {
- display: inline-block;
- cursor: pointer;
-}
-
-.collapsed .mx_BottomLeftMenu_homePage,
-.collapsed .mx_BottomLeftMenu_directory,
-.collapsed .mx_BottomLeftMenu_createRoom,
-.collapsed .mx_BottomLeftMenu_people,
-.collapsed .mx_BottomLeftMenu_settings {
+.collapsed .mx_RoleButton {
margin-right: 0px ! important;
padding-top: 3px ! important;
padding-bottom: 3px ! important;
}
-.mx_LeftPanel .mx_BottomLeftMenu_homePage,
-.mx_LeftPanel .mx_BottomLeftMenu_directory,
-.mx_LeftPanel .mx_BottomLeftMenu_createRoom,
-.mx_LeftPanel .mx_BottomLeftMenu_people {
+.mx_BottomLeftMenu_options > div {
+ display: inline-block;
+}
+
+.mx_BottomLeftMenu_options .mx_RoleButton {
+ margin-left: 0px;
margin-right: 10px;
}
-.mx_LeftPanel .mx_BottomLeftMenu_settings {
+.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings {
float: right;
}
+.mx_BottomLeftMenu_options .mx_BottomLeftMenu_settings .mx_RoleButton {
+ margin-right: 0px;
+}
+
.mx_LeftPanel.collapsed .mx_BottomLeftMenu_settings {
float: none;
}
-.mx_LeftPanel .mx_BottomLeftMenu_tooltip {
- display: inline-block;
- position: relative;
- top: -25px;
- left: 6px;
+.mx_MatrixChat_useCompactLayout {
+ .mx_LeftPanel .mx_BottomLeftMenu {
+ flex: 0 0 50px;
+ }
+
+ .mx_LeftPanel.collapsed .mx_BottomLeftMenu {
+ flex: 0 0 160px;
+ }
+
+ .mx_LeftPanel .mx_BottomLeftMenu_options {
+ margin-top: 12px;
+ }
}
diff --git a/src/skins/vector/css/vector-web/structures/_RightPanel.scss b/src/skins/vector/css/vector-web/structures/_RightPanel.scss
index bb60fa1e..056e9bd3 100644
--- a/src/skins/vector/css/vector-web/structures/_RightPanel.scss
+++ b/src/skins/vector/css/vector-web/structures/_RightPanel.scss
@@ -118,3 +118,14 @@ limitations under the License.
vertical-align: top;
padding-left: 10px
}
+
+.mx_MatrixChat_useCompactLayout {
+ .mx_RightPanel_footer {
+ flex: 0 0 50px;
+ }
+
+ .mx_RightPanel_footer .mx_RightPanel_invite {
+ line-height: 25px;
+ padding-top: 8px;
+ }
+}
diff --git a/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss b/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss
index 6e508ec7..91cf86c9 100644
--- a/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss
+++ b/src/skins/vector/css/vector-web/structures/_RoomDirectory.scss
@@ -21,12 +21,17 @@ limitations under the License.
margin-right: auto;
margin-bottom: 12px;
color: $primary-fg-color;
+ word-break: break-word;
display: flex;
flex-direction: column;
}
+.mx_RoomDirectory .mx_RoomHeader_simpleHeader {
+ margin-left: 0px;
+}
+
.mx_RoomDirectory_list {
flex: 1;
diff --git a/src/skins/vector/css/vector-web/views/dialogs/_SetEmailDialog.scss b/src/skins/vector/css/vector-web/views/dialogs/_SetEmailDialog.scss
new file mode 100644
index 00000000..588f10c9
--- /dev/null
+++ b/src/skins/vector/css/vector-web/views/dialogs/_SetEmailDialog.scss
@@ -0,0 +1,36 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_SetEmailDialog_email_input {
+ border-radius: 3px;
+ border: 1px solid $input-border-color;
+ padding: 9px;
+ color: $input-fg-color;
+ background-color: $primary-bg-color;
+ font-size: 15px;
+ width: 100%;
+ max-width: 280px;
+ margin-bottom: 10px;
+}
+
+.mx_SetEmailDialog_email_input:focus {
+ outline: none;
+ box-shadow: none;
+ border: 1px solid $accent-color;
+}
+
+.mx_SetEmailDialog_email_input_placeholder {
+}
diff --git a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss b/src/skins/vector/css/vector-web/views/dialogs/_SetPasswordDialog.scss
similarity index 70%
rename from src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss
rename to src/skins/vector/css/vector-web/views/dialogs/_SetPasswordDialog.scss
index 2f0750ad..28a8b7c9 100644
--- a/src/skins/vector/css/matrix-react-sdk/views/dialogs/_SetDisplayNameDialog.scss
+++ b/src/skins/vector/css/vector-web/views/dialogs/_SetPasswordDialog.scss
@@ -1,5 +1,5 @@
/*
-Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,11 +14,22 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-.mx_SetDisplayNameDialog_input {
+.mx_SetPasswordDialog_change_password input {
border-radius: 3px;
border: 1px solid $input-border-color;
padding: 9px;
color: $primary-fg-color;
background-color: $primary-bg-color;
font-size: 15px;
-}
\ No newline at end of file
+ width: 100%;
+ max-width: 280px;
+ margin-bottom: 10px;
+}
+
+.mx_SetPasswordDialog_change_password_button {
+ margin-top: 68px;
+}
+
+.mx_SetPasswordDialog .mx_Dialog_content {
+ margin-bottom: 0px;
+}
diff --git a/src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss b/src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss
index 5a0b23ae..1a7b1c16 100644
--- a/src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss
+++ b/src/skins/vector/css/vector-web/views/globals/_MatrixToolbar.scss
@@ -39,6 +39,10 @@ limitations under the License.
cursor: pointer;
}
+.mx_MatrixToolbar_clickable {
+ cursor: pointer;
+}
+
.mx_MatrixToolbar_close {
cursor: pointer;
}
diff --git a/src/skins/vector/css/vector-web/views/messages/_DateSeparator.scss b/src/skins/vector/css/vector-web/views/messages/_DateSeparator.scss
new file mode 100644
index 00000000..f676d24b
--- /dev/null
+++ b/src/skins/vector/css/vector-web/views/messages/_DateSeparator.scss
@@ -0,0 +1,25 @@
+/*
+Copyright 2017 Vector Creations Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+.mx_DateSeparator {
+ clear: both;
+ margin-top: 32px;
+ margin-bottom: 8px;
+ margin-left: 63px;
+ padding-bottom: 6px;
+ border-bottom: 1px solid $primary-hairline-color;
+}
+
diff --git a/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss b/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss
index e0a50a95..08229e37 100644
--- a/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss
+++ b/src/skins/vector/css/vector-web/views/rooms/_RoomDropTarget.scss
@@ -33,11 +33,6 @@ limitations under the License.
margin-left: 10px;
}
-.mx_RoomDropTarget_placeholder {
- padding-top: 1px;
- padding-bottom: 1px;
-}
-
.mx_RoomDropTarget_label {
position: relative;
margin-top: 3px;
diff --git a/src/skins/vector/img/icon_copy_message.svg b/src/skins/vector/img/icon_copy_message.svg
new file mode 100644
index 00000000..8d8887bb
--- /dev/null
+++ b/src/skins/vector/img/icon_copy_message.svg
@@ -0,0 +1,86 @@
+
+
diff --git a/src/skins/vector/img/icon_copy_message_dark.svg b/src/skins/vector/img/icon_copy_message_dark.svg
new file mode 100644
index 00000000..b81e617d
--- /dev/null
+++ b/src/skins/vector/img/icon_copy_message_dark.svg
@@ -0,0 +1,77 @@
+
+
diff --git a/src/skins/vector/img/icons-directory.svg b/src/skins/vector/img/icons-directory.svg
index 1f1cc29a..2688b847 100644
--- a/src/skins/vector/img/icons-directory.svg
+++ b/src/skins/vector/img/icons-directory.svg
@@ -1,21 +1,24 @@
+
\ No newline at end of file
diff --git a/src/skins/vector/img/logo.png b/src/skins/vector/img/logo.png
deleted file mode 100644
index da6bb327..00000000
Binary files a/src/skins/vector/img/logo.png and /dev/null differ
diff --git a/src/skins/vector/img/logos/riot-logo-1.svg b/src/skins/vector/img/logos/riot-logo-1.svg
index 6b79dd9e..297608b8 100644
--- a/src/skins/vector/img/logos/riot-logo-1.svg
+++ b/src/skins/vector/img/logos/riot-logo-1.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/skins/vector/img/logos/riot-logo-2.svg b/src/skins/vector/img/logos/riot-logo-2.svg
index 96e0bbb1..757f6230 100644
--- a/src/skins/vector/img/logos/riot-logo-2.svg
+++ b/src/skins/vector/img/logos/riot-logo-2.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/skins/vector/img/logos/riot-logo-3.svg b/src/skins/vector/img/logos/riot-logo-3.svg
index 985b9c9f..d71b489a 100644
--- a/src/skins/vector/img/logos/riot-logo-3.svg
+++ b/src/skins/vector/img/logos/riot-logo-3.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/skins/vector/img/logos/riot-logo-4.svg b/src/skins/vector/img/logos/riot-logo-4.svg
index 24a7ddab..aa5522f6 100644
--- a/src/skins/vector/img/logos/riot-logo-4.svg
+++ b/src/skins/vector/img/logos/riot-logo-4.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/skins/vector/img/logos/riot-logo-5.svg b/src/skins/vector/img/logos/riot-logo-5.svg
index 6a2c61df..6cbc2592 100644
--- a/src/skins/vector/img/logos/riot-logo-5.svg
+++ b/src/skins/vector/img/logos/riot-logo-5.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/skins/vector/img/logos/riot-logo-bw.svg b/src/skins/vector/img/logos/riot-logo-bw.svg
index cb6d77d6..e7d6e869 100644
--- a/src/skins/vector/img/logos/riot-logo-bw.svg
+++ b/src/skins/vector/img/logos/riot-logo-bw.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/skins/vector/img/scrollto.svg b/src/skins/vector/img/scrollto.svg
new file mode 100644
index 00000000..75df053a
--- /dev/null
+++ b/src/skins/vector/img/scrollto.svg
@@ -0,0 +1,21 @@
+
+
\ No newline at end of file
diff --git a/src/vector/index.html b/src/vector/index.html
index 331bf684..49c2979e 100644
--- a/src/vector/index.html
+++ b/src/vector/index.html
@@ -12,7 +12,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
<% for (var i=0; i < htmlWebpackPlugin.files.js.length; i++) {
// Not a particularly graceful way of not putting the indexeddb worker script
// into the main page
diff --git a/src/vector/index.js b/src/vector/index.js
index e08b7174..9f162051 100644
--- a/src/vector/index.js
+++ b/src/vector/index.js
@@ -56,12 +56,14 @@ if (process.env.NODE_ENV !== 'production') {
var RunModernizrTests = require("./modernizr"); // this side-effects a global
var ReactDOM = require("react-dom");
var sdk = require("matrix-react-sdk");
-var PlatformPeg = require("matrix-react-sdk/lib/PlatformPeg");
+const PlatformPeg = require("matrix-react-sdk/lib/PlatformPeg");
sdk.loadSkin(require('../component-index'));
var VectorConferenceHandler = require('../VectorConferenceHandler');
var UpdateChecker = require("./updater");
var q = require('q');
var request = require('browser-request');
+import * as UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
+import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
import url from 'url';
@@ -103,7 +105,7 @@ function checkBrowserFeatures(featureList) {
var validBrowser = checkBrowserFeatures([
"displaytable", "flexbox", "es5object", "es5function", "localstorage",
- "objectfit"
+ "objectfit", "indexeddb", "webworkers",
]);
// Parse the given window.location and return parameters that can be used when calling
@@ -141,7 +143,7 @@ var onNewScreen = function(screen) {
var hash = '#/' + screen;
lastLocationHashSet = hash;
window.location.hash = hash;
-}
+};
// We use this to work out what URL the SDK should
// pass through when registering to allow the user to
@@ -228,8 +230,9 @@ function onLoadCompleted() {
}
}
-
async function loadApp() {
+ await loadLanguage();
+
const fragparts = parseQsFromFragment(window.location);
const params = parseQs(window.location);
@@ -242,13 +245,13 @@ async function loadApp() {
if (!preventRedirect) {
if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
- if (confirm("Riot is not supported on mobile web. Install the app?")) {
+ if (confirm(languageHandler._t("Riot is not supported on mobile web. Install the app?"))) {
window.location = "https://itunes.apple.com/us/app/vector.im/id1083446067";
return;
}
}
else if (/Android/.test(navigator.userAgent)) {
- if (confirm("Riot is not supported on mobile web. Install the app?")) {
+ if (confirm(languageHandler._t("Riot is not supported on mobile web. Install the app?"))) {
window.location = "https://play.google.com/store/apps/details?id=im.vector.alpha";
return;
}
@@ -259,11 +262,15 @@ async function loadApp() {
let configError;
try {
configJson = await getConfig();
- rageshake.setBugReportEndpoint(configJson.bug_report_endpoint_url);
} catch (e) {
configError = e;
}
+ if (window.localStorage && window.localStorage.getItem('mx_accepts_unsupported_browser')) {
+ console.log('User has previously accepted risks in using an unsupported browser');
+ validBrowser = true;
+ }
+
console.log("Vector starting at "+window.location);
if (configError) {
window.matrixChat = ReactDOM.render(
@@ -271,7 +278,6 @@ async function loadApp() {
, document.getElementById('matrixchat'));
} else if (validBrowser) {
UpdateChecker.start();
-
const MatrixChat = sdk.getComponent('structures.MatrixChat');
window.matrixChat = ReactDOM.render(
,
document.getElementById('matrixchat')
);
- }
- else {
+ } else {
console.error("Browser is missing required features.");
// take to a different landing page to AWOOOOOGA at the user
var CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
window.matrixChat = ReactDOM.render(
{
+ langs.push(...languageHandler.getNormalizedLanguageKeys(l));
+ });
+ } else {
+ langs = [prefLang];
+ }
+ try {
+ await languageHandler.setLanguage(langs);
+ } catch (e) {
+ console.error("Unable to set language", e);
+ }
+}
+
loadApp();
diff --git a/src/vector/modernizr.js b/src/vector/modernizr.js
index 5ef7778a..07bd2fd3 100644
--- a/src/vector/modernizr.js
+++ b/src/vector/modernizr.js
@@ -1,3 +1,3 @@
-/*! modernizr 3.1.0 (Custom Build) | MIT *
- * http://modernizr.com/download/?-displaytable-es5-flexbox-localstorage-objectfit-cssclassprefix:modernizr_ !*/
-!function(window,document,undefined){function is(e,t){return typeof e===t}function testRunner(){var e,t,r,n,o,s,i;for(var d in tests){if(e=[],t=tests[d],t.name&&(e.push(t.name.toLowerCase()),t.options&&t.options.aliases&&t.options.aliases.length))for(r=0;rd;d++)if(l=e[d],c=mStyle.style[l],contains(l,"-")&&(l=cssToDOM(l)),mStyle.style[l]!==undefined){if(n||is(r,"undefined"))return o(),"pfx"==t?l:!0;try{mStyle.style[l]=r}catch(u){}if(mStyle.style[l]!=c)return o(),"pfx"==t?l:!0}return o(),!1}function fnBind(e,t){return function(){return e.apply(t,arguments)}}function testDOMProps(e,t,r){var n;for(var o in e)if(e[o]in t)return r===!1?e[o]:(n=t[e[o]],is(n,"function")?fnBind(n,r||t):n);return!1}function testPropsAll(e,t,r,n,o){var s=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+cssomPrefixes.join(s+" ")+s).split(" ");return is(t,"string")||is(t,"undefined")?testProps(i,t,n,o):(i=(e+" "+domPrefixes.join(s+" ")+s).split(" "),testDOMProps(i,t,r))}function testAllProps(e,t,r){return testPropsAll(e,undefined,undefined,t,r)}var tests=[],ModernizrProto={_version:"3.1.0",_config:{classPrefix:"modernizr_",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var r=this;setTimeout(function(){t(r[e])},0)},addTest:function(e,t,r){tests.push({name:e,fn:t,options:r})},addAsyncTest:function(e){tests.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=ModernizrProto,Modernizr=new Modernizr;var classes=[],docElement=document.documentElement,isSVG="svg"===docElement.nodeName.toLowerCase(),testStyles=ModernizrProto.testStyles=injectElementWithStyles;testStyles("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(e){var t,r=e.childNodes;t=r[0].offsetLefto;o++){var s=prefixes[o],i=s.toUpperCase()+"_"+t;if(i in n)return"@-"+s.toLowerCase()+"-"+e}return!1};ModernizrProto.atRule=atRule;var prefixed=ModernizrProto.prefixed=function(e,t,r){return 0===e.indexOf("@")?atRule(e):(-1!=e.indexOf("-")&&(e=cssToDOM(e)),t?testPropsAll(e,t,r):testPropsAll(e,"pfx"))};Modernizr.addTest("objectfit",!!prefixed("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("localstorage",function(){var e="modernizr";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(t){return!1}}),testRunner(),setClasses(classes),delete ModernizrProto.addTest,delete ModernizrProto.addAsyncTest;for(var i=0;id;d++)if(l=e[d],c=mStyle.style[l],contains(l,"-")&&(l=cssToDOM(l)),mStyle.style[l]!==undefined){if(n||is(r,"undefined"))return o(),"pfx"==t?l:!0;try{mStyle.style[l]=r}catch(u){}if(mStyle.style[l]!=c)return o(),"pfx"==t?l:!0}return o(),!1}function fnBind(e,t){return function(){return e.apply(t,arguments)}}function testDOMProps(e,t,r){var n;for(var o in e)if(e[o]in t)return r===!1?e[o]:(n=t[e[o]],is(n,"function")?fnBind(n,r||t):n);return!1}function testPropsAll(e,t,r,n,o){var i=e.charAt(0).toUpperCase()+e.slice(1),s=(e+" "+cssomPrefixes.join(i+" ")+i).split(" ");return is(t,"string")||is(t,"undefined")?testProps(s,t,n,o):(s=(e+" "+domPrefixes.join(i+" ")+i).split(" "),testDOMProps(s,t,r))}function testAllProps(e,t,r){return testPropsAll(e,undefined,undefined,t,r)}var tests=[],ModernizrProto={_version:"3.3.1",_config:{classPrefix:"modernizr_",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var r=this;setTimeout(function(){t(r[e])},0)},addTest:function(e,t,r){tests.push({name:e,fn:t,options:r})},addAsyncTest:function(e){tests.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=ModernizrProto,Modernizr=new Modernizr;var classes=[],docElement=document.documentElement,isSVG="svg"===docElement.nodeName.toLowerCase(),testStyles=ModernizrProto.testStyles=injectElementWithStyles;testStyles("#modernizr{display: table; direction: ltr}#modernizr div{display: table-cell; padding: 10px}",function(e){var t,r=e.childNodes;t=r[0].offsetLefto;o++){var i=prefixes[o],s=i.toUpperCase()+"_"+t;if(s in n)return"@-"+i.toLowerCase()+"-"+e}return!1};ModernizrProto.atRule=atRule;var prefixed=ModernizrProto.prefixed=function(e,t,r){return 0===e.indexOf("@")?atRule(e):(-1!=e.indexOf("-")&&(e=cssToDOM(e)),t?testPropsAll(e,t,r):testPropsAll(e,"pfx"))};Modernizr.addTest("objectfit",!!prefixed("objectFit"),{aliases:["object-fit"]}),Modernizr.addTest("localstorage",function(){var e="modernizr";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch(t){return!1}}),Modernizr.addTest("webworkers","Worker"in window);var indexeddb;try{indexeddb=prefixed("indexedDB",window)}catch(e){}Modernizr.addTest("indexeddb",!!indexeddb),indexeddb&&Modernizr.addTest("indexeddb.deletedatabase","deleteDatabase"in indexeddb),testRunner(),setClasses(classes),delete ModernizrProto.addTest,delete ModernizrProto.addAsyncTest;for(var i=0;i as the spec doesn't include anything about things like &
+ // so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
+ if (window.process.platform === 'linux') {
+ msg = msg.replace(//g, '>');
+ }
+
// Notifications in Electron use the HTML5 notification API
const notification = new global.Notification(
title,
{
body: msg,
icon: avatarUrl,
- tag: "vector",
+ tag: 'vector',
silent: true, // we play our own sounds
- }
+ },
);
notification.onclick = function() {
dis.dispatch({
action: 'view_room',
- room_id: room.roomId
+ room_id: room.roomId,
});
global.focus();
- const currentWin = electron.remote.getCurrentWindow();
- currentWin.show();
- currentWin.restore();
- currentWin.focus();
+ const win = remote.getCurrentWindow();
+
+ if (win.isMinimized()) win.restore();
+ else if (!win.isVisible()) win.show();
+ else win.focus();
};
return notification;
}
+ loudNotification(ev: Event, room: Object) {
+ ipcRenderer.send('loudNotification');
+ }
+
clearNotification(notif: Notification) {
notif.close();
}
- getAppVersion() {
- return q(electron.remote.app.getVersion());
+ getAppVersion(): Promise {
+ return q(remote.app.getVersion());
}
pollForUpdate() {
@@ -128,19 +150,21 @@ export default class ElectronPlatform extends VectorBasePlatform {
electron.ipcRenderer.send('install_update');
}
- getDefaultDeviceDisplayName() {
- return "Riot Desktop on " + platformFriendlyName();
+ getDefaultDeviceDisplayName(): string {
+ return _t('Riot Desktop on %(platformName)s', { platformName: platformFriendlyName() });
}
- screenCaptureErrorString() {
+ screenCaptureErrorString(): ?string {
return null;
}
- requestNotificationPermission() : Promise {
+ isElectron(): boolean { return true; }
+
+ requestNotificationPermission(): Promise {
return q('granted');
}
reload() {
- electron.remote.getCurrentWebContents().reload();
+ remote.getCurrentWebContents().reload();
}
}
diff --git a/src/vector/platform/VectorBasePlatform.js b/src/vector/platform/VectorBasePlatform.js
index 5240f3f5..76707d1d 100644
--- a/src/vector/platform/VectorBasePlatform.js
+++ b/src/vector/platform/VectorBasePlatform.js
@@ -17,12 +17,63 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import BasePlatform from 'matrix-react-sdk/lib/BasePlatform'
+import BasePlatform from 'matrix-react-sdk/lib/BasePlatform';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+
+import Favico from 'favico.js';
/**
* Vector-specific extensions to the BasePlatform template
*/
export default class VectorBasePlatform extends BasePlatform {
+ constructor() {
+ super();
+
+ // The 'animations' are really low framerate and look terrible.
+ // Also it re-starts the animationb every time you set the badge,
+ // and we set the state each time, even if the value hasn't changed,
+ // so we'd need to fix that if enabling the animation.
+ this.favicon = new Favico({animation: 'none'});
+ this._updateFavicon();
+ }
+
+ getHumanReadableName(): string {
+ return 'Vector Base Platform'; // no translation required: only used for analytics
+ }
+
+ _updateFavicon() {
+ try {
+ // This needs to be in in a try block as it will throw
+ // if there are more than 100 badge count changes in
+ // its internal queue
+ let bgColor = "#d00",
+ notif = this.notificationCount;
+
+ if (this.errorDidOccur) {
+ notif = notif || "×";
+ bgColor = "#f00";
+ }
+
+ this.favicon.badge(notif, {
+ bgColor: bgColor,
+ });
+ } catch (e) {
+ console.warn(`Failed to set badge count: ${e.message}`);
+ }
+ }
+
+ setNotificationCount(count: number) {
+ if (this.notificationCount === count) return;
+ super.setNotificationCount(count);
+ this._updateFavicon();
+ }
+
+ setErrorStatus(errorDidOccur: boolean) {
+ if (this.errorDidOccur === errorDidOccur) return;
+ super.setErrorStatus(errorDidOccur);
+ this._updateFavicon();
+ }
+
/**
* Check for the availability of an update to the version of the
* app that's currently running.
@@ -44,7 +95,7 @@ export default class VectorBasePlatform extends BasePlatform {
* Get a sensible default display name for the
* device Vector is running on
*/
- getDefaultDeviceDisplayName() {
- return "Unknown device";
+ getDefaultDeviceDisplayName(): string {
+ return _t("Unknown device");
}
}
diff --git a/src/vector/platform/WebPlatform.js b/src/vector/platform/WebPlatform.js
index 5dc55052..b9e941e6 100644
--- a/src/vector/platform/WebPlatform.js
+++ b/src/vector/platform/WebPlatform.js
@@ -18,9 +18,9 @@ limitations under the License.
*/
import VectorBasePlatform from './VectorBasePlatform';
-import Favico from 'favico.js';
import request from 'browser-request';
import dis from 'matrix-react-sdk/lib/dispatcher.js';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
import q from 'q';
import url from 'url';
@@ -30,52 +30,17 @@ export default class WebPlatform extends VectorBasePlatform {
constructor() {
super();
this.runningVersion = null;
- // The 'animations' are really low framerate and look terrible.
- // Also it re-starts the animationb every time you set the badge,
- // and we set the state each time, even if the value hasn't changed,
- // so we'd need to fix that if enabling the animation.
- this.favicon = new Favico({animation: 'none'});
- this._updateFavicon();
}
- _updateFavicon() {
- try {
- // This needs to be in in a try block as it will throw
- // if there are more than 100 badge count changes in
- // its internal queue
- let bgColor = "#d00",
- notif = this.notificationCount;
-
- if (this.errorDidOccur) {
- notif = notif || "×";
- bgColor = "#f00";
- }
-
- this.favicon.badge(notif, {
- bgColor: bgColor
- });
- } catch (e) {
- console.warn(`Failed to set badge count: ${e.message}`);
- }
- }
-
- setNotificationCount(count: number) {
- if (this.notificationCount === count) return;
- super.setNotificationCount(count);
- this._updateFavicon();
- }
-
- setErrorStatus(errorDidOccur: boolean) {
- if (this.errorDidOccur === errorDidOccur) return;
- super.setErrorStatus(errorDidOccur);
- this._updateFavicon();
+ getHumanReadableName(): string {
+ return 'Web Platform'; // no translation required: only used for analytics
}
/**
* Returns true if the platform supports displaying
* notifications, otherwise false.
*/
- supportsNotifications() : boolean {
+ supportsNotifications(): boolean {
return Boolean(global.Notification);
}
@@ -83,8 +48,8 @@ export default class WebPlatform extends VectorBasePlatform {
* Returns true if the application currently has permission
* to display notifications. Otherwise false.
*/
- maySendNotifications() : boolean {
- return global.Notification.permission == 'granted';
+ maySendNotifications(): boolean {
+ return global.Notification.permission === 'granted';
}
/**
@@ -94,7 +59,7 @@ export default class WebPlatform extends VectorBasePlatform {
* that is 'granted' if the user allowed the request or
* 'denied' otherwise.
*/
- requestNotificationPermission() : Promise {
+ requestNotificationPermission(): Promise {
// annoyingly, the latest spec says this returns a
// promise, but this is only supported in Chrome 46
// and Firefox 47, so adapt the callback API.
@@ -113,13 +78,13 @@ export default class WebPlatform extends VectorBasePlatform {
icon: avatarUrl,
tag: "vector",
silent: true, // we play our own sounds
- }
+ },
);
notification.onclick = function() {
dis.dispatch({
action: 'view_room',
- room_id: room.roomId
+ room_id: room.roomId,
});
global.focus();
notification.close();
@@ -132,7 +97,7 @@ export default class WebPlatform extends VectorBasePlatform {
}, 5 * 1000);
}
- _getVersion() {
+ _getVersion(): Promise {
const deferred = q.defer();
// We add a cachebuster to the request to make sure that we know about
@@ -148,19 +113,19 @@ export default class WebPlatform extends VectorBasePlatform {
},
(err, response, body) => {
if (err || response.status < 200 || response.status >= 300) {
- if (err == null) err = { status: response.status };
+ if (err === null) err = { status: response.status };
deferred.reject(err);
return;
}
const ver = body.trim();
deferred.resolve(ver);
- }
+ },
);
return deferred.promise;
}
- getAppVersion() {
+ getAppVersion(): Promise {
if (this.runningVersion !== null) {
return q(this.runningVersion);
}
@@ -169,9 +134,9 @@ export default class WebPlatform extends VectorBasePlatform {
pollForUpdate() {
this._getVersion().done((ver) => {
- if (this.runningVersion == null) {
+ if (this.runningVersion === null) {
this.runningVersion = ver;
- } else if (this.runningVersion != ver) {
+ } else if (this.runningVersion !== ver) {
dis.dispatch({
action: 'new_version',
currentVersion: this.runningVersion,
@@ -187,22 +152,23 @@ export default class WebPlatform extends VectorBasePlatform {
window.location.reload();
}
- getDefaultDeviceDisplayName() {
+ getDefaultDeviceDisplayName(): string {
// strip query-string and fragment from uri
- let u = url.parse(window.location.href);
+ const u = url.parse(window.location.href);
u.search = "";
u.hash = "";
- let app_name = u.format();
+ const appName = u.format();
- let ua = new UAParser();
- return app_name + " via " + ua.getBrowser().name +
- " on " + ua.getOS().name;
+ const ua = new UAParser();
+ const browserName = ua.getBrowser().name || "unknown browser";
+ const osName = ua.getOS().name || "unknown os";
+ return _t('%(appName)s via %(browserName)s on %(osName)s', {appName: appName, browserName: browserName, osName: osName});
}
- screenCaptureErrorString() {
+ screenCaptureErrorString(): ?string {
// it won't work at all if you're not on HTTPS so whine whine whine
if (!global.window || global.window.location.protocol !== "https:") {
- return "You need to be using HTTPS to place a screen-sharing call.";
+ return _t("You need to be using HTTPS to place a screen-sharing call.");
}
return null;
}
diff --git a/src/vector/rageshake.js b/src/vector/rageshake.js
index 0e5b5dac..0138d624 100644
--- a/src/vector/rageshake.js
+++ b/src/vector/rageshake.js
@@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
-import request from "browser-request";
import q from "q";
// This module contains all the code needed to log the console, persist it to
@@ -39,8 +37,12 @@ import q from "q";
// actually timestamps. We then purge the remaining logs. We also do this
// purge on startup to prevent logs from accumulating.
+// the frequency with which we flush to indexeddb
const FLUSH_RATE_MS = 30 * 1000;
+// the length of log data we keep in indexeddb (and include in the reports)
+const MAX_LOG_SIZE = 1024 * 1024 * 1; // 1 MB
+
// A class which monkey-patches the global console and stores log lines.
class ConsoleLogger {
constructor() {
@@ -205,9 +207,6 @@ class IndexedDBLogStore {
}
let txn = this.db.transaction(["logs", "logslastmod"], "readwrite");
let objStore = txn.objectStore("logs");
- objStore.add(this._generateLogEntry(lines));
- let lastModStore = txn.objectStore("logslastmod");
- lastModStore.put(this._generateLastModifiedTime());
txn.oncomplete = (event) => {
resolve();
};
@@ -219,6 +218,9 @@ class IndexedDBLogStore {
new Error("Failed to write logs: " + event.target.errorCode)
);
}
+ objStore.add(this._generateLogEntry(lines));
+ let lastModStore = txn.objectStore("logslastmod");
+ lastModStore.put(this._generateLastModifiedTime());
});
return this.flushPromise;
}
@@ -234,7 +236,6 @@ class IndexedDBLogStore {
* is a big string with all the new-line delimited logs.
*/
async consume() {
- const MAX_LOG_SIZE = 1024 * 1024 * 50; // 50 MB
const db = this.db;
// Returns: a string representing the concatenated logs for this ID.
@@ -396,7 +397,6 @@ function selectQuery(store, keyRange, resultMapper) {
let store = null;
let logger = null;
let initPromise = null;
-let bugReportEndpoint = null;
module.exports = {
/**
@@ -430,81 +430,29 @@ module.exports = {
await store.consume();
},
- setBugReportEndpoint: function(url) {
- bugReportEndpoint = url;
- },
-
/**
- * Send a bug report.
- * @param {string} userText Any additional user input.
- * @param {boolean} sendLogs True to send logs
- * @return {Promise} Resolved when the bug report is sent.
+ * Get a recent snapshot of the logs, ready for attaching to a bug report
+ *
+ * @return {Array<{lines: string, id, string}>} list of log data
*/
- sendBugReport: async function(userText, sendLogs) {
+ getLogsForReport: async function() {
if (!logger) {
throw new Error(
"No console logger, did you forget to call init()?"
);
}
- if (!bugReportEndpoint) {
- throw new Error("No bug report endpoint has been set.");
- }
-
- let version = "UNKNOWN";
- try {
- version = await PlatformPeg.get().getAppVersion();
- }
- catch (err) {} // PlatformPeg already logs this.
-
- let userAgent = "UNKNOWN";
- if (window.navigator && window.navigator.userAgent) {
- userAgent = window.navigator.userAgent;
- }
-
// If in incognito mode, store is null, but we still want bug report
// sending to work going off the in-memory console logs.
- console.log("Sending bug report.");
- let logs = [];
- if (sendLogs) {
- if (store) {
- // flush most recent logs
- await store.flush();
- logs = await store.consume();
- }
- else {
- logs.push({
- lines: logger.flush(true),
- id: "-",
- });
- }
+ if (store) {
+ // flush most recent logs
+ await store.flush();
+ return await store.consume();
}
-
- await q.Promise((resolve, reject) => {
- request({
- method: "POST",
- url: bugReportEndpoint,
- body: {
- logs: logs,
- text: (
- userText || "User did not supply any additional text."
- ),
- app: 'riot-web',
- version: version,
- user_agent: userAgent,
- },
- json: true,
- timeout: 5 * 60 * 1000,
- }, (err, res) => {
- if (err) {
- reject(err);
- return;
- }
- if (res.status < 200 || res.status >= 400) {
- reject(new Error(`HTTP ${res.status}`));
- return;
- }
- resolve();
- })
- });
- }
+ else {
+ return [{
+ lines: logger.flush(true),
+ id: "-",
+ }];
+ }
+ },
};
diff --git a/src/vector/submit-rageshake.js b/src/vector/submit-rageshake.js
new file mode 100644
index 00000000..c6c551c6
--- /dev/null
+++ b/src/vector/submit-rageshake.js
@@ -0,0 +1,125 @@
+/*
+Copyright 2017 OpenMarket Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import pako from 'pako';
+import q from "q";
+
+import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
+import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
+import { _t } from 'matrix-react-sdk/lib/languageHandler';
+
+import rageshake from './rageshake'
+
+
+// polyfill textencoder if necessary
+import * as TextEncodingUtf8 from 'text-encoding-utf-8';
+let TextEncoder = window.TextEncoder;
+if (!TextEncoder) {
+ TextEncoder = TextEncodingUtf8.TextEncoder;
+}
+
+/**
+ * Send a bug report.
+ *
+ * @param {string} bugReportEndpoint HTTP url to send the report to
+ *
+ * @param {object} opts optional dictionary of options
+ *
+ * @param {string} opts.userText Any additional user input.
+ *
+ * @param {boolean} opts.sendLogs True to send logs
+ *
+ * @param {function(string)} opts.progressCallback Callback to call with progress updates
+ *
+ * @return {Promise} Resolved when the bug report is sent.
+ */
+export default async function sendBugReport(bugReportEndpoint, opts) {
+ if (!bugReportEndpoint) {
+ throw new Error("No bug report endpoint has been set.");
+ }
+
+ opts = opts || {};
+ const progressCallback = opts.progressCallback || (() => {});
+
+ progressCallback(_t("Collecting app version information"));
+ let version = "UNKNOWN";
+ try {
+ version = await PlatformPeg.get().getAppVersion();
+ }
+ catch (err) {} // PlatformPeg already logs this.
+
+ let userAgent = "UNKNOWN";
+ if (window.navigator && window.navigator.userAgent) {
+ userAgent = window.navigator.userAgent;
+ }
+
+ const client = MatrixClientPeg.get();
+
+ console.log("Sending bug report.");
+
+ const body = new FormData();
+ body.append('text', opts.userText || "User did not supply any additional text.");
+ body.append('app', 'riot-web');
+ body.append('version', version);
+ body.append('user_agent', userAgent);
+
+ if (client) {
+ body.append('user_id', client.credentials.userId);
+ body.append('device_id', client.deviceId);
+ }
+
+ if (opts.sendLogs) {
+ progressCallback(_t("Collecting logs"));
+ const logs = await rageshake.getLogsForReport();
+ for (let entry of logs) {
+ // encode as UTF-8
+ const buf = new TextEncoder().encode(entry.lines);
+
+ // compress
+ const compressed = pako.gzip(buf);
+
+ body.append('compressed-log', new Blob([compressed]), entry.id);
+ }
+ }
+
+ progressCallback(_t("Uploading report"));
+ await _submitReport(bugReportEndpoint, body, progressCallback);
+}
+
+function _submitReport(endpoint, body, progressCallback) {
+ const deferred = q.defer();
+
+ const req = new XMLHttpRequest();
+ req.open("POST", endpoint);
+ req.timeout = 5 * 60 * 1000;
+ req.onreadystatechange = function() {
+ if (req.readyState === XMLHttpRequest.LOADING) {
+ progressCallback(_t("Waiting for response from server"));
+ } else if (req.readyState === XMLHttpRequest.DONE) {
+ on_done();
+ }
+ };
+ req.send(body);
+ return deferred.promise;
+
+ function on_done() {
+ if (req.status < 200 || req.status >= 400) {
+ deferred.reject(new Error(`HTTP ${req.status}`));
+ return;
+ }
+ deferred.resolve();
+ }
+}
diff --git a/test/app-tests/joining.js b/test/app-tests/joining.js
index c5646732..d9670125 100644
--- a/test/app-tests/joining.js
+++ b/test/app-tests/joining.js
@@ -68,18 +68,16 @@ describe('joining a room', function () {
}
});
- it('should not get stuck at a spinner', function(done) {
+ it('should not get stuck at a spinner', function() {
var ROOM_ALIAS = '#alias:localhost';
var ROOM_ID = '!id:localhost';
- httpBackend.when('PUT', '/presence/'+encodeURIComponent(USER_ID)+'/status')
- .respond(200, {});
httpBackend.when('GET', '/pushrules').respond(200, {});
httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
- httpBackend.when('GET', '/sync').respond(200, {});
- httpBackend.when('POST', '/publicRooms').respond(200, {chunk: []});
- httpBackend.when('GET', '/thirdparty/protocols').respond(200, {});
- httpBackend.when('GET', '/directory/room/'+encodeURIComponent(ROOM_ALIAS)).respond(200, { room_id: ROOM_ID });
+
+ // note that we deliberately do *not* set an expectation for a
+ // presence update - setting one makes the first httpBackend.flush
+ // return before the first /sync arrives.
// start with a logged-in client
localStorage.setItem("mx_hs_url", HS_URL );
@@ -87,16 +85,43 @@ describe('joining a room', function () {
localStorage.setItem("mx_access_token", ACCESS_TOKEN );
localStorage.setItem("mx_user_id", USER_ID);
- var mc = ;
+ var mc = (
+ {throw new Error("unimplemented");}}
+ initialScreenAfterLogin={{
+ screen: 'directory',
+ }}
+ />
+ );
matrixChat = ReactDOM.render(mc, parentDiv);
- // switch to the Directory
- matrixChat._setPage(PageTypes.RoomDirectory);
-
var roomView;
- // wait for /sync to happen
- return q.delay(1).then(() => {
- return httpBackend.flush();
+
+ // wait for /sync to happen. This may take some time, as the client
+ // has to initialise indexeddb.
+ console.log("waiting for /sync");
+ let syncDone = false;
+ httpBackend.when('GET', '/sync')
+ .check((r) => {syncDone = true;})
+ .respond(200, {});
+ function awaitSync(attempts) {
+ if (syncDone) {
+ return q();
+ }
+ if (!attempts) {
+ throw new Error("Gave up waiting for /sync")
+ }
+ return httpBackend.flush().then(() => awaitSync(attempts-1));
+ }
+
+ return awaitSync(10).then(() => {
+ // wait for the directory requests
+ httpBackend.when('POST', '/publicRooms').respond(200, {chunk: []});
+ httpBackend.when('GET', '/thirdparty/protocols').respond(200, {});
+ return q.all([
+ httpBackend.flush('/thirdparty/protocols'),
+ httpBackend.flush('/publicRooms'),
+ ]);
}).then(() => {
var roomDir = ReactTestUtils.findRenderedComponentWithType(
matrixChat, RoomDirectory);
@@ -110,40 +135,44 @@ describe('joining a room', function () {
// that should create a roomview which will start a peek; wait
// for the peek.
+ httpBackend.when('GET', '/directory/room/'+encodeURIComponent(ROOM_ALIAS)).respond(200, { room_id: ROOM_ID });
httpBackend.when('GET', '/rooms/'+encodeURIComponent(ROOM_ID)+"/initialSync")
.respond(401, {errcode: 'M_GUEST_ACCESS_FORBIDDEN'});
- return httpBackend.flush();
+
+ return q.all([
+ httpBackend.flush('/directory/room/'+encodeURIComponent(ROOM_ALIAS), 1, 200),
+ httpBackend.flush('/rooms/'+encodeURIComponent(ROOM_ID)+"/initialSync", 1, 200),
+ ]);
}).then(() => {
httpBackend.verifyNoOutstandingExpectation();
+ return q.delay(1);
+ }).then(() => {
// we should now have a roomview, with a preview bar
roomView = ReactTestUtils.findRenderedComponentWithType(
matrixChat, RoomView);
- var previewBar = ReactTestUtils.findRenderedComponentWithType(
+ const previewBar = ReactTestUtils.findRenderedComponentWithType(
roomView, RoomPreviewBar);
- var joinLink = ReactTestUtils.findRenderedDOMComponentWithTag(
+ const joinLink = ReactTestUtils.findRenderedDOMComponentWithTag(
previewBar, 'a');
ReactTestUtils.Simulate.click(joinLink);
- // that will fire off a request to check our displayname, followed by a
- // join request
- httpBackend.when('GET', '/profile/'+encodeURIComponent(USER_ID))
- .respond(200, {displayname: 'boris'});
httpBackend.when('POST', '/join/'+encodeURIComponent(ROOM_ALIAS))
.respond(200, {room_id: ROOM_ID});
- return httpBackend.flush();
}).then(() => {
// wait for the join request to be made
return q.delay(1);
}).then(() => {
- // flush it through
- return httpBackend.flush();
+ // and again, because the state update has to go to the store and
+ // then one dispatch within the store, then to the view
+ // XXX: This is *super flaky*: a better way would be to declare
+ // that we expect a certain state transition to happen, then wait
+ // for that transition to occur.
+ return q.delay(1);
}).then(() => {
- httpBackend.verifyNoOutstandingExpectation();
-
// the roomview should now be loading
expect(roomView.state.room).toBe(null);
expect(roomView.state.joining).toBe(true);
@@ -152,6 +181,16 @@ describe('joining a room', function () {
ReactTestUtils.findRenderedDOMComponentWithClass(
roomView, "mx_Spinner");
+ // flush it through
+ return httpBackend.flush('/join/'+encodeURIComponent(ROOM_ALIAS));
+ }).then(() => {
+ httpBackend.verifyNoOutstandingExpectation();
+
+ return q.delay(1);
+ }).then(() => {
+ // We've joined, expect this to false
+ expect(roomView.state.joining).toBe(false);
+
// now send the room down the /sync pipe
httpBackend.when('GET', '/sync').
respond(200, {
@@ -171,8 +210,7 @@ describe('joining a room', function () {
}).then(() => {
// now the room should have loaded
expect(roomView.state.room).toExist();
- expect(roomView.state.joining).toBe(false);
- }).done(done, done);
+ });
});
});
});
diff --git a/test/app-tests/loading.js b/test/app-tests/loading.js
index 22daa395..a323a262 100644
--- a/test/app-tests/loading.js
+++ b/test/app-tests/loading.js
@@ -28,8 +28,9 @@ import jssdk from 'matrix-js-sdk';
import sdk from 'matrix-react-sdk';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
+import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
-import test_utils from '../test-utils';
+import * as test_utils from '../test-utils';
import MockHttpBackend from '../mock-request';
import {parseQs, parseQsFromFragment} from '../../src/vector/url_utils';
@@ -61,14 +62,25 @@ describe('loading:', function () {
windowLocation = null;
matrixChat = null;
+
+ languageHandler.setMissingEntryGenerator(function(key) {
+ return key.split('|', 2)[1];
+ });
});
- afterEach(function() {
+ afterEach(async function() {
if (parentDiv) {
ReactDOM.unmountComponentAtNode(parentDiv);
parentDiv.remove();
parentDiv = null;
}
+
+ // unmounting should have cleared the MatrixClientPeg
+ expect(MatrixClientPeg.get()).toBe(null);
+
+ // clear the indexeddbs so we can start from a clean slate next time.
+ await test_utils.deleteIndexedDB('matrix-js-sdk:crypto');
+ await test_utils.deleteIndexedDB('matrix-js-sdk:riot-web-sync');
});
/* simulate the load process done by index.js
@@ -87,21 +99,14 @@ describe('loading:', function () {
toString: function() { return this.search + this.hash; },
};
- let lastLoadedScreen = null;
- let appLoaded = false;
-
let loadCompleteDefer = q.defer();
loadCompletePromise = loadCompleteDefer.promise;
function onNewScreen(screen) {
console.log(Date.now() + " newscreen "+screen);
- if (!appLoaded) {
- lastLoadedScreen = screen;
- } else {
- var hash = '#/' + screen;
- windowLocation.hash = hash;
- console.log(Date.now() + " browser URI now "+ windowLocation);
- }
+ var hash = '#/' + screen;
+ windowLocation.hash = hash;
+ console.log(Date.now() + " browser URI now "+ windowLocation);
}
// Parse the given window.location and return parameters that can be used when calling
@@ -114,41 +119,48 @@ describe('loading:', function () {
}
}
- function routeUrl(location, matrixChat) {
- console.log(Date.now() + "Routing URL " + location);
- const s = getScreenFromLocation(location);
- console.log("Showing screen", s);
- matrixChat.showScreen(s.screen, s.params);
- }
-
const MatrixChat = sdk.getComponent('structures.MatrixChat');
const fragParts = parseQsFromFragment(windowLocation);
+
+ const config = Object.assign({
+ default_hs_url: DEFAULT_HS_URL,
+ default_is_url: DEFAULT_IS_URL,
+ }, opts.config || {});
+
var params = parseQs(windowLocation);
matrixChat = ReactDOM.render(
{throw new Error('Not implemented');}}
/>, parentDiv
);
+ }
- // pause for a cycle, then simulate the window.onload handler
- window.setTimeout(() => {
- console.log(Date.now() + " simulating window.onload");
- routeUrl(windowLocation, matrixChat);
- appLoaded = true;
- if (lastLoadedScreen) {
- onNewScreen(lastLoadedScreen);
- lastLoadedScreen = null;
+ // set an expectation that we will get a call to /sync, then flush
+ // http requests until we do.
+ //
+ // returns a promise resolving to the received request
+ async function expectAndAwaitSync(response) {
+ response = response || {};
+ let syncRequest = null;
+ httpBackend.when('GET', '/sync')
+ .check((r) => {syncRequest = r;})
+ .respond(200, response);
+
+ console.log("waiting for /sync");
+ for (let attempts = 10; attempts > 0; attempts--) {
+ if (syncRequest) {
+ return syncRequest;
}
- }, 0);
+ await httpBackend.flush();
+ }
+ throw new Error("Gave up waiting for /sync");
}
describe("Clean load with no stored credentials:", function() {
@@ -169,7 +181,7 @@ describe('loading:', function () {
// Wait for another trip around the event loop for the UI to update
return q.delay(1);
}).then(() => {
- // we expect a single component
+ // we expect a single component following session load
ReactTestUtils.findRenderedComponentWithType(
matrixChat, sdk.getComponent('structures.login.Login'));
expect(windowLocation.hash).toEqual("");
@@ -195,34 +207,7 @@ describe('loading:', function () {
// Wait for another trip around the event loop for the UI to update
return q.delay(1);
}).then(() => {
- // we expect a single component
- let login = ReactTestUtils.findRenderedComponentWithType(
- matrixChat, sdk.getComponent('structures.login.Login'));
- httpBackend.when('POST', '/login').check(function(req) {
- console.log(req);
- expect(req.data.type).toEqual('m.login.password');
- expect(req.data.identifier.type).toEqual('m.id.user');
- expect(req.data.identifier.user).toEqual('user');
- expect(req.data.password).toEqual('pass');
- }).respond(200, {
- user_id: '@user:id',
- device_id: 'DEVICE_ID',
- access_token: 'access_token',
- });
- login.onPasswordLogin("user", undefined, undefined, "pass")
- return httpBackend.flush();
- }).then(() => {
- // Wait for another trip around the event loop for the UI to update
- return q.delay(1);
- }).then(() => {
- // we expect a spinner
- ReactTestUtils.findRenderedComponentWithType(
- matrixChat, sdk.getComponent('elements.Spinner'));
-
- httpBackend.when('GET', '/pushrules').respond(200, {});
- httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
- httpBackend.when('GET', '/sync').respond(200, {});
- return httpBackend.flush();
+ return completeLogin(matrixChat);
}).then(() => {
// once the sync completes, we should have a room view
return awaitRoomView(matrixChat);
@@ -237,6 +222,36 @@ describe('loading:', function () {
expect(localStorage.getItem('mx_is_url')).toEqual(DEFAULT_IS_URL);
}).done(done, done);
});
+
+ it('should not register as a guest when using a #/login link', function() {
+ loadApp({
+ uriFragment: "#/login",
+ });
+
+ return q.delay(100).then(() => {
+ // we expect a single component
+ ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('structures.login.Login'));
+
+ // the only outstanding request should be a GET /login
+ // (in particular there should be no /register request for
+ // guest registration).
+ for (const req of httpBackend.requests) {
+ if (req.method === 'GET' && req.path.endsWith('/_matrix/client/r0/login')) {
+ continue;
+ }
+
+ throw new Error(`Unexpected HTTP request to ${req}`);
+ }
+ return completeLogin(matrixChat);
+ }).then(() => {
+
+ // once the sync completes, we should have a room view
+ ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('structures.HomePage'));
+ expect(windowLocation.hash).toEqual("#/home");
+ });
+ });
});
describe("MatrixClient rehydrated from stored credentials:", function() {
@@ -245,31 +260,50 @@ describe('loading:', function () {
localStorage.setItem("mx_is_url", "http://localhost" );
localStorage.setItem("mx_access_token", "access_token");
localStorage.setItem("mx_user_id", "@me:localhost");
+ localStorage.setItem("mx_last_room_id", "!last_room:id");
});
- it('shows a directory by default if we have no joined rooms', function(done) {
+ it('shows the last known room by default', function() {
httpBackend.when('GET', '/pushrules').respond(200, {});
httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
- httpBackend.when('GET', '/sync').respond(200, {});
loadApp();
return awaitSyncingSpinner(matrixChat).then(() => {
// we got a sync spinner - let the sync complete
- return httpBackend.flush();
+ return expectAndAwaitSync();
}).then(() => {
- // once the sync completes, we should have a directory
+ // once the sync completes, we should have a room view
+ return awaitRoomView(matrixChat);
+ }).then(() => {
+ httpBackend.verifyNoOutstandingExpectation();
+ expect(windowLocation.hash).toEqual("#/room/!last_room:id");
+ });
+ });
+
+ it('shows a home page by default if we have no joined rooms', function(done) {
+ localStorage.removeItem("mx_last_room_id");
+
+ httpBackend.when('GET', '/pushrules').respond(200, {});
+ httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
+
+ loadApp();
+
+ return awaitSyncingSpinner(matrixChat).then(() => {
+ // we got a sync spinner - let the sync complete
+ return expectAndAwaitSync();
+ }).then(() => {
+ // once the sync completes, we should have a home page
httpBackend.verifyNoOutstandingExpectation();
ReactTestUtils.findRenderedComponentWithType(
- matrixChat, sdk.getComponent('structures.RoomDirectory'));
- expect(windowLocation.hash).toEqual("#/directory");
+ matrixChat, sdk.getComponent('structures.HomePage'));
+ expect(windowLocation.hash).toEqual("#/home");
}).done(done, done);
});
it('shows a room view if we followed a room link', function(done) {
httpBackend.when('GET', '/pushrules').respond(200, {});
httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
- httpBackend.when('GET', '/sync').respond(200, {});
loadApp({
uriFragment: "#/room/!room:id",
@@ -277,7 +311,7 @@ describe('loading:', function () {
return awaitSyncingSpinner(matrixChat).then(() => {
// we got a sync spinner - let the sync complete
- return httpBackend.flush();
+ return expectAndAwaitSync();
}).then(() => {
// once the sync completes, we should have a room view
return awaitRoomView(matrixChat);
@@ -285,12 +319,81 @@ describe('loading:', function () {
httpBackend.verifyNoOutstandingExpectation();
expect(windowLocation.hash).toEqual("#/room/!room:id");
}).done(done, done);
+ });
+ it("logs in correctly with a Riot Team Server", function() {
+ sdk.setFetch(httpBackend.fetchFn); // XXX: ought to restore this!
+
+ httpBackend.when('GET', '/pushrules').respond(200, {});
+ httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
+
+ loadApp({
+ config: {
+ teamServerConfig: {
+ teamServerURL: 'http://my_team_server',
+ },
+ },
+ });
+
+ return q.delay(1).then(() => {
+ // we expect a loading spinner while we log into the RTS
+ assertAtLoadingSpinner(matrixChat);
+
+ httpBackend.when('GET', 'my_team_server/login').respond(200, {
+ team_token: 'nom',
+ });
+ return httpBackend.flush();
+ }).then(() => {
+ return awaitSyncingSpinner(matrixChat)
+ }).then(() => {
+ // we got a sync spinner - let the sync complete
+ return expectAndAwaitSync();
+ }).then(() => {
+ // once the sync completes, we should have a home page
+ ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('structures.HomePage'));
+ });
+ });
+
+ describe('/#/login link:', function() {
+ beforeEach(function() {
+ loadApp({
+ uriFragment: "#/login",
+ });
+ });
+
+ it('shows a login view', function() {
+ // we expect a single component
+ ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('structures.login.Login')
+ );
+
+ // the only outstanding request should be a GET /login
+ // (in particular there should be no /register request for
+ // guest registration, nor /sync, etc).
+ for (const req of httpBackend.requests) {
+ if (req.method === 'GET' && req.path.endsWith('/_matrix/client/r0/login')) {
+ continue;
+ }
+
+ throw new Error(`Unexpected HTTP request to ${req}`);
+ }
+ });
+
+ it('shows the homepage after login', function() {
+ return completeLogin(matrixChat).then(() => {
+ // we should see a home page, even though we previously had
+ // a stored mx_last_room_id
+ ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('structures.HomePage'));
+ expect(windowLocation.hash).toEqual("#/home");
+ });
+ });
});
});
describe('Guest auto-registration:', function() {
- it('shows a directory by default', function (done) {
+ it('shows a home page by default', function (done) {
loadApp();
q.delay(1).then(() => {
@@ -310,14 +413,13 @@ describe('loading:', function () {
return awaitSyncingSpinner(matrixChat);
}).then(() => {
// we got a sync spinner - let the sync complete
- httpBackend.when('GET', '/sync').respond(200, {});
- return httpBackend.flush();
+ return expectAndAwaitSync();
}).then(() => {
- // once the sync completes, we should have a directory
+ // once the sync completes, we should have a home page
httpBackend.verifyNoOutstandingExpectation();
ReactTestUtils.findRenderedComponentWithType(
- matrixChat, sdk.getComponent('structures.RoomDirectory'));
- expect(windowLocation.hash).toEqual("#/directory");
+ matrixChat, sdk.getComponent('structures.HomePage'));
+ expect(windowLocation.hash).toEqual("#/home");
}).done(done, done);
});
@@ -344,16 +446,15 @@ describe('loading:', function () {
}).then(() => {
return awaitSyncingSpinner(matrixChat);
}).then(() => {
- httpBackend.when('GET', '/sync').check(function(req) {
- expect(req.path).toMatch(new RegExp("^https://homeserver/"));
- }).respond(200, {});
- return httpBackend.flush();
- }).then(() => {
- // once the sync completes, we should have a directory
+ return expectAndAwaitSync();
+ }).then((req) => {
+ expect(req.path).toMatch(new RegExp("^https://homeserver/"));
+
+ // once the sync completes, we should have a home page
httpBackend.verifyNoOutstandingExpectation();
ReactTestUtils.findRenderedComponentWithType(
- matrixChat, sdk.getComponent('structures.RoomDirectory'));
- expect(windowLocation.hash).toEqual("#/directory");
+ matrixChat, sdk.getComponent('structures.HomePage'));
+ expect(windowLocation.hash).toEqual("#/home");
expect(MatrixClientPeg.get().baseUrl).toEqual("https://homeserver");
expect(MatrixClientPeg.get().idBaseUrl).toEqual("https://idserver");
}).done(done, done);
@@ -379,8 +480,7 @@ describe('loading:', function () {
}).then(() => {
return awaitSyncingSpinner(matrixChat);
}).then(() => {
- httpBackend.when('GET', '/sync').respond(200, {});
- return httpBackend.flush();
+ return expectAndAwaitSync();
}).then(() => {
// once the sync completes, we should have a room view
return awaitRoomView(matrixChat);
@@ -429,6 +529,45 @@ describe('loading:', function () {
}).done(done, done);
});
});
+
+
+ // check that we have a Login component, send a 'user:pass' login,
+ // and await the HTTP requests.
+ function completeLogin(matrixChat) {
+ // we expect a single component
+ const login = ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('structures.login.Login'));
+
+ httpBackend.when('POST', '/login').check(function(req) {
+ console.log(req);
+ expect(req.data.type).toEqual('m.login.password');
+ expect(req.data.identifier.type).toEqual('m.id.user');
+ expect(req.data.identifier.user).toEqual('user');
+ expect(req.data.password).toEqual('pass');
+ }).respond(200, {
+ user_id: '@user:id',
+ device_id: 'DEVICE_ID',
+ access_token: 'access_token',
+ });
+ login.onPasswordLogin("user", undefined, undefined, "pass");
+
+ return httpBackend.flush().then(() => {
+ // Wait for another trip around the event loop for the UI to update
+ return q.delay(1);
+ }).then(() => {
+ // we expect a spinner
+ ReactTestUtils.findRenderedComponentWithType(
+ matrixChat, sdk.getComponent('elements.Spinner'));
+
+ httpBackend.when('GET', '/pushrules').respond(200, {});
+ httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
+ return expectAndAwaitSync().catch((e) => {
+ throw new Error("Never got /sync after login: did the client start?");
+ });
+ }).then(() => {
+ httpBackend.verifyNoOutstandingExpectation();
+ });
+ }
});
// assert that we are on the loading page
@@ -444,19 +583,21 @@ function assertAtLoadingSpinner(matrixChat) {
// the page includes a logout link.
function awaitSyncingSpinner(matrixChat, retryLimit, retryCount) {
if (retryLimit === undefined) {
- retryLimit = 5;
+ retryLimit = 10;
}
if (retryCount === undefined) {
retryCount = 0;
}
- if (matrixChat.state.loading) {
+ if (matrixChat.state.loading || matrixChat.state.loggingIn) {
console.log(Date.now() + " Awaiting sync spinner: still loading.");
if (retryCount >= retryLimit) {
throw new Error("MatrixChat still not loaded after " +
retryCount + " tries");
}
- return q.delay(0).then(() => {
+ // loading can take quite a long time, because we delete the
+ // indexedDB store.
+ return q.delay(5).then(() => {
return awaitSyncingSpinner(matrixChat, retryLimit, retryCount + 1);
});
}
diff --git a/test/mock-request.js b/test/mock-request.js
index 8510ad54..64ac6c06 100644
--- a/test/mock-request.js
+++ b/test/mock-request.js
@@ -1,6 +1,6 @@
"use strict";
-var q = require("q");
-var expect = require('expect');
+const q = require("q");
+import expect from 'expect';
/**
* Construct a mock HTTP backend, heavily inspired by Angular.js.
@@ -9,24 +9,53 @@ var expect = require('expect');
function HttpBackend() {
this.requests = [];
this.expectedRequests = [];
- var self = this;
+ const self = this;
// the request function dependency that the SDK needs.
this.requestFn = function(opts, callback) {
- var realReq = new Request(opts.method, opts.uri, opts.body, opts.qs);
- realReq.callback = callback;
- console.log("HTTP backend received request: %s %s", opts.method, opts.uri);
- self.requests.push(realReq);
+ const req = new Request(opts, callback);
+ console.log(`${Date.now()} HTTP backend received request: ${req}`);
+ self.requests.push(req);
- var abort = function() {
- var idx = self.requests.indexOf(realReq);
+ const abort = function() {
+ const idx = self.requests.indexOf(req);
if (idx >= 0) {
- console.log("Aborting HTTP request: %s %s", opts.method, opts.uri);
+ console.log("Aborting HTTP request: %s %s", opts.method,
+ opts.uri);
self.requests.splice(idx, 1);
+ req.callback("aborted");
}
- }
- return {
- abort: abort
};
+
+ return {
+ abort: abort,
+ };
+ };
+
+ // very simplistic mapping from the whatwg fetch interface onto the request
+ // interface, so we can use the same mock backend for both.
+ this.fetchFn = function(input, init) {
+ init = init || {};
+ const requestOpts = {
+ uri: input,
+ method: init.method || 'GET',
+ body: init.body,
+ };
+
+ return new Promise((resolve, reject) => {
+ function callback(err, response, body) {
+ if (err) {
+ reject(err);
+ }
+ resolve({
+ ok: response.statusCode >= 200 && response.statusCode < 300,
+ json: () => body,
+ });
+ };
+
+ const req = new Request(requestOpts, callback);
+ console.log(`HTTP backend received request: ${req}`);
+ self.requests.push(req);
+ });
};
}
HttpBackend.prototype = {
@@ -34,43 +63,58 @@ HttpBackend.prototype = {
* Respond to all of the requests (flush the queue).
* @param {string} path The path to flush (optional) default: all.
* @param {integer} numToFlush The number of things to flush (optional), default: all.
- * @return {Promise} resolved when there is nothing left to flush.
+ * @param {integer=} waitTime The time (in ms) to wait for a request to happen.
+ * default: 100
+ *
+ * @return {Promise} resolves when there is nothing left to flush, with the
+ * number of requests flushed
*/
- flush: function(path, numToFlush) {
- var defer = q.defer();
- var self = this;
- var flushed = 0;
- var triedWaiting = false;
- console.log(
- "HTTP backend flushing... (path=%s numToFlush=%s)", path, numToFlush
+ flush: function(path, numToFlush, waitTime) {
+ const defer = q.defer();
+ const self = this;
+ let flushed = 0;
+ if (waitTime === undefined) {
+ waitTime = 100;
+ }
+
+ function log(msg) {
+ console.log(`${Date.now()} flush[${path || ''}]: ${msg}`);
+ }
+
+ log("HTTP backend flushing... (path=" + path
+ + " numToFlush=" + numToFlush
+ + " waitTime=" + waitTime
+ + ")",
);
- var tryFlush = function() {
+ const endTime = waitTime + Date.now();
+
+ const tryFlush = function() {
// if there's more real requests and more expected requests, flush 'em.
- console.log(
- " trying to flush queue => reqs=%s expected=%s [%s]",
- self.requests.length, self.expectedRequests.length, path
+ log(` trying to flush => reqs=[${self.requests}] ` +
+ `expected=[${self.expectedRequests}]`,
);
if (self._takeFromQueue(path)) {
// try again on the next tick.
- console.log(" flushed. Trying for more. [%s]", path);
flushed += 1;
if (numToFlush && flushed === numToFlush) {
- console.log(" [%s] Flushed assigned amount: %s", path, numToFlush);
- defer.resolve();
- }
- else {
+ log(`Flushed assigned amount: ${numToFlush}`);
+ defer.resolve(flushed);
+ } else {
+ log(` flushed. Trying for more.`);
setTimeout(tryFlush, 0);
}
- }
- else if (flushed === 0 && !triedWaiting) {
+ } else if (flushed === 0 && Date.now() < endTime) {
// we may not have made the request yet, wait a generous amount of
// time before giving up.
+ log(` nothing to flush yet; waiting for requests.`);
setTimeout(tryFlush, 5);
- triedWaiting = true;
- }
- else {
- console.log(" no more flushes. [%s]", path);
- defer.resolve();
+ } else {
+ if (flushed === 0) {
+ log("nothing to flush; giving up");
+ } else {
+ log(`no more flushes after flushing ${flushed} requests`);
+ }
+ defer.resolve(flushed);
}
};
@@ -85,14 +129,19 @@ HttpBackend.prototype = {
* @return {boolean} true if something was resolved.
*/
_takeFromQueue: function(path) {
- var req = null;
- var i, j;
- var matchingReq, expectedReq, testResponse = null;
+ let req = null;
+ let i;
+ let j;
+ let matchingReq = null;
+ let expectedReq = null;
+ let testResponse = null;
for (i = 0; i < this.requests.length; i++) {
req = this.requests[i];
for (j = 0; j < this.expectedRequests.length; j++) {
expectedReq = this.expectedRequests[j];
- if (path && path !== expectedReq.path) { continue; }
+ if (path && path !== expectedReq.path) {
+ continue;
+ }
if (expectedReq.method === req.method &&
req.path.indexOf(expectedReq.path) !== -1) {
if (!expectedReq.data || (JSON.stringify(expectedReq.data) ===
@@ -113,13 +162,13 @@ HttpBackend.prototype = {
matchingReq.checks[j](req);
}
testResponse = matchingReq.response;
- console.log(" responding to %s", matchingReq.path);
- var body = testResponse.body;
+ console.log(`${Date.now()} responding to ${matchingReq.path}`);
+ let body = testResponse.body;
if (Object.prototype.toString.call(body) == "[object Function]") {
body = body(req.path, req.data);
}
req.callback(
- testResponse.err, testResponse.response, body
+ testResponse.err, testResponse.response, body,
);
matchingReq = null;
}
@@ -134,10 +183,10 @@ HttpBackend.prototype = {
* Makes sure that the SDK hasn't sent any more requests to the backend.
*/
verifyNoOutstandingRequests: function() {
- var firstOutstandingReq = this.requests[0] || {};
+ const firstOutstandingReq = this.requests[0] || {};
expect(this.requests.length).toEqual(0,
"Expected no more HTTP requests but received request to " +
- firstOutstandingReq.path
+ firstOutstandingReq.path,
);
},
@@ -145,12 +194,9 @@ HttpBackend.prototype = {
* Makes sure that the test doesn't have any unresolved requests.
*/
verifyNoOutstandingExpectation: function() {
- var firstOutstandingExpectation = this.expectedRequests[0] || {};
- expect(this.expectedRequests.length).toEqual(
- 0,
- "Expected to see HTTP request for "
- + firstOutstandingExpectation.method
- + " " + firstOutstandingExpectation.path
+ const firstOutstandingExpectation = this.expectedRequests[0] || {};
+ expect(this.expectedRequests.length).toEqual(0,
+ "Expected to see HTTP request for " + firstOutstandingExpectation.path,
);
},
@@ -162,22 +208,36 @@ HttpBackend.prototype = {
* @return {Request} An expected request.
*/
when: function(method, path, data) {
- var pendingReq = new Request(method, path, data);
+ const pendingReq = new ExpectedRequest(method, path, data);
this.expectedRequests.push(pendingReq);
return pendingReq;
- }
+ },
};
-function Request(method, path, data, queryParams) {
+/**
+ * Represents the expectation of a request.
+ *
+ *
Includes the conditions to be matched against, the checks to be made,
+ * and the response to be returned.
+ *
+ * @constructor
+ * @param {string} method
+ * @param {string} path
+ * @param {object?} data
+ */
+function ExpectedRequest(method, path, data) {
this.method = method;
this.path = path;
this.data = data;
- this.queryParams = queryParams;
- this.callback = null;
this.response = null;
this.checks = [];
}
-Request.prototype = {
+
+ExpectedRequest.prototype = {
+ toString: function() {
+ return this.method + " " + this.path
+ },
+
/**
* Execute a check when this request has been satisfied.
* @param {Function} fn The function to execute.
@@ -198,10 +258,10 @@ Request.prototype = {
this.response = {
response: {
statusCode: code,
- headers: {}
+ headers: {},
},
body: data,
- err: null
+ err: null,
};
},
@@ -214,14 +274,62 @@ Request.prototype = {
this.response = {
response: {
statusCode: code,
- headers: {}
+ headers: {},
},
body: null,
- err: err
+ err: err,
};
},
};
+/**
+ * Represents a request made by the app.
+ *
+ * @constructor
+ * @param {object} opts opts passed to request()
+ * @param {function} callback
+ */
+function Request(opts, callback) {
+ this.opts = opts;
+ this.callback = callback;
+
+ Object.defineProperty(this, 'method', {
+ get: function() {
+ return opts.method;
+ },
+ });
+
+ Object.defineProperty(this, 'path', {
+ get: function() {
+ return opts.uri;
+ },
+ });
+
+ Object.defineProperty(this, 'data', {
+ get: function() {
+ return opts.body;
+ },
+ });
+
+ Object.defineProperty(this, 'queryParams', {
+ get: function() {
+ return opts.qs;
+ },
+ });
+
+ Object.defineProperty(this, 'headers', {
+ get: function() {
+ return opts.headers || {};
+ },
+ });
+}
+
+Request.prototype = {
+ toString: function() {
+ return this.method + " " + this.path;
+ },
+};
+
/**
* The HttpBackend class.
*/
diff --git a/test/skin-sdk.js b/test/skin-sdk.js
index a5a7233c..3421d5d0 100644
--- a/test/skin-sdk.js
+++ b/test/skin-sdk.js
@@ -5,4 +5,4 @@
*/
var sdk = require('matrix-react-sdk');
-sdk.loadSkin(require('component-index'));
+sdk.loadSkin(require('../src/component-index'));
diff --git a/test/test-utils.js b/test/test-utils.js
index 53528e5c..a1c1cd0a 100644
--- a/test/test-utils.js
+++ b/test/test-utils.js
@@ -7,7 +7,7 @@ var q = require('q');
* name to stdout.
* @param {Mocha.Context} context The test context
*/
-module.exports.beforeEach = function(context) {
+export function beforeEach(context) {
var desc = context.currentTest.fullTitle();
console.log();
console.log(desc);
@@ -16,13 +16,40 @@ module.exports.beforeEach = function(context) {
// some tests store things in localstorage. Improve independence of tests
// by making sure that they don't inherit any old state.
window.localStorage.clear();
-};
+}
/**
* returns true if the current environment supports webrtc
*/
-module.exports.browserSupportsWebRTC = function() {
+export function browserSupportsWebRTC() {
var n = global.window.navigator;
return n.getUserMedia || n.webkitGetUserMedia ||
n.mozGetUserMedia;
-};
+}
+
+export function deleteIndexedDB(dbName) {
+ return new q.Promise((resolve, reject) => {
+ if (!window.indexedDB) {
+ resolve();
+ return;
+ }
+
+ console.log(`Removing indexeddb instance: ${dbName}`);
+ const req = window.indexedDB.deleteDatabase(dbName);
+
+ req.onblocked = () => {
+ console.log(`can't yet delete indexeddb because it is open elsewhere`);
+ };
+
+ req.onerror = (ev) => {
+ reject(new Error(
+ "unable to delete indexeddb: " + ev.target.error,
+ ));
+ };
+
+ req.onsuccess = () => {
+ console.log(`Removed indexeddb instance: ${dbName}`);
+ resolve();
+ };
+ });
+}
diff --git a/test/unit-tests/notifications/ContentRules-test.js b/test/unit-tests/notifications/ContentRules-test.js
index e7928147..c1cdc40a 100644
--- a/test/unit-tests/notifications/ContentRules-test.js
+++ b/test/unit-tests/notifications/ContentRules-test.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-var notifications = require('notifications');
+var notifications = require('../../../src/notifications');
var ContentRules = notifications.ContentRules;
var PushRuleVectorState = notifications.PushRuleVectorState;
diff --git a/test/unit-tests/notifications/PushRuleVectorState-test.js b/test/unit-tests/notifications/PushRuleVectorState-test.js
index 6b0f81c6..68e7044f 100644
--- a/test/unit-tests/notifications/PushRuleVectorState-test.js
+++ b/test/unit-tests/notifications/PushRuleVectorState-test.js
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-var notifications = require('notifications');
+var notifications = require('../../../src/notifications');
var prvs = notifications.PushRuleVectorState;
diff --git a/webpack.config.js b/webpack.config.js
index e32f7177..5d4fef72 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,7 +1,7 @@
-var path = require('path');
-var webpack = require('webpack');
-var ExtractTextPlugin = require("extract-text-webpack-plugin");
-var HtmlWebpackPlugin = require('html-webpack-plugin');
+const path = require('path');
+const webpack = require('webpack');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
@@ -10,7 +10,7 @@ module.exports = {
// We ship olm.js as a separate lump of javascript. This makes it get
// loaded via a separate tag in index.html (which loads it
- // into the browser global `Olm`), and define it as an external below.
+ // into the browser global `Olm`, where js-sdk expects to find it).
//
// (we should probably make js-sdk load it asynchronously at some
// point, so that it doesn't block the pageload, but that is a separate
@@ -19,11 +19,11 @@ module.exports = {
// CSS themes
"theme-light": "./src/skins/vector/css/themes/light.scss",
- "theme-dark": "./src/skins/vector/css/themes/dark.scss"
+ "theme-dark": "./src/skins/vector/css/themes/dark.scss",
},
module: {
preLoaders: [
- { test: /\.js$/, loader: "source-map-loader" }
+ { test: /\.js$/, loader: "source-map-loader" },
],
loaders: [
{ test: /\.json$/, loader: "json" },
@@ -38,9 +38,7 @@ module.exports = {
// would also drag in the imgs and fonts that our CSS refers to
// as webpack inputs.)
// 3. ExtractTextPlugin turns that string into a separate asset.
- loader: ExtractTextPlugin.extract(
- "css-raw-loader!postcss-loader?config=postcss.config.js"
- ),
+ loader: ExtractTextPlugin.extract("css-raw-loader!postcss-loader?config=postcss.config.js"),
},
{
// this works similarly to the scss case, without postcss.
@@ -49,15 +47,18 @@ module.exports = {
},
],
noParse: [
+ // for cross platform compatibility use [\\\/] as the path separator
+ // this ensures that the regex trips on both Windows and *nix
+
// don't parse the languages within highlight.js. They cause stack
// overflows (https://github.com/webpack/webpack/issues/1721), and
// there is no need for webpack to parse them - they can just be
// included as-is.
- /highlight\.js\/lib\/languages/,
+ /highlight\.js[\\\/]lib[\\\/]languages/,
// olm takes ages for webpack to process, and it's already heavily
// optimised, so there is little to gain by us uglifying it.
- /olm\/(javascript\/)?olm\.js$/,
+ /olm[\\\/](javascript[\\\/])?olm\.js$/,
],
},
output: {
@@ -83,7 +84,7 @@ module.exports = {
// various levels of '.' and '..'
// Also, sometimes the resource path is absolute.
return path.relative(process.cwd(), info.resourcePath).replace(/^[\/\.]*/, '');
- }
+ },
},
resolve: {
alias: {
@@ -98,7 +99,6 @@ module.exports = {
},
},
externals: {
- "olm": "Olm",
// Don't try to bundle electron: leave it as a commonjs dependency
// (the 'commonjs' here means it will output a 'require')
"electron": "commonjs electron",
@@ -106,16 +106,13 @@ module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env': {
- NODE_ENV: JSON.stringify(process.env.NODE_ENV)
- }
+ NODE_ENV: JSON.stringify(process.env.NODE_ENV),
+ },
}),
- new ExtractTextPlugin(
- "bundles/[hash]/[name].css",
- {
- allChunks: true
- }
- ),
+ new ExtractTextPlugin("bundles/[hash]/[name].css", {
+ allChunks: true,
+ }),
new HtmlWebpackPlugin({
template: './src/vector/index.html',