diff --git a/.travis.yml b/.travis.yml
index 08126853a19e1bdc04faa858f18b2357c20a9975..443836cfa82bc9deec1f7cc3ac8704cadd171a67 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -137,11 +137,11 @@ before_install:
     # Use TRAVIS_TAG if defined, or the short commit SHA otherwise
     - export VERSION=${TRAVIS_TAG:-$(git rev-parse --short HEAD)}
 install:
-    - ./.ci/install.sh
+    - travis_wait ./.ci/install.sh
     - export PATH=/usr/local/bin:${PATH}
 
 script:
-    - ./.ci/script.sh
+    - travis_wait ./.ci/script.sh
     - sed -i -e "s/VERSION_NAME_VALUE/${VERSION}/g" ./.ci/bintray-release.json || true
     - cp ./.ci/bintray-release.json .
 deploy:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 282dc3ae7e73fce216b3e6507c255b99551add00..c962d2da4dad7c2e5ce032ff3a755eafda6c8c88 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,8 +35,6 @@ option(USE_BUNDLED_OPENSSL "Use the bundled version of OpenSSL."
 option(USE_BUNDLED_MTXCLIENT "Use the bundled version of the Matrix Client library." ${HUNTER_ENABLED})
 option(USE_BUNDLED_SODIUM "Use the bundled version of libsodium."
 	${HUNTER_ENABLED})
-option(USE_BUNDLED_ZLIB "Use the bundled version of zlib."
-	${HUNTER_ENABLED})
 option(USE_BUNDLED_LMDB "Use the bundled version of lmdb."
 	${HUNTER_ENABLED})
 option(USE_BUNDLED_LMDBXX "Use the bundled version of lmdb++."
@@ -323,10 +321,7 @@ find_package(Boost 1.70 REQUIRED
 	COMPONENTS iostreams
 	system
 	thread)
-if(USE_BUNDLED_ZLIB)
-	hunter_add_package(ZLIB)
-endif()
-find_package(ZLIB REQUIRED)
+
 if(USE_BUNDLED_OPENSSL)
 	hunter_add_package(OpenSSL)
 endif()
@@ -338,7 +333,7 @@ if(USE_BUNDLED_MTXCLIENT)
 	FetchContent_Declare(
 		MatrixClient
 		GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
-		GIT_TAG        71bd56b66cf634341ffef804f07d33f01fd57c25
+		GIT_TAG        1018c0822b80cdfc5d6b589fe94d1fd759113ef6
 		)
 	FetchContent_MakeAvailable(MatrixClient)
 else()
diff --git a/README.md b/README.md
index 0cb3e04416f1b473b6e57e7db981ab91a824726c..d051eadd000562b40bdc17edb9a1a7177c62ff7c 100644
--- a/README.md
+++ b/README.md
@@ -97,13 +97,6 @@ guix install nheko
 
 #### macOS (10.14 and above)
 
-
-with [macports](https://www.macports.org/):
-
-```sh
-sudo port install nheko
-```
-
 with [homebrew](https://brew.sh/):
 
 ```sh
@@ -120,7 +113,7 @@ brew cask install nheko
 - [LMDB](https://symas.com/lightning-memory-mapped-database/)
 - [cmark](https://github.com/commonmark/cmark) 0.29 or greater.
 - Boost 1.70 or greater.
-- [libolm](https://git.matrix.org/git/olm)
+- [libolm](https://gitlab.matrix.org/matrix-org/olm)
 - [libsodium](https://github.com/jedisct1/libsodium)
 - [spdlog](https://github.com/gabime/spdlog)
 - A compiler that supports C++ 17:
@@ -210,7 +203,7 @@ guix environment nheko
 
 ```bash
 brew update
-brew install qt5 lmdb cmake llvm libsodium spdlog boost cmark
+brew install qt5 lmdb cmake llvm libsodium spdlog boost cmark libolm
 ```
 
 ##### Windows
diff --git a/io.github.NhekoReborn.Nheko.json b/io.github.NhekoReborn.Nheko.json
index 60d984fb84bba66874a0db49257c9ac060017a35..3de0437069f8d6da86c4e2e1723a005b73338701 100644
--- a/io.github.NhekoReborn.Nheko.json
+++ b/io.github.NhekoReborn.Nheko.json
@@ -146,9 +146,9 @@
       "name": "mtxclient",
       "sources": [
         {
-          "sha256": "7055f1459a43a12f27f949564624f13cc593ac894e445e6de0e6563ad38ebc3e",
+          "sha256": "537f4e6b280f351ad950cd6598c2407505a55f0d6c856b4ff97a9c59fc6fdb7a",
           "type": "archive",
-          "url": "https://github.com/Nheko-Reborn/mtxclient/archive/71bd56b66cf634341ffef804f07d33f01fd57c25.tar.gz"
+          "url": "https://github.com/Nheko-Reborn/mtxclient/archive/1018c0822b80cdfc5d6b589fe94d1fd759113ef6.tar.gz"
         }
       ]
     },
diff --git a/resources/langs/.gitignore b/resources/langs/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fc168248ef15236745b289874e2d3175fa0e575a
--- /dev/null
+++ b/resources/langs/.gitignore
@@ -0,0 +1 @@
+*.qm
\ No newline at end of file
diff --git a/resources/langs/nheko_de.ts b/resources/langs/nheko_de.ts
index 90f0e7d3a30ed44aaeff1ebe4cbf624484d5da3c..24c6cea77a43d0dfeb4206e6ed4143976c300647 100644
--- a/resources/langs/nheko_de.ts
+++ b/resources/langs/nheko_de.ts
@@ -245,7 +245,7 @@
     <message>
         <location line="+2"/>
         <source>This message is not encrypted!</source>
-        <translation type="unfinished"></translation>
+        <translation>Diese Nachricht ist nicht verschlüsselt!</translation>
     </message>
 </context>
 <context>
@@ -673,7 +673,7 @@ Beispiel: https://mein.server:8787</translation>
     <message>
         <location line="+2"/>
         <source>%1 made this room require and invitation to join.</source>
-        <translation type="unfinished"></translation>
+        <translation>%1 hat eingestellt, dass dieser Raum eine Einladung benötigt um beizutreten.</translation>
     </message>
     <message>
         <location line="+23"/>
@@ -1037,7 +1037,7 @@ Beispiel: https://mein.server:8787</translation>
     <message>
         <location line="+25"/>
         <source>INTERFACE</source>
-        <translation type="unfinished"></translation>
+        <translation>OBERFLÄCHE</translation>
     </message>
     <message>
         <location line="+108"/>
diff --git a/resources/langs/nheko_en.qm b/resources/langs/nheko_en.qm
deleted file mode 100644
index 0973db2d9c4232eec42ce38a1493607f33abb136..0000000000000000000000000000000000000000
--- a/resources/langs/nheko_en.qm
+++ /dev/null
@@ -1,82 +0,0 @@
-<¸dÊÍ!¿`¡½ÝB�� ��;��„�Ï��c=�þ��XB�H5��î�H5��T�‹t��,°�Œ��Fv�œT��-�Ÿg��FŸ� %r��ì�&Ã#��,0�H/ƒ��S~�Hw9��‘�J6•��Bž�J6•��\`�LF	��.J�L™b��Jè�M'ã��lY�Q;Þ��œ�Q;Þ��R�TÊ´��d`�Uð­��tW�XÇ9��Bo�XÇ9��Cë�Zì5��Q�[fó���[fó��US�hÂá��sÐ�ˆÎÞ��&é�¨Þ��C�±å~��"3�Ëý��;ÿ�×¹À��!z�Ûe��DQ'òÑ��$ÓL<™��]xO+%��pêQc^��(\ks��®^È��3$r n��A“‘õÿ��Y½™·��O=³7ž��?�¶ˆ=��>`»ÙS��bÅÉŽ��!Ù×Lé��P£ã&5��$‚÷º¤��aþð1��äŒS��Fý&¥Þ��º(Õ¾��;=/§™��ayL3��E„‚��pª7õ��W®›
~��6'Éëa��Q±Õî³��^üøÈA��aÀ˜3��-`c��CX-`c��N8-`c��\™^)��N„´Lþ��2ÃŒÃ��E‘Þô±��êÌa���£ì»#��Eü9CÞ��5¥A€¾��8yœt��*H‚M©��%í†E��^x‹[Y��Kÿ“¤1��
-÷˜I¼��¾˜I¼��Sµ˜I¼��UŠ˜I¼��Ws˜I¼��X
-˜I¼��YN˜I¼��Y‡˜I¼��Z ˜I¼��[4­Tt��I
-È´��,zà„ï��oâTt��M⪯��rîs¾��0vød.��5ÿ•"��q¸nŽ��({™“��\1m��;Œ!¬4��Tµ5æÄ��FÈNÌÞ��gO	Å��mÙOzž��[©]¤Î��@)gîe��LEr,N��3dtݾ��%~€£��pŒFÅ��ˆºã��lΦÂÞ��Rh¨³¤��K¨·1��\굑��kjÇ5t��Zðß§^��-—õD��+Ý ùS��e§!–s��c¾0PŽ��4„5Óã��©fö]��+LoE��.È{��B:”õ)��d©ƒƒ��3«­ù��¯.¹��PW°_��fŽË2��GÈÎ|î��OÑIG��-ÑÕ"��n¡öÕ��O†	Â.��àɝ��*ü,4N��7ÉfÊ��XÊi܃��Oók¯��Ak³��¢m"?��@–yb��AS•ž��k·U>��¿‘¥��má0¾��HÇ+šó��^*-Kž��ïGD.��1ùJòÁ��b>kbŽ��0àm4%��C z~��9”ùN��NͦëE��MHªãä��ªãä��%TÏk��l	¾��cs	*˜Ô��v	9ûu�� 	=ŒÅ��	_Á��eY	k ‘��Ð	oÊÞ����	oÊÞ��AÙ	…Á²��V	‹6Å��so	ŒvÓ��D	©ÒÅ��pL	¬Ðá��¸	¶ôH��&‰	¾Â��(B	¾Â��R0	ÉCõ��)¿	ø°5��MÝ
-lþ��_Y
-šc��Þ
-Õ��oÊ
-/–4��T8
-5ôa��L
-=Ý��Sï
-?iÕ��rê
-@›ž��
-C0�� ®
-T*N��7_
-d
U��$(
-dÐÍ��UÆ
-dÐÍ��[m
-efz��Zd
-n��?@
-{™I��Tþ
-„I��/±
-—àQ��3§
-WÞ��/[
- 6ô��E
-¬ÕI��S?
-°ÔÉ��kÏ
-·Ñe��DÀ
-º0��*
-Ìùƒ��j/
-êI^��/ò
-ëf	��-L
-ëf	��]Ù–c��mUgN��:ÌŽ��:ñ(Fþ��aW0Þ³��XtG›t��)øQÿ©��Mˆ÷T��Éœ	4��,ࢦ��L…§­4��ÐÂÀê��I™ïÎ��e§
��=¢,-m��i¸3âM��<ÃEn��JHXÊ��1}[c��EÅr¿Ý��*¹r¿Ý��ETv—¥��@Ö~VW��¯‡(>��4/ŽíÁ���YV��QP˜jò��#éœtN��6ÚÚk��l‰»s��F?»s��fLÆÓÂ��GRÇ[^��gÑu$��TÒíÁ��
oàó��d™ù>��H‡
x.��?¶
/v¢��eò
2%.��Í
5òŽ��_¡
TA��]+
o��BÎ
yyò��jm
 ¡��
‰ÌS��dê
®!��
¹ÀÃ��m‹
¼ÉÞ��ö
ÜZ��jðY.c��t[¤½��
¿y.c��›¿
-3�� cåæ	��+†®��86	æÎ��n1+Î��qE8b��L¿l€Õ��t›wÅ��H,Œxð��o]ŒðÕ��/
ŽZ°��rz™HÁ��!¬Ëã��KhµÎ��VwÇY��IAâ£Î��šôv��.}i��tñ���*�Y�o�u� �j�o�i�n�e�d� �t�h�i�s� �r�o�o�m�.�������You joined this room.���Cache����B�a�n�n�e�d� �u�s�e�r�:� �%�1�������Banned user: %1���ChatPage���.�C�a�c�h�e� �m�i�g�r�a�t�i�o�n� �f�a�i�l�e�d�!�������Cache migration failed!���ChatPage���4�F�a�i�l�e�d� �t�o� �b�a�n� �%�1� �i�n� �%�2�:� �%�3�������Failed to ban %1 in %2: %3���ChatPage���:�F�a�i�l�e�d� �t�o� �i�n�v�i�t�e� �%�1� �t�o� �%�2�:� �%�3�������Failed to invite %1 to %2: %3���ChatPage���2�F�a�i�l�e�d� �t�o� �i�n�v�i�t�e� �u�s�e�r�:� �%�1�������Failed to invite user: %1���ChatPage���.�F�a�i�l�e�d� �t�o� �j�o�i�n� �r�o�o�m�:� �%�1�������Failed to join room: %1���ChatPage���6�F�a�i�l�e�d� �t�o� �k�i�c�k� �%�1� �t�o� �%�2�:� �%�3�������Failed to kick %1 to %2: %3���ChatPage���0�F�a�i�l�e�d� �t�o� �l�e�a�v�e� �r�o�o�m�:� �%�1�������Failed to leave room: %1���ChatPage���6�F�a�i�l�e�d� �t�o� �r�e�m�o�v�e� �i�n�v�i�t�e�:� �%�1�������Failed to remove invite: %1���ChatPage���d�F�a�i�l�e�d� �t�o� �r�e�s�t�o�r�e� �O�L�M� �a�c�c�o�u�n�t�.� �P�l�e�a�s�e� �l�o�g�i�n� �a�g�a�i�n�.�������2Failed to restore OLM account. Please login again.���ChatPage���`�F�a�i�l�e�d� �t�o� �r�e�s�t�o�r�e� �s�a�v�e� �d�a�t�a�.� �P�l�e�a�s�e� �l�o�g�i�n� �a�g�a�i�n�.�������0Failed to restore save data. Please login again.���ChatPage��� �F�a�i�l�e�d� �t�o� �s�e�t�u�p� �e�n�c�r�y�p�t�i�o�n� �k�e�y�s�.� �S�e�r�v�e�r� �r�e�s�p�o�n�s�e�:� �%�1� �%�2�.� �P�l�e�a�s�e� �t�r�y� �a�g�a�i�n� �l�a�t�e�r�.�������PFailed to setup encryption keys. Server response: %1 %2. Please try again later.���ChatPage���8�F�a�i�l�e�d� �t�o� �u�n�b�a�n� �%�1� �i�n� �%�2�:� �%�3�������Failed to unban %1 in %2: %3���ChatPage���R�F�a�i�l�e�d� �t�o� �u�p�l�o�a�d� �m�e�d�i�a�.� �P�l�e�a�s�e� �t�r�y� �a�g�a�i�n�.�������)Failed to upload media. Please try again.���ChatPage���4�I�n�c�o�m�p�a�t�i�b�l�e� �c�a�c�h�e� �v�e�r�s�i�o�n�������Incompatible cache version���ChatPage��� �I�n�v�i�t�e�d� �u�s�e�r�:� �%�1�������Invited user: %1���ChatPage����K�i�c�k�e�d� �u�s�e�r�:� �%�1�������Kicked user: %1���ChatPage��¢�M�i�g�r�a�t�i�n�g� �t�h�e� �c�a�c�h�e� �t�o� �t�h�e� �c�u�r�r�e�n�t� �v�e�r�s�i�o�n� �f�a�i�l�e�d�.� �T�h�i�s� �c�a�n� �h�a�v�e� �d�i�f�f�e�r�e�n�t� �r�e�a�s�o�n�s�.� �P�l�e�a�s�e� �o�p�e�n� �a�n� �i�s�s�u�e� �a�n�d� �t�r�y� �t�o� �u�s�e� �a�n� �o�l�d�e�r� �v�e�r�s�i�o�n� �i�n� �t�h�e� �m�e�a�n� �t�i�m�e�.� �A�l�t�e�r�n�a�t�i�v�e�l�y� �y�o�u� �c�a�n� �t�r�y� �d�e�l�e�t�i�n�g� �t�h�e� �c�a�c�h�e� �m�a�n�u�a�l�l�y�.�������ÑMigrating the cache to the current version failed. This can have different reasons. Please open an issue and try to use an older version in the mean time. Alternatively you can try deleting the cache manually.���ChatPage���:�P�l�e�a�s�e� �t�r�y� �t�o� �l�o�g�i�n� �a�g�a�i�n�:� �%�1�������Please try to login again: %1���ChatPage��� �R�o�o�m� �%�1� �c�r�e�a�t�e�d�.�������Room %1 created.���ChatPage���0�R�o�o�m� �c�r�e�a�t�i�o�n� �f�a�i�l�e�d�:� �%�1�������Room creation failed: %1���ChatPage���Î�T�h�e� �c�a�c�h�e� �o�n� �y�o�u�r� �d�i�s�k� �i�s� �n�e�w�e�r� �t�h�a�n� �t�h�i�s� �v�e�r�s�i�o�n� �o�f� �N�h�e�k�o� �s�u�p�p�o�r�t�s�.� �P�l�e�a�s�e� �u�p�d�a�t�e� �o�r� �c�l�e�a�r� �y�o�u�r� �c�a�c�h�e�.�������gThe cache on your disk is newer than this version of Nheko supports. Please update or clear your cache.���ChatPage���"�U�n�b�a�n�n�e�d� �u�s�e�r�:� �%�1�������Unbanned user: %1���ChatPage���&�Y�o�u� �j�o�i�n�e�d� �t�h�e� �r�o�o�m�������You joined the room���ChatPage���� �(�c�o�m�m�u�n�i�t�y�)������� (community)���CommunitiesListItem���� �(�t�a�g�)������� (tag)���CommunitiesListItem����A�l�l� �r�o�o�m�s�������	All rooms���CommunitiesListItem����F�a�v�o�u�r�i�t�e� �r�o�o�m�s�������Favourite rooms���CommunitiesListItem���$�L�o�w� �p�r�i�o�r�i�t�y� �r�o�o�m�s�������Low priority rooms���CommunitiesListItem���
-�A�p�p�l�y�������Apply���	EditModal����C�a�n�c�e�l�������Cancel���	EditModal����N�a�m�e�������Name���	EditModal���
-�T�o�p�i�c�������Topic���	EditModal����E�n�c�r�y�p�t�e�d�������	Encrypted���EncryptionIndicator����R�e�m�o�v�e�������Remove���InviteeItem��,�A� �n�a�m�e� �f�o�r� �t�h�i�s� �d�e�v�i�c�e�,� �w�h�i�c�h� �w�i�l�l� �b�e� �s�h�o�w�n� �t�o� �o�t�h�e�r�s�,� �w�h�e�n� �v�e�r�i�f�y�i�n�g� �y�o�u�r� �d�e�v�i�c�e�s�.� �I�f� �n�o�n�e� �i�s� �p�r�o�v�i�d�e�d�,� �a� �r�a�n�d�o�m� �s�t�r�i�n�g� �i�s� �u�s�e�d� �f�o�r� �p�r�i�v�a�c�y� �p�u�r�p�o�s�e�s�.�������–A name for this device, which will be shown to others, when verifying your devices. If none is provided, a random string is used for privacy purposes.���	LoginPage���†�A�n� �u�n�k�n�o�w�n� �e�r�r�o�r� �o�c�c�u�r�e�d�.� �M�a�k�e� �s�u�r�e� �t�h�e� �h�o�m�e�s�e�r�v�e�r� �d�o�m�a�i�n� �i�s� �v�a�l�i�d�.�������CAn unknown error occured. Make sure the homeserver domain is valid.���	LoginPage���d�A�u�t�o�d�i�s�c�o�v�e�r�y� �f�a�i�l�e�d�.� �R�e�c�e�i�v�e�d� �m�a�l�f�o�r�m�e�d� �r�e�s�p�o�n�s�e�.�������2Autodiscovery failed. Received malformed response.���	LoginPage���‚�A�u�t�o�d�i�s�c�o�v�e�r�y� �f�a�i�l�e�d�.� �U�n�k�n�o�w�n� �e�r�r�o�r� �w�h�i�l�e� �r�e�q�u�e�s�t�i�n�g� �.�w�e�l�l�-�k�n�o�w�n�.�������@Autodiscovery failed. Unknown error when requesting .well-known.���	LoginPage����D�e�v�i�c�e� �n�a�m�e�������Device name���	LoginPage����E�m�p�t�y� �p�a�s�s�w�o�r�d�������Empty password���	LoginPage���
-�L�O�G�I�N�������LOGIN���	LoginPage����M�a�t�r�i�x� �I�D�������	Matrix ID���	LoginPage����P�a�s�s�w�o�r�d�������Password���	LoginPage���Œ�R�e�c�e�i�v�e�d� �m�a�l�f�o�r�m�e�d� �r�e�s�p�o�n�s�e�.� �M�a�k�e� �s�u�r�e� �t�h�e� �h�o�m�e�s�e�r�v�e�r� �d�o�m�a�i�n� �i�s� �v�a�l�i�d�.�������FReceived malformed response. Make sure the homeserver domain is valid.���	LoginPage����S�S�O� �L�O�G�I�N�������	SSO LOGIN���	LoginPage��� �S�S�O� �l�o�g�i�n� �f�a�i�l�e�d�������SSO login failed���	LoginPage���Æ�T�h�e� �a�d�d�r�e�s�s� �t�h�a�t� �c�a�n� �b�e� �u�s�e�d� �t�o� �c�o�n�t�a�c�t� �y�o�u� �h�o�m�e�s�e�r�v�e�r�s� �c�l�i�e�n�t� �A�P�I�.�
-�E�x�a�m�p�l�e�:� �h�t�t�p�s�:�/�/�s�e�r�v�e�r�.�m�y�:�8�7�8�7�������cThe address that can be used to contact you homeservers client API.
-Example: https://server.my:8787���	LoginPage���ˆ�T�h�e� �r�e�q�u�i�r�e�d� �e�n�d�p�o�i�n�t�s� �w�e�r�e� �n�o�t� �f�o�u�n�d�.� �P�o�s�s�i�b�l�y� �n�o�t� �a� �M�a�t�r�i�x� �s�e�r�v�e�r�.�������DThe required endpoints were not found. Possibly not a Matrix server.���	LoginPage��Ê�Y�o�u�r� �l�o�g�i�n� �n�a�m�e�.� �A� �m�x�i�d� �s�h�o�u�l�d� �s�t�a�r�t� �w�i�t�h� �@� �f�o�l�l�o�w�e�d� �b�y� �t�h�e� �u�s�e�r� �i�d�.� �A�f�t�e�r� �t�h�e� �u�s�e�r� �i�d� �y�o�u� �n�e�e�d� �t�o� �i�n�c�l�u�d�e� �y�o�u�r� �s�e�r�v�e�r� �n�a�m�e� �a�f�t�e�r� �a� �:�.�
-�Y�o�u� �c�a�n� �a�l�s�o� �p�u�t� �y�o�u�r� �h�o�m�e�s�e�r�v�e�r� �a�d�d�r�e�s�s� �t�h�e�r�e�,� �i�f� �y�o�u�r� �s�e�r�v�e�r� �d�o�e�s�n�'�t� �s�u�p�p�o�r�t� �.�w�e�l�l�-�k�n�o�w�n� �l�o�o�k�u�p�.�
-�E�x�a�m�p�l�e�:� �@�u�s�e�r�:�s�e�r�v�e�r�.�m�y�
-�I�f� �N�h�e�k�o� �f�a�i�l�s� �t�o� �d�i�s�c�o�v�e�r� �y�o�u�r� �h�o�m�e�s�e�r�v�e�r�,� �i�t� �w�i�l�l� �s�h�o�w� �y�o�u� �a� �f�i�e�l�d� �t�o� �e�n�t�e�r� �t�h�e� �s�e�r�v�e�r� �m�a�n�u�a�l�l�y�.������eYour login name. A mxid should start with @ followed by the user id. After the user id you need to include your server name after a :.
-You can also put your homeserver address there, if your server doesn't support .well-known lookup.
-Example: @user:server.my
-If Nheko fails to discover your homeserver, it will show you a field to enter the server manually.���	LoginPage���&�e�.�g� �@�j�o�e�:�m�a�t�r�i�x�.�o�r�g�������e.g @joe:matrix.org���	LoginPage����O�K�������OK���
-MemberList����R�o�o�m� �m�e�m�b�e�r�s�������Room members���
-MemberList���D�%�1� �c�r�e�a�t�e�d� �a�n�d� �c�o�n�f�i�g�u�r�e�d� �r�o�o�m�:� �%�2�������"%1 created and configured room: %2���MessageDelegate���$�E�n�c�r�y�p�t�i�o�n� �e�n�a�b�l�e�d�������Encryption enabled���MessageDelegate����r�e�d�a�c�t�e�d�������redacted���MessageDelegate���"�r�e�m�o�v�e�d� �r�o�o�m� �n�a�m�e�������removed room name���MessageDelegate����r�e�m�o�v�e�d� �t�o�p�i�c�������
removed topic���MessageDelegate���0�r�o�o�m� �n�a�m�e� �c�h�a�n�g�e�d� �t�o�:� �%�1�������room name changed to: %1���MessageDelegate���(�t�o�p�i�c� �c�h�a�n�g�e�d� �t�o�:� �%�1�������topic changed to: %1���MessageDelegate���*�u�n�i�m�p�l�e�m�e�n�t�e�d� �e�v�e�n�t�:� �������unimplemented event: ���Placeholder���$�S�e�a�r�c�h� �f�o�r� �a� �r�o�o�m &�������Search for a room...���
QuickSwitcher���A� �s�e�r�v�e�r� �t�h�a�t� �a�l�l�o�w�s� �r�e�g�i�s�t�r�a�t�i�o�n�.� �S�i�n�c�e� �m�a�t�r�i�x� �i�s� �d�e�c�e�n�t�r�a�l�i�z�e�d�,� �y�o�u� �n�e�e�d� �t�o� �f�i�r�s�t� �f�i�n�d� �a� �s�e�r�v�e�r� �y�o�u� �c�a�n� �r�e�g�i�s�t�e�r� �o�n� �o�r� �h�o�s�t� �y�o�u�r� �o�w�n�.�������‡A server that allows registration. Since matrix is decentralized, you need to first find a server you can register on or host your own.���RegisterPage����H�o�m�e�s�e�r�v�e�r�������
-Homeserver���RegisterPage���&�I�n�v�a�l�i�d� �s�e�r�v�e�r� �n�a�m�e�������Invalid server name���RegisterPage��� �I�n�v�a�l�i�d� �u�s�e�r�n�a�m�e�������Invalid username���RegisterPage���@�N�o� �s�u�p�p�o�r�t�e�d� �r�e�g�i�s�t�r�a�t�i�o�n� �f�l�o�w�s�!������� No supported registration flows!���RegisterPage����P�a�s�s�w�o�r�d�������Password���RegisterPage���*�P�a�s�s�w�o�r�d� �c�o�n�f�i�r�m�a�t�i�o�n�������Password confirmation���RegisterPage���R�P�a�s�s�w�o�r�d� �i�s� �n�o�t� �l�o�n�g� �e�n�o�u�g�h� �(�m�i�n� �8� �c�h�a�r�s�)�������)Password is not long enough (min 8 chars)���RegisterPage���*�P�a�s�s�w�o�r�d�s� �d�o�n�'�t� �m�a�t�c�h�������Passwords don't match���RegisterPage����P�l�e�a�s�e� �c�h�o�o�s�e� �a� �s�e�c�u�r�e� �p�a�s�s�w�o�r�d�.� �T�h�e� �e�x�a�c�t� �r�e�q�u�i�r�e�m�e�n�t�s� �f�o�r� �p�a�s�s�w�o�r�d� �s�t�r�e�n�g�t�h� �m�a�y� �d�e�p�e�n�d� �o�n� �y�o�u�r� �s�e�r�v�e�r�.�������hPlease choose a secure password. The exact requirements for password strength may depend on your server.���RegisterPage����R�E�G�I�S�T�E�R�������REGISTER���RegisterPage����T�h�e� �u�s�e�r�n�a�m�e� �m�u�s�t� �n�o�t� �b�e� �e�m�p�t�y�,� �a�n�d� �m�u�s�t� �c�o�n�t�a�i�n� �o�n�l�y� �t�h�e� �c�h�a�r�a�c�t�e�r�s� �a�-�z�,� �0�-�9�,� �.�,� �_�,� �=�,� �-�,� �a�n�d� �/�.�������aThe username must not be empty, and must contain only the characters a-z, 0-9, ., _, =, -, and /.���RegisterPage����U�s�e�r�n�a�m�e�������Username���RegisterPage���"�n�o� �v�e�r�s�i�o�n� �s�t�o�r�e�d�������no version stored���RoomInfo����A�c�c�e�p�t�������Accept���RoomInfoListItem����D�e�c�l�i�n�e�������Decline���RoomInfoListItem����L�e�a�v�e� �r�o�o�m�������
-Leave room���RoomInfoListItem����C�r�e�a�t�e� �n�e�w� �r�o�o�m�������Create new room���SideBarActions����J�o�i�n� �a� �r�o�o�m�������Join a room���SideBarActions����R�o�o�m� �d�i�r�e�c�t�o�r�y�������Room directory���SideBarActions��� �S�t�a�r�t� �a� �n�e�w� �c�h�a�t�������Start a new chat���SideBarActions����U�s�e�r� �s�e�t�t�i�n�g�s�������
User settings���SideBarActions����F�a�i�l�e�d�������Failed���StatusIndicator����R�e�a�d�������Read���StatusIndicator����R�e�c�e�i�v�e�d�������Received���StatusIndicator����S�e�n�t�������Sent���StatusIndicator����A�l�l� �F�i�l�e�s� �(�*�)�������
All Files (*)���TextInputWidget���^�C�o�n�n�e�c�t�i�o�n� �l�o�s�t�.� �N�h�e�k�o� �i�s� �t�r�y�i�n�g� �t�o� �r�e�-�c�o�n�n�e�c�t &�������1Connection lost. Nheko is trying to re-connect...���TextInputWidget���
-�E�m�o�j�i�������Emoji���TextInputWidget����S�e�l�e�c�t� �a� �f�i�l�e�������
Select a file���TextInputWidget����S�e�n�d� �a� �f�i�l�e�������Send a file���TextInputWidget����S�e�n�d� �a� �m�e�s�s�a�g�e�������Send a message���TextInputWidget��� �W�r�i�t�e� �a� �m�e�s�s�a�g�e &�������Write a message...���TextInputWidget����R�e�a�s�o�n�:� �%�1������� Reason: %1���
TimelineModel����%�1�%�2� �i�s� �t�y�p�i�n�g�.���*�%�1� �a�n�d� �%�2� �a�r�e� �t�y�p�i�n�g�.�������%1 and %2 are typing.���
TimelineModel���0�%�1� �c�h�a�n�g�e�d� �t�h�e�i�r� �a�v�a�t�a�r�.�������%1 changed their avatar.���
TimelineModel���R�%�1� �c�h�a�n�g�e�d� �t�h�e�i�r� �d�i�s�p�l�a�y� �n�a�m�e� �a�n�d� �a�v�a�t�a�r�.�������)%1 changed their display name and avatar.���
TimelineModel���<�%�1� �c�h�a�n�g�e�d� �t�h�e�i�r� �d�i�s�p�l�a�y� �n�a�m�e�.�������%1 changed their display name.���
TimelineModel���L�%�1� �h�a�s� �c�h�a�n�g�e�d� �t�h�e� �r�o�o�m�'�s� �p�e�r�m�i�s�s�i�o�n�s�.�������&%1 has changed the room's permissions.���
TimelineModel���N�%�1� �h�a�s� �c�l�o�s�e�d� �t�h�e� �r�o�o�m� �t�o� �g�u�e�s�t� �a�c�c�e�s�s�.�������'%1 has closed the room to guest access.���
TimelineModel����%�1� �j�o�i�n�e�d�.�������
-%1 joined.���
TimelineModel����%�1� �k�n�o�c�k�e�d�.�������%1 knocked.���
TimelineModel���D�%�1� �l�e�f�t� �a�f�t�e�r� �h�a�v�i�n�g� �a�l�r�e�a�d�y� �l�e�f�t�!�������"%1 left after having already left!���
TimelineModel���"�%�1� �l�e�f�t� �t�h�e� �r�o�o�m�.�������%1 left the room.���
TimelineModel���ª�%�1� �m�a�d�e� �t�h�e� �r�o�o�m� �h�i�s�t�o�r�y� �w�o�r�l�d� �r�e�a�d�a�b�l�e�.� �E�v�e�n�t�s� �m�a�y� �b�e� �n�o�w� �r�e�a�d� �b�y� �n�o�n�-�j�o�i�n�e�d� �p�e�o�p�l�e�.�������U%1 made the room history world readable. Events may be now read by non-joined people.���
TimelineModel���@�%�1� �m�a�d�e� �t�h�e� �r�o�o�m� �o�p�e�n� �t�o� �g�u�e�s�t�s�.������� %1 made the room open to guests.���
TimelineModel���`�%�1� �m�a�d�e� �t�h�i�s� �r�o�o�m� �r�e�q�u�i�r�e� �a�n� �i�n�v�i�t�a�t�i�o�n� �t�o� �j�o�i�n�.�������1%1 made this room require and invitation to join.���
TimelineModel���B�%�1� �o�p�e�n�e�d� �t�h�e� �r�o�o�m� �t�o� �t�h�e� �p�u�b�l�i�c�.�������!%1 opened the room to the public.���
TimelineModel���0�%�1� �r�e�d�a�c�t�e�d� �t�h�e�i�r� �k�n�o�c�k�.�������%1 redacted their knock.���
TimelineModel���2�%�1� �r�e�j�e�c�t�e�d� �t�h�e�i�r� �i�n�v�i�t�e�.�������%1 rejected their invite.���
TimelineModel���|�%�1� �s�e�t� �t�h�e� �r�o�o�m� �h�i�s�t�o�r�y� �v�i�s�i�b�l�e� �t�o� �m�e�m�b�e�r�s� �f�r�o�m� �t�h�i�s� �p�o�i�n�t� �o�n�.�������>%1 set the room history visible to members from this point on.���
TimelineModel���Œ�%�1� �s�e�t� �t�h�e� �r�o�o�m� �h�i�s�t�o�r�y� �v�i�s�i�b�l�e� �t�o� �m�e�m�b�e�r�s� �s�i�n�c�e� �t�h�e�y� �j�o�i�n�e�d� �t�h�e� �r�o�o�m�.�������F%1 set the room history visible to members since they joined the room.���
TimelineModel���†�%�1� �s�e�t� �t�h�e� �r�o�o�m� �h�i�s�t�o�r�y� �v�i�s�i�b�l�e� �t�o� �m�e�m�b�e�r�s� �s�i�n�c�e� �t�h�e�y� �w�e�r�e� �i�n�v�i�t�e�d�.�������C%1 set the room history visible to members since they were invited.���
TimelineModel����%�1� �w�a�s� �b�a�n�n�e�d�.�������%1 was banned.���
TimelineModel����%�1� �w�a�s� �i�n�v�i�t�e�d�.�������%1 was invited.���
TimelineModel���6�-�-� �D�e�c�r�y�p�t�i�o�n� �E�r�r�o�r� �(�%�1�)� �-�-�������-- Decryption Error (%1) --���
TimelineModel���l�-�-� �D�e�c�r�y�p�t�i�o�n� �E�r�r�o�r� �(�f�a�i�l�e�d� �t�o� �c�o�m�m�u�n�i�c�a�t�e� �w�i�t�h� �D�B�)� �-�-�������6-- Decryption Error (failed to communicate with DB) --���
TimelineModel���~�-�-� �D�e�c�r�y�p�t�i�o�n� �E�r�r�o�r� �(�f�a�i�l�e�d� �t�o� �r�e�t�r�i�e�v�e� �m�e�g�o�l�m� �k�e�y�s� �f�r�o�m� �d�b�)� �-�-�������?-- Decryption Error (failed to retrieve megolm keys from db) --���
TimelineModel���h�-�-� �E�n�c�r�y�p�t�e�d� �E�v�e�n�t� �(�N�o� �k�e�y�s� �f�o�u�n�d� �f�o�r� �d�e�c�r�y�p�t�i�o�n�)� �-�-�������4-- Encrypted Event (No keys found for decryption) --���
TimelineModel���T�-�-� �E�n�c�r�y�p�t�e�d� �E�v�e�n�t� �(�U�n�k�n�o�w�n� �e�v�e�n�t� �t�y�p�e�)� �-�-�������*-- Encrypted Event (Unknown event type) --���
TimelineModel����K�i�c�k�e�d� �%�1�.�������
-Kicked %1.���
TimelineModel���8�M�e�s�s�a�g�e� �r�e�d�a�c�t�i�o�n� �f�a�i�l�e�d�:� �%�1�������Message redaction failed: %1���
TimelineModel���6�R�e�j�e�c�t�e�d� �t�h�e� �k�n�o�c�k� �f�r�o�m� �%�1�.�������Rejected the knock from %1.���
TimelineModel���2�R�e�v�o�k�e�d� �t�h�e� �i�n�v�i�t�e� �t�o� �%�1�.�������Revoked the invite to %1.���
TimelineModel����S�a�v�e� �a�u�d�i�o�������
-Save audio���
TimelineModel����S�a�v�e� �f�i�l�e�������	Save file���
TimelineModel����S�a�v�e� �i�m�a�g�e�������
-Save image���
TimelineModel����S�a�v�e� �v�i�d�e�o�������
-Save video���
TimelineModel����U�n�b�a�n�n�e�d� �%�1�.�������Unbanned %1.���
TimelineModel���*�Y�o�u� �j�o�i�n�e�d� �t�h�i�s� �r�o�o�m�.�������You joined this room.���
TimelineModel����O�p�t�i�o�n�s�������Options���TimelineRow���
-�R�e�p�l�y�������Reply���TimelineRow���
-�C�l�o�s�e�������Close���TimelineView����M�a�r�k� �a�s� �r�e�a�d�������Mark as read���TimelineView����N�o� �r�o�o�m� �o�p�e�n�������No room open���TimelineView����R�e�a�d� �r�e�c�e�i�p�t�s�������
Read receipts���TimelineView����R�e�d�a�c�t� �m�e�s�s�a�g�e�������Redact message���TimelineView���
-�R�e�p�l�y�������Reply���TimelineView����S�a�v�e� �a�s�������Save as���TimelineView���4�V�i�e�w� �d�e�c�r�y�p�t�e�d� �r�a�w� �m�e�s�s�a�g�e�������View decrypted raw message���TimelineView��� �V�i�e�w� �r�a�w� �m�e�s�s�a�g�e�������View raw message���TimelineView����I�n�v�i�t�e� �u�s�e�r�s�������Invite users���
-TopRoomBar����L�e�a�v�e� �r�o�o�m�������
-Leave room���
-TopRoomBar����M�e�m�b�e�r�s�������Members���
-TopRoomBar����M�e�n�t�i�o�n�s�������Mentions���
-TopRoomBar����R�o�o�m� �o�p�t�i�o�n�s�������Room options���
-TopRoomBar����S�e�t�t�i�n�g�s�������Settings���
-TopRoomBar����Q�u�i�t�������Quit���TrayIcon����S�h�o�w�������Show���TrayIcon����L�o�g�o�u�t�������Logout���UserInfoWidget��� �C�i�r�c�u�l�a�r� �A�v�a�t�a�r�s�������Circular Avatars���UserSettingsPage���6�D�e�c�r�y�p�t� �m�e�s�s�a�g�e�s� �i�n� �s�i�d�e�b�a�r�������Decrypt messages in sidebar���UserSettingsPage���*�D�e�s�k�t�o�p� �n�o�t�i�f�i�c�a�t�i�o�n�s�������Desktop notifications���UserSettingsPage���$�D�e�v�i�c�e� �F�i�n�g�e�r�p�r�i�n�t�������Device Fingerprint���UserSettingsPage����D�e�v�i�c�e� �I�D�������	Device ID���UserSettingsPage����E�N�C�R�Y�P�T�I�O�N�������
-ENCRYPTION���UserSettingsPage����E�X�P�O�R�T�������EXPORT���UserSettingsPage���"�E�m�o�j�i� �F�o�n�t� �F�a�m�i�l�y�������Emoji Font Family���UserSettingsPage���\�E�n�t�e�r� �p�a�s�s�p�h�r�a�s�e� �t�o� �e�n�c�r�y�p�t� �y�o�u�r� �s�e�s�s�i�o�n� �k�e�y�s�:�������.Enter passphrase to encrypt your session keys:���UserSettingsPage���R�E�n�t�e�r� �t�h�e� �p�a�s�s�p�h�r�a�s�e� �t�o� �d�e�c�r�y�p�t� �t�h�e� �f�i�l�e�:�������)Enter the passphrase to decrypt the file:���UserSettingsPage���
-�E�r�r�o�r�������Error���UserSettingsPage����F�i�l�e� �P�a�s�s�w�o�r�d�������
File Password���UserSettingsPage���L�F�i�l�e� �t�o� �s�a�v�e� �t�h�e� �e�x�p�o�r�t�e�d� �s�e�s�s�i�o�n� �k�e�y�s�������&File to save the exported session keys���UserSettingsPage����F�o�n�t� �F�a�m�i�l�y�������Font Family���UserSettingsPage����F�o�n�t� �s�i�z�e�������	Font size���UserSettingsPage����G�E�N�E�R�A�L�������GENERAL���UserSettingsPage����G�r�o�u�p�'�s� �s�i�d�e�b�a�r�������Group's sidebar���UserSettingsPage����I�M�P�O�R�T�������IMPORT���UserSettingsPage����I�N�T�E�R�F�A�C�E�������	INTERFACE���UserSettingsPage��� �M�i�n�i�m�i�z�e� �t�o� �t�r�a�y�������Minimize to tray���UserSettingsPage���$�O�p�e�n� �S�e�s�s�i�o�n�s� �F�i�l�e�������Open Sessions File���UserSettingsPage����R�e�a�d� �r�e�c�e�i�p�t�s�������
Read receipts���UserSettingsPage����S�c�a�l�e� �f�a�c�t�o�r�������Scale factor���UserSettingsPage���2�S�e�n�d� �m�e�s�s�a�g�e�s� �a�s� �M�a�r�k�d�o�w�n�������Send messages as Markdown���UserSettingsPage����S�e�s�s�i�o�n� �K�e�y�s�������Session Keys���UserSettingsPage���0�S�h�o�w� �b�u�t�t�o�n�s� �i�n� �t�i�m�e�l�i�n�e�������Show buttons in timeline���UserSettingsPage���*�S�o�r�t� �r�o�o�m�s� �b�y� �u�n�r�e�a�d�s�������Sort rooms by unreads���UserSettingsPage����S�t�a�r�t� �i�n� �t�r�a�y�������
Start in tray���UserSettingsPage���8�T�h�e� �p�a�s�s�w�o�r�d� �c�a�n�n�o�t� �b�e� �e�m�p�t�y�������The password cannot be empty���UserSettingsPage���
-�T�h�e�m�e�������Theme���UserSettingsPage���(�T�y�p�i�n�g� �n�o�t�i�f�i�c�a�t�i�o�n�s�������Typing notifications���UserSettingsPage��� �E�n�j�o�y� �y�o�u�r� �s�t�a�y�!�������Enjoy your stay!���WelcomePage���
-�L�O�G�I�N�������LOGIN���WelcomePage����R�E�G�I�S�T�E�R�������REGISTER���WelcomePage���z�W�e�l�c�o�m�e� �t�o� �n�h�e�k�o�!� �T�h�e� �d�e�s�k�t�o�p� �c�l�i�e�n�t� �f�o�r� �t�h�e� �M�a�t�r�i�x� �p�r�o�t�o�c�o�l�.�������=Welcome to nheko! The desktop client for the Matrix protocol.���WelcomePage����Y�e�s�t�e�r�d�a�y�������	Yesterday���descriptiveTime���
-�A�l�i�a�s�������Alias���dialogs::CreateRoom����C�a�n�c�e�l�������Cancel���dialogs::CreateRoom����C�r�e�a�t�e� �r�o�o�m�������Create room���dialogs::CreateRoom����D�i�r�e�c�t� �C�h�a�t�������Direct Chat���dialogs::CreateRoom����N�a�m�e�������Name���dialogs::CreateRoom����R�o�o�m� �P�r�e�s�e�t�������Room Preset���dialogs::CreateRoom����R�o�o�m� �V�i�s�i�b�i�l�i�t�y�������Room Visibility���dialogs::CreateRoom���
-�T�o�p�i�c�������Topic���dialogs::CreateRoom����C�a�n�c�e�l�������Cancel���dialogs::FallbackAuth����C�o�n�f�i�r�m�������Confirm���dialogs::FallbackAuth���0�O�p�e�n� �F�a�l�l�b�a�c�k� �i�n� �B�r�o�w�s�e�r�������Open Fallback in Browser���dialogs::FallbackAuth���Œ�O�p�e�n� �t�h�e� �f�a�l�l�b�a�c�k�,� �f�o�l�l�o�w� �t�h�e� �s�t�e�p�s� �a�n�d� �c�o�n�f�i�r�m� �a�f�t�e�r� �c�o�m�p�l�e�t�i�n�g� �t�h�e�m�.�������FOpen the fallback, follow the steps and confirm after completing them.���dialogs::FallbackAuth����C�a�n�c�e�l�������Cancel���dialogs::InviteUsers���"�U�s�e�r� �I�D� �t�o� �i�n�v�i�t�e�������User ID to invite���dialogs::InviteUsers����C�a�n�c�e�l�������Cancel���dialogs::JoinRoom����J�o�i�n�������Join���dialogs::JoinRoom��� �R�o�o�m� �I�D� �o�r� �a�l�i�a�s�������Room ID or alias���dialogs::JoinRoom���>�A�r�e� �y�o�u� �s�u�r�e� �y�o�u� �w�a�n�t� �t�o� �l�e�a�v�e�?�������Are you sure you want to leave?���dialogs::LeaveRoom����C�a�n�c�e�l�������Cancel���dialogs::LeaveRoom����C�a�n�c�e�l�������Cancel���dialogs::Logout���*�L�o�g�o�u�t�.� �A�r�e� �y�o�u� �s�u�r�e�?�������Logout. Are you sure?���dialogs::Logout����C�a�n�c�e�l�������Cancel���dialogs::PreviewUploadOverlay���<�M�e�d�i�a� �t�y�p�e�:� �%�1�
-�M�e�d�i�a� �s�i�z�e�:� �%�2�
-�������Media type: %1
-Media size: %2
-���dialogs::PreviewUploadOverlay����U�p�l�o�a�d�������Upload���dialogs::PreviewUploadOverlay����C�a�n�c�e�l�������Cancel���dialogs::ReCaptcha����C�o�n�f�i�r�m�������Confirm���dialogs::ReCaptcha���`�S�o�l�v�e� �t�h�e� �r�e�C�A�P�T�C�H�A� �a�n�d� �p�r�e�s�s� �t�h�e� �c�o�n�f�i�r�m� �b�u�t�t�o�n�������0Solve the reCAPTCHA and press the confirm button���dialogs::ReCaptcha���
-�C�l�o�s�e�������Close���dialogs::ReadReceipts����R�e�a�d� �r�e�c�e�i�p�t�s�������
Read receipts���dialogs::ReadReceipts����T�o�d�a�y� �%�1�������Today %1���dialogs::ReceiptItem����Y�e�s�t�e�r�d�a�y� �%�1�������Yesterday %1���dialogs::ReceiptItem����%�n� �m�e�m�b�e�r����%�n� �m�e�m�b�e�r�s�������%n member(s)���dialogs::RoomSettings����A�l�l� �F�i�l�e�s� �(�*�)�������
All Files (*)���dialogs::RoomSettings����A�l�l� �m�e�s�s�a�g�e�s�������All messages���dialogs::RoomSettings���T�A�n�y�o�n�e� �w�h�o� �k�n�o�w�s� �t�h�e� �r�o�o�m� �l�i�n�k� �(�n�o� �g�u�e�s�t�s�)�������Anyone���dialogs::RoomSettings���"�A�n�y�o�n�e� �a�n�d� �g�u�e�s�t�s�������Anyone and guests���dialogs::RoomSettings����E�n�c�r�y�p�t�i�o�n�������
-Encryption���dialogs::RoomSettings���E�n�c�r�y�p�t�i�o�n� �i�s� �c�u�r�r�e�n�t�l�y� �e�x�p�e�r�i�m�e�n�t�a�l� �a�n�d� �t�h�i�n�g�s� �m�i�g�h�t� �b�r�e�a�k� �u�n�e�x�p�e�c�t�e�d�l�y�.� �<�b�r�>�P�l�e�a�s�e� �t�a�k�e� �n�o�t�e� �t�h�a�t� �i�t� �c�a�n�'�t� �b�e� �d�i�s�a�b�l�e�d� �a�f�t�e�r�w�a�r�d�s�.�������„Encryption is currently experimental and things might break unexpectedly. <br>Please take note that it can't be disabled afterwards.���dialogs::RoomSettings���*�E�n�d�-�t�o�-�E�n�d� �E�n�c�r�y�p�t�i�o�n�������End-to-End Encryption���dialogs::RoomSettings���8�E�r�r�o�r� �w�h�i�l�e� �r�e�a�d�i�n�g� �f�i�l�e�:� �%�1�������Error while reading file: %1���dialogs::RoomSettings���>�F�a�i�l�e�d� �t�o� �e�n�a�b�l�e� �e�n�c�r�y�p�t�i�o�n�:� �%�1�������Failed to enable encryption: %1���dialogs::RoomSettings���4�F�a�i�l�e�d� �t�o� �u�p�l�o�a�d� �i�m�a�g�e�:� �%�s�������Failed to upload image: %s���dialogs::RoomSettings����I�n�f�o�������Info���dialogs::RoomSettings����I�n�t�e�r�n�a�l� �I�D�������Internal ID���dialogs::RoomSettings����I�n�v�i�t�e�d� �u�s�e�r�s�������
Invited users���dialogs::RoomSettings����M�e�n�t�i�o�n�s� �o�n�l�y�������
Mentions only���dialogs::RoomSettings���
-�M�u�t�e�d�������Muted���dialogs::RoomSettings����N�o�t�i�f�i�c�a�t�i�o�n�s�������
Notifications���dialogs::RoomSettings���.�R�e�s�p�o�n�d� �t�o� �k�e�y� �r�e�q�u�e�s�t�s�������Respond to key requests���dialogs::RoomSettings����R�o�o�m� �V�e�r�s�i�o�n�������Room Version���dialogs::RoomSettings����R�o�o�m� �a�c�c�e�s�s�������Room access���dialogs::RoomSettings��� �S�e�l�e�c�t� �a�n� �a�v�a�t�a�r�������Select an avatar���dialogs::RoomSettings����S�e�t�t�i�n�g�s�������Settings���dialogs::RoomSettings���B�T�h�e� �s�e�l�e�c�t�e�d� �f�i�l�e� �i�s� �n�o�t� �a�n� �i�m�a�g�e�������!The selected file is not an image���dialogs::RoomSettings��¢�W�h�e�t�h�e�r� �o�r� �n�o�t� �t�h�e� �c�l�i�e�n�t� �s�h�o�u�l�d� �r�e�s�p�o�n�d� �a�u�t�o�m�a�t�i�c�a�l�l�y� �w�i�t�h� �t�h�e� �s�e�s�s�i�o�n� �k�e�y�s�
-� �u�p�o�n� �r�e�q�u�e�s�t�.� �U�s�e� �w�i�t�h� �c�a�u�t�i�o�n�,� �t�h�i�s� �i�s� �a� �t�e�m�p�o�r�a�r�y� �m�e�a�s�u�r�e� �t�o� �t�e�s�t� �t�h�e�
-� �E�2�E� �i�m�p�l�e�m�e�n�t�a�t�i�o�n� �u�n�t�i�l� �d�e�v�i�c�e� �v�e�r�i�f�i�c�a�t�i�o�n� �i�s� �c�o�m�p�l�e�t�e�d�.�������ÑWhether or not the client should respond automatically with the session keys
- upon request. Use with caution, this is a temporary measure to test the
- E2E implementation until device verification is completed.���dialogs::RoomSettings���4�B�a�n� �t�h�e� �u�s�e�r� �f�r�o�m� �t�h�e� �r�o�o�m�������Ban the user from the room���dialogs::UserProfile����D�e�v�i�c�e�s�������Devices���dialogs::UserProfile���<�I�g�n�o�r�e� �m�e�s�s�a�g�e�s� �f�r�o�m� �t�h�i�s� �u�s�e�r�������Ignore messages from this user���dialogs::UserProfile���6�K�i�c�k� �t�h�e� �u�s�e�r� �f�r�o�m� �t�h�e� �r�o�o�m�������Kick the user from the room���dialogs::UserProfile���(�S�t�a�r�t� �a� �c�o�n�v�e�r�s�a�t�i�o�n�������Start a conversation���dialogs::UserProfile����A�c�t�i�v�i�t�y�������Activity���emoji::Panel��� �A�n�i�m�a�l�s� �&� �N�a�t�u�r�e�������Animals & Nature���emoji::Panel���
-�F�l�a�g�s�������Flags���emoji::Panel����F�o�o�d� �&� �D�r�i�n�k�������Food & Drink���emoji::Panel����O�b�j�e�c�t�s�������Objects���emoji::Panel��� �S�m�i�l�e�y�s� �&� �P�e�o�p�l�e�������Smileys & People���emoji::Panel����S�y�m�b�o�l�s�������Symbols���emoji::Panel����T�r�a�v�e�l� �&� �P�l�a�c�e�s�������Travel & Places���emoji::Panel����%�1� �s�e�n�t� �a� �f�i�l�e�������%1 sent a file���message-description sent:���,�%�1� �s�e�n�t� �a� �n�o�t�i�f�i�c�a�t�i�o�n�������%1 sent a notification���message-description sent:���"�%�1� �s�e�n�t� �a� �s�t�i�c�k�e�r�������%1 sent a sticker���message-description sent:����%�1� �s�e�n�t� �a� �v�i�d�e�o�������%1 sent a video���message-description sent:���*�%�1� �s�e�n�t� �a�n� �a�u�d�i�o� �c�l�i�p�������%1 sent an audio clip���message-description sent:���8�%�1� �s�e�n�t� �a�n� �e�n�c�r�y�p�t�e�d� �m�e�s�s�a�g�e�������%1 sent an encrypted message���message-description sent:��� �%�1� �s�e�n�t� �a�n� �i�m�a�g�e�������%1 sent an image���message-description sent:����%�1�:� �%�2�������%1: %2���message-description sent:����Y�o�u� �s�e�n�t� �a� �f�i�l�e�������You sent a file���message-description sent:���.�Y�o�u� �s�e�n�t� �a� �n�o�t�i�f�i�c�a�t�i�o�n�������You sent a notification���message-description sent:���$�Y�o�u� �s�e�n�t� �a� �s�t�i�c�k�e�r�������You sent a sticker���message-description sent:��� �Y�o�u� �s�e�n�t� �a� �v�i�d�e�o�������You sent a video���message-description sent:���,�Y�o�u� �s�e�n�t� �a�n� �a�u�d�i�o� �c�l�i�p�������You sent an audio clip���message-description sent:���:�Y�o�u� �s�e�n�t� �a�n� �e�n�c�r�y�p�t�e�d� �m�e�s�s�a�g�e�������You sent an encrypted message���message-description sent:���"�Y�o�u� �s�e�n�t� �a�n� �i�m�a�g�e�������You sent an image���message-description sent:����Y�o�u�:� �%�1�������You: %1���message-description sent:����A�l�l� �R�o�o�m�s�������	All Rooms���popups::UserMentions����T�h�i�s� �R�o�o�m�������	This Room���popups::UserMentions���(�U�n�k�n�o�w�n� �M�e�s�s�a�g�e� �T�y�p�e�������Unknown Message Type���utilsˆ���
\ No newline at end of file
diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index 9fc98419c46af493408195ccfc0a8c4850aaaa90..07831c59cfc4af94dd7ecfadfa56908a57b13fe8 100644
--- a/resources/qml/TimelineRow.qml
+++ b/resources/qml/TimelineRow.qml
@@ -14,6 +14,7 @@ MouseArea {
 	height: row.height
 	propagateComposedEvents: true
 	preventStealing: true
+	hoverEnabled: true
 
 	acceptedButtons: Qt.LeftButton | Qt.RightButton
 	onClicked: {
@@ -24,7 +25,10 @@ MouseArea {
 		if (mouse.source === Qt.MouseEventNotSynthesized)
 		messageContextMenu.show(model.id, model.type, model.isEncrypted, row)
 	}
-
+	Rectangle {
+		color: (timelineSettings.message_hover_highlight && parent.containsMouse) ? colors.base : "transparent"
+		anchors.fill: row
+	}
 	RowLayout {
 		id: row
 
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index ea5e6d6066b6690ee62a895935e4f6d029bd4f4b..721fd2b84992d633ec501aa9263d913cf1230500 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -34,6 +34,7 @@ Page {
 		id: timelineSettings
 		category: "user/timeline"
 		property bool buttons: true
+		property bool message_hover_highlight: false
 	}
 
     EmojiPicker {
@@ -113,6 +114,7 @@ Page {
 		}
 
 		BusyIndicator {
+			visible: running
 			anchors.centerIn: parent
             running: timelineManager.isInitialSync
 			height: 200
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index bfefd7bb377344634dd205f83f1d2684b654a9af..6670532ced804ce86be67b65353fce738bc12b63 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -1017,7 +1017,7 @@ ChatPage::trySync()
                   // TODO: fine grained error handling
                   try {
                           cache::saveState(res);
-                          olm::handle_to_device_messages(res.to_device);
+                          olm::handle_to_device_messages(res.to_device.events);
 
                           auto updates = cache::roomUpdates(res);
 
@@ -1240,7 +1240,7 @@ ChatPage::initialSyncHandler(const mtx::responses::Sync &res, mtx::http::Request
         try {
                 cache::saveState(res);
 
-                olm::handle_to_device_messages(res.to_device);
+                olm::handle_to_device_messages(res.to_device.events);
 
                 emit initializeViews(std::move(res.rooms));
                 emit initializeRoomList(cache::roomInfo());
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 8ea395660376e3cc2f71a9d42653e27174354f88..2c4f6186f8b1bb22d3acc9fdaab483901be6e7e9 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -23,52 +23,55 @@ client()
 }
 
 void
-handle_to_device_messages(const std::vector<nlohmann::json> &msgs)
+handle_to_device_messages(const std::vector<mtx::events::collections::DeviceEvents> &msgs)
 {
         if (msgs.empty())
                 return;
 
         nhlog::crypto()->info("received {} to_device messages", msgs.size());
+        nlohmann::json j_msg;
 
         for (const auto &msg : msgs) {
-                if (msg.count("type") == 0) {
+                j_msg = std::visit([](auto &e) { return json(e); }, std::move(msg));
+                if (j_msg.count("type") == 0) {
                         nhlog::crypto()->warn("received message with no type field: {}",
-                                              msg.dump(2));
+                                              j_msg.dump(2));
                         continue;
                 }
 
-                std::string msg_type = msg.at("type");
+                std::string msg_type = j_msg.at("type");
 
                 if (msg_type == to_string(mtx::events::EventType::RoomEncrypted)) {
                         try {
-                                OlmMessage olm_msg = msg;
+                                OlmMessage olm_msg = j_msg;
                                 handle_olm_message(std::move(olm_msg));
                         } catch (const nlohmann::json::exception &e) {
                                 nhlog::crypto()->warn(
-                                  "parsing error for olm message: {} {}", e.what(), msg.dump(2));
+                                  "parsing error for olm message: {} {}", e.what(), j_msg.dump(2));
                         } catch (const std::invalid_argument &e) {
-                                nhlog::crypto()->warn(
-                                  "validation error for olm message: {} {}", e.what(), msg.dump(2));
+                                nhlog::crypto()->warn("validation error for olm message: {} {}",
+                                                      e.what(),
+                                                      j_msg.dump(2));
                         }
 
                 } else if (msg_type == to_string(mtx::events::EventType::RoomKeyRequest)) {
-                        nhlog::crypto()->warn("handling key request event: {}", msg.dump(2));
+                        nhlog::crypto()->warn("handling key request event: {}", j_msg.dump(2));
                         try {
-                                mtx::events::msg::KeyRequest req = msg;
-                                if (req.action == mtx::events::msg::RequestAction::Request)
-                                        handle_key_request_message(std::move(req));
+                                mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> req = j_msg;
+                                if (req.content.action == mtx::events::msg::RequestAction::Request)
+                                        handle_key_request_message(req);
                                 else
                                         nhlog::crypto()->warn(
                                           "ignore key request (unhandled action): {}",
-                                          req.request_id);
+                                          req.content.request_id);
                         } catch (const nlohmann::json::exception &e) {
                                 nhlog::crypto()->warn(
                                   "parsing error for key_request message: {} {}",
                                   e.what(),
-                                  msg.dump(2));
+                                  j_msg.dump(2));
                         }
                 } else {
-                        nhlog::crypto()->warn("unhandled event: {}", msg.dump(2));
+                        nhlog::crypto()->warn("unhandled event: {}", j_msg.dump(2));
                 }
         }
 }
@@ -341,51 +344,53 @@ send_key_request_for(const std::string &room_id,
 }
 
 void
-handle_key_request_message(const mtx::events::msg::KeyRequest &req)
+handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> &req)
 {
-        if (req.algorithm != MEGOLM_ALGO) {
+        if (req.content.algorithm != MEGOLM_ALGO) {
                 nhlog::crypto()->debug("ignoring key request {} with invalid algorithm: {}",
-                                       req.request_id,
-                                       req.algorithm);
+                                       req.content.request_id,
+                                       req.content.algorithm);
                 return;
         }
 
         // Check if we were the sender of the session being requested.
-        if (req.sender_key != olm::client()->identity_keys().curve25519) {
+        if (req.content.sender_key != olm::client()->identity_keys().curve25519) {
                 nhlog::crypto()->debug("ignoring key request {} because we were not the sender: "
                                        "\nrequested({}) ours({})",
-                                       req.request_id,
-                                       req.sender_key,
+                                       req.content.request_id,
+                                       req.content.sender_key,
                                        olm::client()->identity_keys().curve25519);
                 return;
         }
 
         // Check if we have the keys for the requested session.
-        if (!cache::outboundMegolmSessionExists(req.room_id)) {
-                nhlog::crypto()->warn("requested session not found in room: {}", req.room_id);
+        if (!cache::outboundMegolmSessionExists(req.content.room_id)) {
+                nhlog::crypto()->warn("requested session not found in room: {}",
+                                      req.content.room_id);
                 return;
         }
 
         // Check that the requested session_id and the one we have saved match.
-        const auto session = cache::getOutboundMegolmSession(req.room_id);
-        if (req.session_id != session.data.session_id) {
+        const auto session = cache::getOutboundMegolmSession(req.content.room_id);
+        if (req.content.session_id != session.data.session_id) {
                 nhlog::crypto()->warn("session id of retrieved session doesn't match the request: "
                                       "requested({}), ours({})",
-                                      req.session_id,
+                                      req.content.session_id,
                                       session.data.session_id);
                 return;
         }
 
-        if (!cache::isRoomMember(req.sender, req.room_id)) {
+        if (!cache::isRoomMember(req.sender, req.content.room_id)) {
                 nhlog::crypto()->warn(
                   "user {} that requested the session key is not member of the room {}",
                   req.sender,
-                  req.room_id);
+                  req.content.room_id);
                 return;
         }
 
-        if (!utils::respondsToKeyRequests(req.room_id)) {
-                nhlog::crypto()->debug("ignoring all key requests for room {}", req.room_id);
+        if (!utils::respondsToKeyRequests(req.content.room_id)) {
+                nhlog::crypto()->debug("ignoring all key requests for room {}",
+                                       req.content.room_id);
                 return;
         }
 
@@ -393,11 +398,11 @@ handle_key_request_message(const mtx::events::msg::KeyRequest &req)
         // Prepare the m.room_key event.
         //
         auto payload = json{{"algorithm", "m.megolm.v1.aes-sha2"},
-                            {"room_id", req.room_id},
-                            {"session_id", req.session_id},
+                            {"room_id", req.content.room_id},
+                            {"session_id", req.content.session_id},
                             {"session_key", session.data.session_key}};
 
-        send_megolm_key_to_device(req.sender, req.requesting_device_id, payload);
+        send_megolm_key_to_device(req.sender, req.content.requesting_device_id, payload);
 }
 
 void
diff --git a/src/Olm.h b/src/Olm.h
index 28521413e43790ea27d12de97793083d7453a03c..09038ad1ef9c50177c53eda4c23136170e2c8823 100644
--- a/src/Olm.h
+++ b/src/Olm.h
@@ -40,7 +40,7 @@ mtx::crypto::OlmClient *
 client();
 
 void
-handle_to_device_messages(const std::vector<nlohmann::json> &msgs);
+handle_to_device_messages(const std::vector<mtx::events::collections::DeviceEvents> &msgs);
 
 nlohmann::json
 try_olm_decryption(const std::string &sender_key,
@@ -77,7 +77,7 @@ send_key_request_for(const std::string &room_id,
                      const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &);
 
 void
-handle_key_request_message(const mtx::events::msg::KeyRequest &);
+handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> &);
 
 void
 send_megolm_key_to_device(const std::string &user_id,
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index e19aa876b1c5e249b4675554c50f642a99961d55..6af08e12b90a326b0d9c2469c72b69c25525dccf 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -51,11 +51,13 @@ void
 UserSettings::load()
 {
         QSettings settings;
-        isTrayEnabled_                = settings.value("user/window/tray", false).toBool();
-        hasDesktopNotifications_      = settings.value("user/desktop_notifications", true).toBool();
-        isStartInTrayEnabled_         = settings.value("user/window/start_in_tray", false).toBool();
-        isGroupViewEnabled_           = settings.value("user/group_view", true).toBool();
-        isButtonsInTimelineEnabled_   = settings.value("user/timeline/buttons", true).toBool();
+        isTrayEnabled_              = settings.value("user/window/tray", false).toBool();
+        hasDesktopNotifications_    = settings.value("user/desktop_notifications", true).toBool();
+        isStartInTrayEnabled_       = settings.value("user/window/start_in_tray", false).toBool();
+        isGroupViewEnabled_         = settings.value("user/group_view", true).toBool();
+        isButtonsInTimelineEnabled_ = settings.value("user/timeline/buttons", true).toBool();
+        isMessageHoverHighlightEnabled_ =
+          settings.value("user/timeline/message_hover_highlight", false).toBool();
         isMarkdownEnabled_            = settings.value("user/markdown_enabled", true).toBool();
         isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool();
         sortByImportance_             = settings.value("user/sort_by_unread", true).toBool();
@@ -165,6 +167,7 @@ UserSettings::save()
 
         settings.beginGroup("timeline");
         settings.setValue("buttons", isButtonsInTimelineEnabled_);
+        settings.setValue("message_hover_highlight", isMessageHoverHighlightEnabled_);
         settings.endGroup();
 
         settings.setValue("avatar_circles", avatarCircles_);
@@ -235,6 +238,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         groupViewToggle_         = new Toggle{this};
         timelineButtonsToggle_   = new Toggle{this};
         typingNotifications_     = new Toggle{this};
+        messageHoverHighlight_   = new Toggle{this};
         sortByImportance_        = new Toggle{this};
         readReceipts_            = new Toggle{this};
         markdownEnabled_         = new Toggle{this};
@@ -345,6 +349,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
         boxWrap(tr("Read receipts"), readReceipts_);
         boxWrap(tr("Send messages as Markdown"), markdownEnabled_);
         boxWrap(tr("Desktop notifications"), desktopNotifications_);
+        boxWrap(tr("Highlight message on hover"), messageHoverHighlight_);
         formLayout_->addRow(uiLabel_);
         formLayout_->addRow(new HorizontalLine{this});
 
@@ -463,6 +468,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
                 settings_->setDesktopNotifications(!isDisabled);
         });
 
+        connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool isDisabled) {
+                settings_->setMessageHoverHighlight(!isDisabled);
+        });
+
         connect(
           sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
 
@@ -495,6 +504,7 @@ UserSettingsPage::showEvent(QShowEvent *)
         readReceipts_->setState(!settings_->isReadReceiptsEnabled());
         markdownEnabled_->setState(!settings_->isMarkdownEnabled());
         desktopNotifications_->setState(!settings_->hasDesktopNotifications());
+        messageHoverHighlight_->setState(!settings_->isMessageHoverHighlightEnabled());
         deviceIdValue_->setText(QString::fromStdString(http::client()->device_id()));
 
         deviceFingerprintValue_->setText(
diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index 6b9834eac126f29755dc1e95dbfe1a8a44181993..088bbfb5ff39f9883db99a03b6e21bc311edf14a 100644
--- a/src/UserSettingsPage.h
+++ b/src/UserSettingsPage.h
@@ -44,6 +44,11 @@ public:
         void load();
         void applyTheme();
         void setTheme(QString theme);
+        void setMessageHoverHighlight(bool state)
+        {
+                isMessageHoverHighlightEnabled_ = state;
+                save();
+        }
         void setTray(bool state)
         {
                 isTrayEnabled_ = state;
@@ -118,6 +123,7 @@ public:
         }
 
         QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; }
+        bool isMessageHoverHighlightEnabled() const { return isMessageHoverHighlightEnabled_; }
         bool isTrayEnabled() const { return isTrayEnabled_; }
         bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; }
         bool isGroupViewEnabled() const { return isGroupViewEnabled_; }
@@ -144,6 +150,7 @@ private:
             ? "light"
             : "system";
         QString theme_;
+        bool isMessageHoverHighlightEnabled_;
         bool isTrayEnabled_;
         bool isStartInTrayEnabled_;
         bool isGroupViewEnabled_;
@@ -203,6 +210,7 @@ private:
         Toggle *groupViewToggle_;
         Toggle *timelineButtonsToggle_;
         Toggle *typingNotifications_;
+        Toggle *messageHoverHighlight_;
         Toggle *sortByImportance_;
         Toggle *readReceipts_;
         Toggle *markdownEnabled_;
diff --git a/src/main.cpp b/src/main.cpp
index 09c326f4988262ba948b4bad37ff98bcf904c1af..ec4f638d575583836f5309565d2a146fa450ef03 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -116,6 +116,7 @@ main(int argc, char *argv[])
         QCoreApplication::setApplicationName("nheko");
         QCoreApplication::setApplicationVersion(nheko::version);
         QCoreApplication::setOrganizationName("nheko");
+        QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
         QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
         QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
         SingleApplication app(argc,