Merge branch 'master' into master-ghc8107

This commit is contained in:
Evgeny Poberezkin 2023-11-19 23:42:13 +00:00
commit daa8d9bb21
53 changed files with 3152 additions and 489 deletions

View File

@ -1966,6 +1966,14 @@ This cannot be undone!</source>
<target>Криптирано съобщение: неочаквана грешка</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Въведете kодa за достъп</target>

View File

@ -1966,6 +1966,14 @@ This cannot be undone!</source>
<target>Šifrovaná zpráva: neočekávaná chyba</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Zadat heslo</target>

View File

@ -89,11 +89,12 @@
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source>
<target>%@ und %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve">
<source>%@ and %@ connected</source>
<target>%@ und %@ wurden verbunden</target>
<target>%@ und %@ wurden mit Ihnen verbunden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve">
@ -103,6 +104,7 @@
</trans-unit>
<trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source>
<target>%@ wurde mit Ihnen verbunden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
@ -132,11 +134,12 @@
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source>
<target>%@, %@ und %lld Mitglieder</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
<source>%@, %@ and %lld other members connected</source>
<target>%@, %@ und %lld weitere Mitglieder wurden verbunden</target>
<target>%@, %@ und %lld weitere Mitglieder wurden mit Ihnen verbunden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@:" xml:space="preserve">
@ -201,6 +204,7 @@
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source>
<target>%lld Gruppenereignisse</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
@ -210,14 +214,17 @@
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source>
<target>%lld Nachrichten blockiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source>
<target>%lld Nachrichten als gelöscht markiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source>
<target>%lld Nachrichten von %@ moderiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@ -394,6 +401,7 @@
</trans-unit>
<trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source>
<target>0 sek</target>
<note>time to disappear</note>
</trans-unit>
<trans-unit id="0s" xml:space="preserve">
@ -623,6 +631,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Alle neuen Nachrichten von %@ werden verborgen!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@ -732,10 +741,12 @@
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source>
<target>Bereits verbunden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source>
<target>Sie sind bereits Mitglied der Gruppe!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Always use relay" xml:space="preserve">
@ -875,14 +886,17 @@
</trans-unit>
<trans-unit id="Block" xml:space="preserve">
<source>Block</source>
<target>Blockieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve">
<source>Block member</source>
<target>Mitglied blockieren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source>
<target>Mitglied blockieren?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@ -1153,20 +1167,26 @@
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source>
<target>Mit Ihnen selbst verbinden?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself?
This is your own SimpleX address!</source>
<target>Mit Ihnen selbst verbinden?
Das ist Ihre eigene SimpleX-Adresse!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Mit Ihnen selbst verbinden?
Das ist Ihr eigener Einmal-Link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source>
<target>Über die Kontakt-Adresse verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via link" xml:space="preserve">
@ -1186,6 +1206,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source>
<target>Mit %@ verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1285,6 +1306,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
<source>Correct name to %@?</source>
<target>Richtiger Name für %@?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve">
@ -1309,6 +1331,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create group" xml:space="preserve">
<source>Create group</source>
<target>Gruppe erstellen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
@ -1333,6 +1356,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source>
<target>Profil erstellen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create queue" xml:space="preserve">
@ -1495,6 +1519,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<source>Delete %lld messages?</source>
<target>%lld Nachrichten löschen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@ -1524,6 +1549,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source>
<target>Kontakt löschen und benachrichtigen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete archive" xml:space="preserve">
@ -1559,6 +1585,8 @@ This is your own one-time link!</source>
<trans-unit id="Delete contact?&#10;This cannot be undone!" xml:space="preserve">
<source>Delete contact?
This cannot be undone!</source>
<target>Kontakt löschen?
Das kann nicht rückgängig gemacht werden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete database" xml:space="preserve">
@ -1966,6 +1994,14 @@ This cannot be undone!</source>
<target>Verschlüsselte Nachricht: Unerwarteter Fehler</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Zugangscode eingeben</target>
@ -1978,6 +2014,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve">
<source>Enter group name…</source>
<target>Geben Sie den Gruppennamen ein…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
@ -2007,6 +2044,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve">
<source>Enter your name…</source>
<target>Geben Sie Ihren Namen ein…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
@ -2286,6 +2324,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Expand" xml:space="preserve">
<source>Expand</source>
<target>Erweitern</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Export database" xml:space="preserve">
@ -2435,6 +2474,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Vollständig dezentralisiert nur für Mitglieder sichtbar.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
@ -2459,10 +2499,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Group already exists" xml:space="preserve">
<source>Group already exists</source>
<target>Die Gruppe besteht bereits</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group already exists!" xml:space="preserve">
<source>Group already exists!</source>
<target>Die Gruppe besteht bereits!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group display name" xml:space="preserve">
@ -2814,6 +2856,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source>
<target>Ungültiger Name!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve">
@ -2884,7 +2927,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="It seems like you are already connected via this link. If it is not the case, there was an error (%@)." xml:space="preserve">
<source>It seems like you are already connected via this link. If it is not the case, there was an error (%@).</source>
<target>Es sieht so aus, dass Sie bereits über diesen Link verbunden sind. Wenn das nicht der Fall, gab es einen Fehler (%@).</target>
<target>Es sieht so aus, als ob Sie bereits über diesen Link verbunden sind. Wenn das nicht der Fall ist, gab es einen Fehler (%@).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Italian interface" xml:space="preserve">
@ -2909,6 +2952,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
<source>Join group?</source>
<target>Der Gruppe beitreten?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join incognito" xml:space="preserve">
@ -2918,11 +2962,14 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join with current profile" xml:space="preserve">
<source>Join with current profile</source>
<target>Mit dem aktuellen Profil beitreten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join your group?&#10;This is your link for group %@!" xml:space="preserve">
<source>Join your group?
This is your link for group %@!</source>
<target>Ihrer Gruppe beitreten?
Das ist Ihr Link für die Gruppe %@!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Joining group" xml:space="preserve">
@ -3142,6 +3189,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages from %@ will be shown!" xml:space="preserve">
<source>Messages from %@ will be shown!</source>
<target>Die Nachrichten von %@ werden angezeigt!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve">
@ -3495,6 +3543,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open group" xml:space="preserve">
<source>Open group</source>
<target>Gruppe öffnen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open user profiles" xml:space="preserve">
@ -3704,10 +3753,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profilname</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profilname:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
@ -3957,10 +4008,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Repeat connection request?" xml:space="preserve">
<source>Repeat connection request?</source>
<target>Verbindungsanfrage wiederholen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Repeat join request?" xml:space="preserve">
<source>Repeat join request?</source>
<target>Verbindungsanfrage wiederholen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reply" xml:space="preserve">
@ -4680,6 +4733,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve">
<source>Tap to Connect</source>
<target>Zum Verbinden antippen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
@ -4876,10 +4930,12 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit>
<trans-unit id="This is your own SimpleX address!" xml:space="preserve">
<source>This is your own SimpleX address!</source>
<target>Das ist Ihre eigene SimpleX-Adresse!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>Das ist Ihr eigener Einmal-Link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@ -4926,7 +4982,7 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
</trans-unit>
<trans-unit id="To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." xml:space="preserve">
<source>To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page.</source>
<target>Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite **Meine Chat-Profile** ein, um Ihr verborgenes Profil zu sehen.</target>
<target>Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite **Ihre Chat-Profile** ein, um Ihr verborgenes Profil zu sehen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To support instant push notifications the chat database has to be migrated." xml:space="preserve">
@ -4981,14 +5037,17 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
</trans-unit>
<trans-unit id="Unblock" xml:space="preserve">
<source>Unblock</source>
<target>Freigeben</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
<source>Unblock member</source>
<target>Mitglied freigeben</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
<source>Unblock member?</source>
<target>Mitglied freigeben?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
@ -5315,7 +5374,7 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="You" xml:space="preserve">
<source>You</source>
<target>Meine Daten</target>
<target>Ihre Daten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You accepted connection" xml:space="preserve">
@ -5340,31 +5399,39 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
<source>You are already connecting to %@.</source>
<target>Sie sind bereits mit %@ verbunden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting via this one-time link!" xml:space="preserve">
<source>You are already connecting via this one-time link!</source>
<target>Sie sind bereits über diesen Einmal-Link verbunden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already in group %@." xml:space="preserve">
<source>You are already in group %@.</source>
<target>Sie sind bereits Mitglied der Gruppe %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group %@." xml:space="preserve">
<source>You are already joining the group %@.</source>
<target>Sie sind bereits Mitglied der Gruppe %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link!" xml:space="preserve">
<source>You are already joining the group via this link!</source>
<target>Sie sind über diesen Link bereits Mitglied der Gruppe!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link." xml:space="preserve">
<source>You are already joining the group via this link.</source>
<target>Sie sind über diesen Link bereits Mitglied der Gruppe.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group!&#10;Repeat join request?" xml:space="preserve">
<source>You are already joining the group!
Repeat join request?</source>
<target>Sie sind bereits Mitglied dieser Gruppe!
Verbindungsanfrage wiederholen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
@ -5464,11 +5531,14 @@ Repeat join request?</source>
</trans-unit>
<trans-unit id="You have already requested connection via this address!" xml:space="preserve">
<source>You have already requested connection via this address!</source>
<target>Sie haben über diese Adresse bereits eine Verbindung beantragt!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have already requested connection!&#10;Repeat connection request?" xml:space="preserve">
<source>You have already requested connection!
Repeat connection request?</source>
<target>Sie haben bereits ein Verbindungsanfrage beantragt!
Verbindungsanfrage wiederholen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve">
@ -5523,6 +5593,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>Sie werden verbunden, sobald das Endgerät des Gruppenlink-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@ -5542,6 +5613,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will connect to all group members." xml:space="preserve">
<source>You will connect to all group members.</source>
<target>Sie werden mit allen Gruppenmitgliedern verbunden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
@ -5586,7 +5658,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your SimpleX address" xml:space="preserve">
<source>Your SimpleX address</source>
<target>Meine SimpleX-Adresse</target>
<target>Ihre SimpleX-Adresse</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your XFTP servers" xml:space="preserve">
@ -5611,7 +5683,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Meine Chat-Profile</target>
<target>Ihre Chat-Profile</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your contact needs to be online for the connection to complete.&#10;You can cancel this connection and remove the contact (and try later with a new link)." xml:space="preserve">
@ -5655,16 +5727,17 @@ Sie können es in den Einstellungen ändern.</target>
</trans-unit>
<trans-unit id="Your preferences" xml:space="preserve">
<source>Your preferences</source>
<target>Meine Präferenzen</target>
<target>Ihre Präferenzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your privacy" xml:space="preserve">
<source>Your privacy</source>
<target>Meine Privatsphäre</target>
<target>Ihre Privatsphäre</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile" xml:space="preserve">
<source>Your profile</source>
<target>Mein Profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
@ -5701,7 +5774,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="Your settings" xml:space="preserve">
<source>Your settings</source>
<target>Meine Einstellungen</target>
<target>Ihre Einstellungen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="[Contribute](https://github.com/simplex-chat/simplex-chat#contribute)" xml:space="preserve">
@ -5761,6 +5834,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="and %lld other events" xml:space="preserve">
<source>and %lld other events</source>
<target>und %lld weitere Ereignisse</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="audio call (not e2e encrypted)" xml:space="preserve">
@ -5780,6 +5854,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>blockiert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@ -5954,6 +6029,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</trans-unit>
<trans-unit id="deleted contact" xml:space="preserve">
<source>deleted contact</source>
<target>Gelöschter Kontakt</target>
<note>rcv direct event chat item</note>
</trans-unit>
<trans-unit id="deleted group" xml:space="preserve">

View File

@ -1994,6 +1994,16 @@ This cannot be undone!</target>
<target>Encrypted message: unexpected error</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<target>Encryption re-negotiation error</target>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<target>Encryption re-negotiation failed.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Enter Passcode</target>

View File

@ -1966,6 +1966,14 @@ This cannot be undone!</source>
<target>Mensaje cifrado: error inesperado</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Introduce Código</target>

View File

@ -1960,6 +1960,14 @@ This cannot be undone!</source>
<target>Salattu viesti: odottamaton virhe</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Syötä pääsykoodi</target>

View File

@ -89,6 +89,7 @@
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source>
<target>%@ et %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve">
@ -103,6 +104,7 @@
</trans-unit>
<trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source>
<target>%@ connecté(e)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
@ -132,6 +134,7 @@
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source>
<target>%@, %@ et %lld membres</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
@ -201,6 +204,7 @@
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source>
<target>%lld événements de groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
@ -210,14 +214,17 @@
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source>
<target>%lld messages bloqués</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source>
<target>%lld messages marqués comme supprimés</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source>
<target>%lld messages modérés par %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@ -394,6 +401,7 @@
</trans-unit>
<trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source>
<target>0 sec</target>
<note>time to disappear</note>
</trans-unit>
<trans-unit id="0s" xml:space="preserve">
@ -623,6 +631,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Tous les nouveaux messages de %@ seront cachés !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@ -732,10 +741,12 @@
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source>
<target>Déjà en connexion !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source>
<target>Groupe déjà rejoint !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Always use relay" xml:space="preserve">
@ -875,14 +886,17 @@
</trans-unit>
<trans-unit id="Block" xml:space="preserve">
<source>Block</source>
<target>Bloquer</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve">
<source>Block member</source>
<target>Bloquer ce membre</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source>
<target>Bloquer ce membre ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@ -1153,20 +1167,26 @@
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source>
<target>Se connecter à soi-même ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself?
This is your own SimpleX address!</source>
<target>Se connecter à soi-même ?
C'est votre propre adresse SimpleX !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Se connecter à soi-même ?
Il s'agit de votre propre lien unique !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source>
<target>Se connecter via l'adresse de contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via link" xml:space="preserve">
@ -1186,6 +1206,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source>
<target>Se connecter avec %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1285,6 +1306,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
<source>Correct name to %@?</source>
<target>Corriger le nom pour %@ ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve">
@ -1309,6 +1331,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create group" xml:space="preserve">
<source>Create group</source>
<target>Créer un groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
@ -1333,6 +1356,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source>
<target>Créer le profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create queue" xml:space="preserve">
@ -1495,6 +1519,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<source>Delete %lld messages?</source>
<target>Supprimer %lld messages ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@ -1524,6 +1549,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source>
<target>Supprimer et en informer le contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete archive" xml:space="preserve">
@ -1559,6 +1585,8 @@ This is your own one-time link!</source>
<trans-unit id="Delete contact?&#10;This cannot be undone!" xml:space="preserve">
<source>Delete contact?
This cannot be undone!</source>
<target>Supprimer le contact ?
Cette opération ne peut être annulée !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete database" xml:space="preserve">
@ -1966,6 +1994,14 @@ This cannot be undone!</source>
<target>Message chiffrée: erreur inattendue</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Entrer le code d'accès</target>
@ -1978,6 +2014,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve">
<source>Enter group name…</source>
<target>Entrer un nom de groupe…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
@ -2007,6 +2044,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve">
<source>Enter your name…</source>
<target>Entrez votre nom…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
@ -2286,6 +2324,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Expand" xml:space="preserve">
<source>Expand</source>
<target>Développer</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Export database" xml:space="preserve">
@ -2435,6 +2474,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Entièrement décentralisé visible que par ses membres.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
@ -2459,10 +2499,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Group already exists" xml:space="preserve">
<source>Group already exists</source>
<target>Le groupe existe déjà</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group already exists!" xml:space="preserve">
<source>Group already exists!</source>
<target>Ce groupe existe déjà !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group display name" xml:space="preserve">
@ -2814,6 +2856,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source>
<target>Nom invalide !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve">
@ -2909,6 +2952,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
<source>Join group?</source>
<target>Rejoindre le groupe ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join incognito" xml:space="preserve">
@ -2918,11 +2962,14 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join with current profile" xml:space="preserve">
<source>Join with current profile</source>
<target>Rejoindre avec le profil actuel</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join your group?&#10;This is your link for group %@!" xml:space="preserve">
<source>Join your group?
This is your link for group %@!</source>
<target>Rejoindre votre groupe ?
Voici votre lien pour le groupe %@ !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Joining group" xml:space="preserve">
@ -3142,6 +3189,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages from %@ will be shown!" xml:space="preserve">
<source>Messages from %@ will be shown!</source>
<target>Les messages de %@ seront affichés !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve">
@ -3495,6 +3543,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open group" xml:space="preserve">
<source>Open group</source>
<target>Ouvrir le groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open user profiles" xml:space="preserve">
@ -3704,10 +3753,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nom du profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nom du profil :</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
@ -3957,10 +4008,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Repeat connection request?" xml:space="preserve">
<source>Repeat connection request?</source>
<target>Répéter la demande de connexion ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Repeat join request?" xml:space="preserve">
<source>Repeat join request?</source>
<target>Répéter la requête d'adhésion ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reply" xml:space="preserve">
@ -4680,6 +4733,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve">
<source>Tap to Connect</source>
<target>Tapez pour vous connecter</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
@ -4876,10 +4930,12 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
</trans-unit>
<trans-unit id="This is your own SimpleX address!" xml:space="preserve">
<source>This is your own SimpleX address!</source>
<target>Voici votre propre adresse SimpleX !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>Voici votre propre lien unique !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@ -4981,14 +5037,17 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s
</trans-unit>
<trans-unit id="Unblock" xml:space="preserve">
<source>Unblock</source>
<target>Débloquer</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
<source>Unblock member</source>
<target>Débloquer ce membre</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
<source>Unblock member?</source>
<target>Débloquer ce membre ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
@ -5340,31 +5399,39 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
<source>You are already connecting to %@.</source>
<target>Vous êtes déjà en train de vous connecter à %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting via this one-time link!" xml:space="preserve">
<source>You are already connecting via this one-time link!</source>
<target>Vous êtes déjà connecté(e) via ce lien unique !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already in group %@." xml:space="preserve">
<source>You are already in group %@.</source>
<target>Vous êtes déjà dans le groupe %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group %@." xml:space="preserve">
<source>You are already joining the group %@.</source>
<target>Vous êtes déjà en train de rejoindre le groupe %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link!" xml:space="preserve">
<source>You are already joining the group via this link!</source>
<target>Vous êtes déjà en train de rejoindre le groupe via ce lien !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link." xml:space="preserve">
<source>You are already joining the group via this link.</source>
<target>Vous êtes déjà en train de rejoindre le groupe via ce lien.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group!&#10;Repeat join request?" xml:space="preserve">
<source>You are already joining the group!
Repeat join request?</source>
<target>Vous êtes déjà membre de ce groupe !
Répéter la demande d'adhésion ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
@ -5464,11 +5531,14 @@ Repeat join request?</source>
</trans-unit>
<trans-unit id="You have already requested connection via this address!" xml:space="preserve">
<source>You have already requested connection via this address!</source>
<target>Vous avez déjà demandé une connexion via cette adresse !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have already requested connection!&#10;Repeat connection request?" xml:space="preserve">
<source>You have already requested connection!
Repeat connection request?</source>
<target>Vous avez déjà demandé une connexion !
Répéter la demande de connexion ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve">
@ -5523,6 +5593,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>Vous serez connecté(e) lorsque l'appareil de l'hôte du lien de groupe sera en ligne, veuillez patienter ou vérifier plus tard !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@ -5542,6 +5613,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will connect to all group members." xml:space="preserve">
<source>You will connect to all group members.</source>
<target>Vous vous connecterez à tous les membres du groupe.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
@ -5665,6 +5737,7 @@ Vous pouvez modifier ce choix dans les Paramètres.</target>
</trans-unit>
<trans-unit id="Your profile" xml:space="preserve">
<source>Your profile</source>
<target>Votre profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
@ -5761,6 +5834,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit>
<trans-unit id="and %lld other events" xml:space="preserve">
<source>and %lld other events</source>
<target>et %lld autres événements</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="audio call (not e2e encrypted)" xml:space="preserve">
@ -5780,6 +5854,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>blocké</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@ -5954,6 +6029,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</trans-unit>
<trans-unit id="deleted contact" xml:space="preserve">
<source>deleted contact</source>
<target>contact supprimé</target>
<note>rcv direct event chat item</note>
</trans-unit>
<trans-unit id="deleted group" xml:space="preserve">

View File

@ -89,6 +89,7 @@
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source>
<target>%@ e %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve">
@ -103,6 +104,7 @@
</trans-unit>
<trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source>
<target>%@ si è connesso/a</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
@ -132,6 +134,7 @@
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source>
<target>%@, %@ e %lld membri</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
@ -201,6 +204,7 @@
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source>
<target>%lld eventi del gruppo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
@ -210,14 +214,17 @@
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source>
<target>%lld messaggi bloccati</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source>
<target>%lld messaggi contrassegnati eliminati</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source>
<target>%lld messaggi moderati da %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@ -394,6 +401,7 @@
</trans-unit>
<trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source>
<target>0 sec</target>
<note>time to disappear</note>
</trans-unit>
<trans-unit id="0s" xml:space="preserve">
@ -623,6 +631,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Tutti i nuovi messaggi da %@ verrranno nascosti!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@ -732,10 +741,12 @@
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source>
<target>Già in connessione!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source>
<target>Già in ingresso nel gruppo!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Always use relay" xml:space="preserve">
@ -875,14 +886,17 @@
</trans-unit>
<trans-unit id="Block" xml:space="preserve">
<source>Block</source>
<target>Blocca</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve">
<source>Block member</source>
<target>Blocca membro</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source>
<target>Bloccare il membro?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@ -1153,20 +1167,26 @@
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source>
<target>Connettersi a te stesso?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself?
This is your own SimpleX address!</source>
<target>Connettersi a te stesso?
Questo è il tuo indirizzo SimpleX!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Connettersi a te stesso?
Questo è il tuo link una tantum!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source>
<target>Connettere via indirizzo del contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via link" xml:space="preserve">
@ -1186,6 +1206,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source>
<target>Connettersi con %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1285,6 +1306,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
<source>Correct name to %@?</source>
<target>Correggere il nome a %@?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve">
@ -1309,6 +1331,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create group" xml:space="preserve">
<source>Create group</source>
<target>Crea gruppo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
@ -1333,6 +1356,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source>
<target>Crea profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create queue" xml:space="preserve">
@ -1495,6 +1519,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<source>Delete %lld messages?</source>
<target>Eliminare %lld messaggi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@ -1524,6 +1549,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source>
<target>Elimina e avvisa il contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete archive" xml:space="preserve">
@ -1559,6 +1585,8 @@ This is your own one-time link!</source>
<trans-unit id="Delete contact?&#10;This cannot be undone!" xml:space="preserve">
<source>Delete contact?
This cannot be undone!</source>
<target>Eliminare il contatto?
Non è reversibile!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete database" xml:space="preserve">
@ -1966,6 +1994,14 @@ This cannot be undone!</source>
<target>Messaggio crittografato: errore imprevisto</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Inserisci il codice di accesso</target>
@ -1978,6 +2014,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve">
<source>Enter group name…</source>
<target>Inserisci il nome del gruppo…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
@ -2007,6 +2044,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve">
<source>Enter your name…</source>
<target>Inserisci il tuo nome…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
@ -2286,6 +2324,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Expand" xml:space="preserve">
<source>Expand</source>
<target>Espandi</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Export database" xml:space="preserve">
@ -2435,6 +2474,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Completamente decentralizzato: visibile solo ai membri.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
@ -2459,10 +2499,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Group already exists" xml:space="preserve">
<source>Group already exists</source>
<target>Il gruppo esiste già</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group already exists!" xml:space="preserve">
<source>Group already exists!</source>
<target>Il gruppo esiste già!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group display name" xml:space="preserve">
@ -2814,6 +2856,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source>
<target>Nome non valido!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve">
@ -2909,6 +2952,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
<source>Join group?</source>
<target>Entrare nel gruppo?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join incognito" xml:space="preserve">
@ -2918,11 +2962,14 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join with current profile" xml:space="preserve">
<source>Join with current profile</source>
<target>Entra con il profilo attuale</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join your group?&#10;This is your link for group %@!" xml:space="preserve">
<source>Join your group?
This is your link for group %@!</source>
<target>Entrare nel tuo gruppo?
Questo è il tuo link per il gruppo %@!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Joining group" xml:space="preserve">
@ -3142,6 +3189,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages from %@ will be shown!" xml:space="preserve">
<source>Messages from %@ will be shown!</source>
<target>I messaggi da %@ verranno mostrati!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve">
@ -3495,6 +3543,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open group" xml:space="preserve">
<source>Open group</source>
<target>Apri gruppo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open user profiles" xml:space="preserve">
@ -3704,10 +3753,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nome del profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nome del profilo:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
@ -3957,10 +4008,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Repeat connection request?" xml:space="preserve">
<source>Repeat connection request?</source>
<target>Ripetere la richiesta di connessione?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Repeat join request?" xml:space="preserve">
<source>Repeat join request?</source>
<target>Ripetere la richiesta di ingresso?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reply" xml:space="preserve">
@ -4680,6 +4733,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve">
<source>Tap to Connect</source>
<target>Tocca per connettere</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
@ -4876,10 +4930,12 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
</trans-unit>
<trans-unit id="This is your own SimpleX address!" xml:space="preserve">
<source>This is your own SimpleX address!</source>
<target>Questo è il tuo indirizzo SimpleX!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>Questo è il tuo link una tantum!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@ -4981,14 +5037,17 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio
</trans-unit>
<trans-unit id="Unblock" xml:space="preserve">
<source>Unblock</source>
<target>Sblocca</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
<source>Unblock member</source>
<target>Sblocca membro</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
<source>Unblock member?</source>
<target>Sbloccare il membro?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
@ -5340,31 +5399,39 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
<source>You are already connecting to %@.</source>
<target>Ti stai già connettendo a %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting via this one-time link!" xml:space="preserve">
<source>You are already connecting via this one-time link!</source>
<target>Ti stai già connettendo tramite questo link una tantum!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already in group %@." xml:space="preserve">
<source>You are already in group %@.</source>
<target>Sei già nel gruppo %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group %@." xml:space="preserve">
<source>You are already joining the group %@.</source>
<target>Stai già entrando nel gruppo %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link!" xml:space="preserve">
<source>You are already joining the group via this link!</source>
<target>Stai già entrando nel gruppo tramite questo link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link." xml:space="preserve">
<source>You are already joining the group via this link.</source>
<target>Stai già entrando nel gruppo tramite questo link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group!&#10;Repeat join request?" xml:space="preserve">
<source>You are already joining the group!
Repeat join request?</source>
<target>Stai già entrando nel gruppo!
Ripetere la richiesta di ingresso?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
@ -5464,11 +5531,14 @@ Repeat join request?</source>
</trans-unit>
<trans-unit id="You have already requested connection via this address!" xml:space="preserve">
<source>You have already requested connection via this address!</source>
<target>Hai già richiesto la connessione tramite questo indirizzo!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have already requested connection!&#10;Repeat connection request?" xml:space="preserve">
<source>You have already requested connection!
Repeat connection request?</source>
<target>Hai già richiesto la connessione!
Ripetere la richiesta di connessione?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve">
@ -5523,6 +5593,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>Verrai connesso/a quando il dispositivo dell'host del gruppo sarà in linea, attendi o controlla più tardi!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@ -5542,6 +5613,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will connect to all group members." xml:space="preserve">
<source>You will connect to all group members.</source>
<target>Ti connetterai a tutti i membri del gruppo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
@ -5665,6 +5737,7 @@ Puoi modificarlo nelle impostazioni.</target>
</trans-unit>
<trans-unit id="Your profile" xml:space="preserve">
<source>Your profile</source>
<target>Il tuo profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
@ -5761,6 +5834,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="and %lld other events" xml:space="preserve">
<source>and %lld other events</source>
<target>e altri %lld eventi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="audio call (not e2e encrypted)" xml:space="preserve">
@ -5780,6 +5854,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>bloccato</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@ -5814,7 +5889,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="changed role of %@ to %@" xml:space="preserve">
<source>changed role of %1$@ to %2$@</source>
<target>cambiato il ruolo di %1$@ in %2$@</target>
<target>ha cambiato il ruolo di %1$@ in %2$@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="changed your role to %@" xml:space="preserve">
@ -5954,6 +6029,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</trans-unit>
<trans-unit id="deleted contact" xml:space="preserve">
<source>deleted contact</source>
<target>contatto eliminato</target>
<note>rcv direct event chat item</note>
</trans-unit>
<trans-unit id="deleted group" xml:space="preserve">

View File

@ -1963,6 +1963,14 @@ This cannot be undone!</source>
<target>暗号化されたメッセージ : 予期しないエラー</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>パスコードを入力</target>

View File

@ -89,6 +89,7 @@
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source>
<target>%@ en %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve">
@ -103,6 +104,7 @@
</trans-unit>
<trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source>
<target>%@ verbonden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
@ -132,6 +134,7 @@
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source>
<target>%@, %@ en %lld leden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
@ -201,6 +204,7 @@
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source>
<target>%lld groep gebeurtenissen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
@ -210,14 +214,17 @@
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source>
<target>%lld berichten geblokkeerd</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source>
<target>%lld berichten gemarkeerd als verwijderd</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source>
<target>%lld berichten gemodereerd door %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@ -394,6 +401,7 @@
</trans-unit>
<trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source>
<target>0 sec</target>
<note>time to disappear</note>
</trans-unit>
<trans-unit id="0s" xml:space="preserve">
@ -623,6 +631,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Alle nieuwe berichten van %@ worden verborgen!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@ -732,10 +741,12 @@
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source>
<target>Al bezig met verbinden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source>
<target>Al lid van de groep!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Always use relay" xml:space="preserve">
@ -875,14 +886,17 @@
</trans-unit>
<trans-unit id="Block" xml:space="preserve">
<source>Block</source>
<target>Blokkeren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve">
<source>Block member</source>
<target>Lid blokkeren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source>
<target>Lid blokkeren?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@ -977,7 +991,7 @@
</trans-unit>
<trans-unit id="Change member role?" xml:space="preserve">
<source>Change member role?</source>
<target>Rol van gebruiker wijzigen?</target>
<target>Rol van lid wijzigen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Change passcode" xml:space="preserve">
@ -1153,20 +1167,26 @@
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source>
<target>Verbinding maken met jezelf?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself?
This is your own SimpleX address!</source>
<target>Verbinding maken met jezelf?
Dit is uw eigen SimpleX adres!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Verbinding maken met jezelf?
Dit is uw eigen eenmalige link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source>
<target>Verbinding maken via contactadres</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via link" xml:space="preserve">
@ -1186,6 +1206,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source>
<target>Verbonden met %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1285,6 +1306,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
<source>Correct name to %@?</source>
<target>Juiste naam voor %@?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve">
@ -1309,6 +1331,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create group" xml:space="preserve">
<source>Create group</source>
<target>Groep aanmaken</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
@ -1333,6 +1356,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source>
<target>Maak een profiel aan</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create queue" xml:space="preserve">
@ -1495,6 +1519,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<source>Delete %lld messages?</source>
<target>%lld berichten verwijderen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@ -1524,6 +1549,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source>
<target>Contact verwijderen en op de hoogte stellen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete archive" xml:space="preserve">
@ -1559,6 +1585,8 @@ This is your own one-time link!</source>
<trans-unit id="Delete contact?&#10;This cannot be undone!" xml:space="preserve">
<source>Delete contact?
This cannot be undone!</source>
<target>Verwijder contact?
Dit kan niet ongedaan gemaakt worden!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete database" xml:space="preserve">
@ -1966,6 +1994,14 @@ This cannot be undone!</source>
<target>Versleuteld bericht: onverwachte fout</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Voer toegangscode in</target>
@ -1978,6 +2014,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve">
<source>Enter group name…</source>
<target>Groep naam invoeren…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
@ -2007,6 +2044,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve">
<source>Enter your name…</source>
<target>Vul uw naam in…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
@ -2031,7 +2069,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Error adding member(s)" xml:space="preserve">
<source>Error adding member(s)</source>
<target>Fout bij het toevoegen van gebruiker(s)</target>
<target>Fout bij het toevoegen van leden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error changing address" xml:space="preserve">
@ -2161,7 +2199,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Error removing member" xml:space="preserve">
<source>Error removing member</source>
<target>Fout bij verwijderen van gebruiker</target>
<target>Fout bij verwijderen van lid</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error saving %@ servers" xml:space="preserve">
@ -2286,6 +2324,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Expand" xml:space="preserve">
<source>Expand</source>
<target>Uitbreiden</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Export database" xml:space="preserve">
@ -2435,6 +2474,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>Volledig gedecentraliseerd alleen zichtbaar voor leden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
@ -2459,10 +2499,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Group already exists" xml:space="preserve">
<source>Group already exists</source>
<target>Groep bestaat al</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group already exists!" xml:space="preserve">
<source>Group already exists!</source>
<target>Groep bestaat al!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group display name" xml:space="preserve">
@ -2814,6 +2856,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source>
<target>Ongeldige naam!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve">
@ -2909,6 +2952,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
<source>Join group?</source>
<target>Deelnemen aan groep?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join incognito" xml:space="preserve">
@ -2918,11 +2962,14 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join with current profile" xml:space="preserve">
<source>Join with current profile</source>
<target>Word lid met huidig profiel</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join your group?&#10;This is your link for group %@!" xml:space="preserve">
<source>Join your group?
This is your link for group %@!</source>
<target>Sluit u aan bij uw groep?
Dit is jouw link voor groep %@!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Joining group" xml:space="preserve">
@ -3077,22 +3124,22 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Member" xml:space="preserve">
<source>Member</source>
<target>Gebruiker</target>
<target>Lid</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Member role will be changed to &quot;%@&quot;. All group members will be notified." xml:space="preserve">
<source>Member role will be changed to "%@". All group members will be notified.</source>
<target>De rol van gebruiker wordt gewijzigd in "%@". Alle groepsleden worden op de hoogte gebracht.</target>
<target>De rol van lid wordt gewijzigd in "%@". Alle groepsleden worden op de hoogte gebracht.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Member role will be changed to &quot;%@&quot;. The member will receive a new invitation." xml:space="preserve">
<source>Member role will be changed to "%@". The member will receive a new invitation.</source>
<target>De rol van gebruiker wordt gewijzigd in "%@". Het lid ontvangt een nieuwe uitnodiging.</target>
<target>De rol van lid wordt gewijzigd in "%@". Het lid ontvangt een nieuwe uitnodiging.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Member will be removed from group - this cannot be undone!" xml:space="preserve">
<source>Member will be removed from group - this cannot be undone!</source>
<target>Gebruiker wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!</target>
<target>Lid wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Message delivery error" xml:space="preserve">
@ -3142,6 +3189,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages from %@ will be shown!" xml:space="preserve">
<source>Messages from %@ will be shown!</source>
<target>Berichten van %@ worden getoond!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve">
@ -3415,7 +3463,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Only group owners can enable files and media." xml:space="preserve">
<source>Only group owners can enable files and media.</source>
<target>Alleen groepseigenaren kunnen bestanden en media inschakelen.</target>
<target>Alleen groep eigenaren kunnen bestanden en media inschakelen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only group owners can enable voice messages." xml:space="preserve">
@ -3495,6 +3543,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open group" xml:space="preserve">
<source>Open group</source>
<target>Open groep</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open user profiles" xml:space="preserve">
@ -3704,10 +3753,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Profielnaam</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Profielnaam:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
@ -3927,12 +3978,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Remove member" xml:space="preserve">
<source>Remove member</source>
<target>Gebruiker verwijderen</target>
<target>Lid verwijderen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove member?" xml:space="preserve">
<source>Remove member?</source>
<target>Gebruiker verwijderen?</target>
<target>Lid verwijderen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Remove passphrase from keychain?" xml:space="preserve">
@ -3957,10 +4008,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Repeat connection request?" xml:space="preserve">
<source>Repeat connection request?</source>
<target>Verbindingsverzoek herhalen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Repeat join request?" xml:space="preserve">
<source>Repeat join request?</source>
<target>Deelnameverzoek herhalen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reply" xml:space="preserve">
@ -4075,7 +4128,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Save and notify group members" xml:space="preserve">
<source>Save and notify group members</source>
<target>Opslaan en Groep leden melden</target>
<target>Opslaan en groep leden melden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save and update group profile" xml:space="preserve">
@ -4680,6 +4733,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve">
<source>Tap to Connect</source>
<target>Tik om verbinding te maken</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
@ -4689,12 +4743,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to join" xml:space="preserve">
<source>Tap to join</source>
<target>Tik om mee te doen</target>
<target>Tik om lid te worden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to join incognito" xml:space="preserve">
<source>Tap to join incognito</source>
<target>Tik om incognito deel te nemen</target>
<target>Tik om incognito lid te worden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to start a new chat" xml:space="preserve">
@ -4876,10 +4930,12 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
</trans-unit>
<trans-unit id="This is your own SimpleX address!" xml:space="preserve">
<source>This is your own SimpleX address!</source>
<target>Dit is uw eigen SimpleX adres!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>Dit is uw eigen eenmalige link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@ -4981,14 +5037,17 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc
</trans-unit>
<trans-unit id="Unblock" xml:space="preserve">
<source>Unblock</source>
<target>Deblokkeren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
<source>Unblock member</source>
<target>Lid deblokkeren</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
<source>Unblock member?</source>
<target>Lid deblokkeren?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
@ -5340,31 +5399,39 @@ Om verbinding te maken, vraagt u uw contact om een andere verbinding link te mak
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
<source>You are already connecting to %@.</source>
<target>U maakt al verbinding met %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting via this one-time link!" xml:space="preserve">
<source>You are already connecting via this one-time link!</source>
<target>Je maakt al verbinding via deze eenmalige link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already in group %@." xml:space="preserve">
<source>You are already in group %@.</source>
<target>Je zit al in groep %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group %@." xml:space="preserve">
<source>You are already joining the group %@.</source>
<target>Je bent al lid van de groep %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link!" xml:space="preserve">
<source>You are already joining the group via this link!</source>
<target>Je wordt al lid van de groep via deze link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link." xml:space="preserve">
<source>You are already joining the group via this link.</source>
<target>Je wordt al lid van de groep via deze link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group!&#10;Repeat join request?" xml:space="preserve">
<source>You are already joining the group!
Repeat join request?</source>
<target>Je sluit je al aan bij de groep!
Deelnameverzoek herhalen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
@ -5464,11 +5531,14 @@ Repeat join request?</source>
</trans-unit>
<trans-unit id="You have already requested connection via this address!" xml:space="preserve">
<source>You have already requested connection via this address!</source>
<target>U heeft al een verbinding aangevraagd via dit adres!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have already requested connection!&#10;Repeat connection request?" xml:space="preserve">
<source>You have already requested connection!
Repeat connection request?</source>
<target>Je hebt al verbinding aangevraagd!
Verbindingsverzoek herhalen?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve">
@ -5523,6 +5593,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>U wordt verbonden wanneer het apparaat van de groep link host online is. Wacht even of controleer het later opnieuw!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@ -5542,6 +5613,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will connect to all group members." xml:space="preserve">
<source>You will connect to all group members.</source>
<target>Je maakt verbinding met alle leden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
@ -5665,6 +5737,7 @@ U kunt dit wijzigen in Instellingen.</target>
</trans-unit>
<trans-unit id="Your profile" xml:space="preserve">
<source>Your profile</source>
<target>Jouw profiel</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
@ -5761,6 +5834,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="and %lld other events" xml:space="preserve">
<source>and %lld other events</source>
<target>en %lld andere gebeurtenissen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="audio call (not e2e encrypted)" xml:space="preserve">
@ -5780,6 +5854,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>geblokkeerd</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@ -5954,6 +6029,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="deleted contact" xml:space="preserve">
<source>deleted contact</source>
<target>verwijderd contact</target>
<note>rcv direct event chat item</note>
</trans-unit>
<trans-unit id="deleted group" xml:space="preserve">
@ -6168,7 +6244,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</trans-unit>
<trans-unit id="member" xml:space="preserve">
<source>member</source>
<target>gebruiker</target>
<target>lid</target>
<note>member role</note>
</trans-unit>
<trans-unit id="member connected" xml:space="preserve">

View File

@ -89,6 +89,7 @@
</trans-unit>
<trans-unit id="%@ and %@" xml:space="preserve">
<source>%@ and %@</source>
<target>%@ i %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ and %@ connected" xml:space="preserve">
@ -103,6 +104,7 @@
</trans-unit>
<trans-unit id="%@ connected" xml:space="preserve">
<source>%@ connected</source>
<target>%@ połączony</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
@ -132,6 +134,7 @@
</trans-unit>
<trans-unit id="%@, %@ and %lld members" xml:space="preserve">
<source>%@, %@ and %lld members</source>
<target>%@, %@ i %lld członków</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@, %@ and %lld other members connected" xml:space="preserve">
@ -201,6 +204,7 @@
</trans-unit>
<trans-unit id="%lld group events" xml:space="preserve">
<source>%lld group events</source>
<target>%lld wydarzeń grupy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
@ -210,14 +214,17 @@
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<source>%lld messages blocked</source>
<target>%lld wiadomości zablokowanych</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<source>%lld messages marked deleted</source>
<target>%lld wiadomości oznaczonych do usunięcia</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<source>%lld messages moderated by %@</source>
<target>%lld wiadomości zmoderowanych przez %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@ -394,6 +401,7 @@
</trans-unit>
<trans-unit id="0 sec" xml:space="preserve">
<source>0 sec</source>
<target>0 sek</target>
<note>time to disappear</note>
</trans-unit>
<trans-unit id="0s" xml:space="preserve">
@ -623,6 +631,7 @@
</trans-unit>
<trans-unit id="All new messages from %@ will be hidden!" xml:space="preserve">
<source>All new messages from %@ will be hidden!</source>
<target>Wszystkie nowe wiadomości z %@ zostaną ukryte!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All your contacts will remain connected." xml:space="preserve">
@ -732,10 +741,12 @@
</trans-unit>
<trans-unit id="Already connecting!" xml:space="preserve">
<source>Already connecting!</source>
<target>Już połączony!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Already joining the group!" xml:space="preserve">
<source>Already joining the group!</source>
<target>Już dołączono do grupy!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Always use relay" xml:space="preserve">
@ -875,14 +886,17 @@
</trans-unit>
<trans-unit id="Block" xml:space="preserve">
<source>Block</source>
<target>Zablokuj</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member" xml:space="preserve">
<source>Block member</source>
<target>Zablokuj członka</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
<source>Block member?</source>
<target>Zablokować członka?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@ -1153,20 +1167,26 @@
</trans-unit>
<trans-unit id="Connect to yourself?" xml:space="preserve">
<source>Connect to yourself?</source>
<target>Połączyć się ze sobą?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own SimpleX address!" xml:space="preserve">
<source>Connect to yourself?
This is your own SimpleX address!</source>
<target>Połączyć się ze sobą?
To jest twój własny adres SimpleX!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect to yourself?&#10;This is your own one-time link!" xml:space="preserve">
<source>Connect to yourself?
This is your own one-time link!</source>
<target>Połączyć się ze sobą?
To jest twój jednorazowy link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact address" xml:space="preserve">
<source>Connect via contact address</source>
<target>Połącz przez adres kontaktowy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via link" xml:space="preserve">
@ -1186,6 +1206,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Connect with %@" xml:space="preserve">
<source>Connect with %@</source>
<target>Połącz z %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@ -1285,6 +1306,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Correct name to %@?" xml:space="preserve">
<source>Correct name to %@?</source>
<target>Poprawić imię na %@?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create" xml:space="preserve">
@ -1309,6 +1331,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create group" xml:space="preserve">
<source>Create group</source>
<target>Utwórz grupę</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create group link" xml:space="preserve">
@ -1333,6 +1356,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Create profile" xml:space="preserve">
<source>Create profile</source>
<target>Utwórz profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create queue" xml:space="preserve">
@ -1495,6 +1519,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<source>Delete %lld messages?</source>
<target>Usunąć %lld wiadomości?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@ -1524,6 +1549,7 @@ This is your own one-time link!</source>
</trans-unit>
<trans-unit id="Delete and notify contact" xml:space="preserve">
<source>Delete and notify contact</source>
<target>Usuń i powiadom kontakt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete archive" xml:space="preserve">
@ -1559,6 +1585,8 @@ This is your own one-time link!</source>
<trans-unit id="Delete contact?&#10;This cannot be undone!" xml:space="preserve">
<source>Delete contact?
This cannot be undone!</source>
<target>Usunąć kontakt?
To nie może być cofnięte!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete database" xml:space="preserve">
@ -1966,6 +1994,14 @@ This cannot be undone!</source>
<target>Zaszyfrowana wiadomość: nieoczekiwany błąd</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Wprowadź Pin</target>
@ -1978,6 +2014,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter group name…" xml:space="preserve">
<source>Enter group name…</source>
<target>Wpisz nazwę grupy…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter passphrase…" xml:space="preserve">
@ -2007,6 +2044,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Enter your name…" xml:space="preserve">
<source>Enter your name…</source>
<target>Wpisz swoją nazwę…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error" xml:space="preserve">
@ -2286,6 +2324,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Expand" xml:space="preserve">
<source>Expand</source>
<target>Rozszerz</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Export database" xml:space="preserve">
@ -2435,6 +2474,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Fully decentralized visible only to members." xml:space="preserve">
<source>Fully decentralized visible only to members.</source>
<target>W pełni zdecentralizowana widoczna tylko dla członków.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fully re-implemented - work in background!" xml:space="preserve">
@ -2459,10 +2499,12 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Group already exists" xml:space="preserve">
<source>Group already exists</source>
<target>Grupa już istnieje</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group already exists!" xml:space="preserve">
<source>Group already exists!</source>
<target>Grupa już istnieje!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group display name" xml:space="preserve">
@ -2814,6 +2856,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Invalid name!" xml:space="preserve">
<source>Invalid name!</source>
<target>Nieprawidłowa nazwa!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid server address!" xml:space="preserve">
@ -2909,6 +2952,7 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
<source>Join group?</source>
<target>Dołączyć do grupy?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join incognito" xml:space="preserve">
@ -2918,11 +2962,14 @@ This cannot be undone!</source>
</trans-unit>
<trans-unit id="Join with current profile" xml:space="preserve">
<source>Join with current profile</source>
<target>Dołącz z obecnym profilem</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join your group?&#10;This is your link for group %@!" xml:space="preserve">
<source>Join your group?
This is your link for group %@!</source>
<target>Dołączyć do twojej grupy?
To jest twój link do grupy %@!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Joining group" xml:space="preserve">
@ -3142,6 +3189,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Messages from %@ will be shown!" xml:space="preserve">
<source>Messages from %@ will be shown!</source>
<target>Wiadomości od %@ zostaną pokazane!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve">
@ -3495,6 +3543,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Open group" xml:space="preserve">
<source>Open group</source>
<target>Grupa otwarta</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Open user profiles" xml:space="preserve">
@ -3704,10 +3753,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Profile name" xml:space="preserve">
<source>Profile name</source>
<target>Nazwa profilu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile name:" xml:space="preserve">
<source>Profile name:</source>
<target>Nazwa profilu:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Profile password" xml:space="preserve">
@ -3957,10 +4008,12 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Repeat connection request?" xml:space="preserve">
<source>Repeat connection request?</source>
<target>Powtórzyć prośbę połączenia?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Repeat join request?" xml:space="preserve">
<source>Repeat join request?</source>
<target>Powtórzyć prośbę dołączenia?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reply" xml:space="preserve">
@ -4680,6 +4733,7 @@ This is your link for group %@!</source>
</trans-unit>
<trans-unit id="Tap to Connect" xml:space="preserve">
<source>Tap to Connect</source>
<target>Dotknij aby połączyć</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
@ -4876,10 +4930,12 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
</trans-unit>
<trans-unit id="This is your own SimpleX address!" xml:space="preserve">
<source>This is your own SimpleX address!</source>
<target>To jest twój własny adres SimpleX!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This is your own one-time link!" xml:space="preserve">
<source>This is your own one-time link!</source>
<target>To jest twój jednorazowy link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This setting applies to messages in your current chat profile **%@**." xml:space="preserve">
@ -4981,14 +5037,17 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
</trans-unit>
<trans-unit id="Unblock" xml:space="preserve">
<source>Unblock</source>
<target>Odblokuj</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
<source>Unblock member</source>
<target>Odblokuj członka</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
<source>Unblock member?</source>
<target>Odblokować członka?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
@ -5340,31 +5399,39 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
</trans-unit>
<trans-unit id="You are already connecting to %@." xml:space="preserve">
<source>You are already connecting to %@.</source>
<target>Już się łączysz z %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already connecting via this one-time link!" xml:space="preserve">
<source>You are already connecting via this one-time link!</source>
<target>Już jesteś połączony z tym jednorazowym linkiem!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already in group %@." xml:space="preserve">
<source>You are already in group %@.</source>
<target>Już jesteś w grupie %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group %@." xml:space="preserve">
<source>You are already joining the group %@.</source>
<target>Już dołączasz do grupy %@.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link!" xml:space="preserve">
<source>You are already joining the group via this link!</source>
<target>Już dołączasz do grupy przez ten link!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group via this link." xml:space="preserve">
<source>You are already joining the group via this link.</source>
<target>Już dołączasz do grupy przez ten link.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are already joining the group!&#10;Repeat join request?" xml:space="preserve">
<source>You are already joining the group!
Repeat join request?</source>
<target>Już dołączasz do grupy!
Powtórzyć prośbę dołączenia?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You are connected to the server used to receive messages from this contact." xml:space="preserve">
@ -5464,11 +5531,14 @@ Repeat join request?</source>
</trans-unit>
<trans-unit id="You have already requested connection via this address!" xml:space="preserve">
<source>You have already requested connection via this address!</source>
<target>Już prosiłeś o połączenie na ten adres!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have already requested connection!&#10;Repeat connection request?" xml:space="preserve">
<source>You have already requested connection!
Repeat connection request?</source>
<target>Już prosiłeś o połączenie!
Powtórzyć prośbę połączenia?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve">
@ -5523,6 +5593,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will be connected when group link host's device is online, please wait or check later!" xml:space="preserve">
<source>You will be connected when group link host's device is online, please wait or check later!</source>
<target>Zostaniesz połączony, gdy urządzenie hosta grupy będzie online, proszę czekać lub sprawdzić później!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will be connected when your connection request is accepted, please wait or check later!" xml:space="preserve">
@ -5542,6 +5613,7 @@ Repeat connection request?</source>
</trans-unit>
<trans-unit id="You will connect to all group members." xml:space="preserve">
<source>You will connect to all group members.</source>
<target>Zostaniesz połączony ze wszystkimi członkami grupy.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You will still receive calls and notifications from muted profiles when they are active." xml:space="preserve">
@ -5665,6 +5737,7 @@ Możesz to zmienić w Ustawieniach.</target>
</trans-unit>
<trans-unit id="Your profile" xml:space="preserve">
<source>Your profile</source>
<target>Twój profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
@ -5761,6 +5834,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="and %lld other events" xml:space="preserve">
<source>and %lld other events</source>
<target>i %lld innych wydarzeń</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="audio call (not e2e encrypted)" xml:space="preserve">
@ -5780,6 +5854,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="blocked" xml:space="preserve">
<source>blocked</source>
<target>zablokowany</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@ -5954,6 +6029,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</trans-unit>
<trans-unit id="deleted contact" xml:space="preserve">
<source>deleted contact</source>
<target>usunięto kontakt</target>
<note>rcv direct event chat item</note>
</trans-unit>
<trans-unit id="deleted group" xml:space="preserve">

View File

@ -1966,6 +1966,14 @@ This cannot be undone!</source>
<target>Зашифрованное сообщение: неожиданная ошибка</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Введите Код</target>

View File

@ -1946,6 +1946,14 @@ This cannot be undone!</source>
<target>ข้อความที่ encrypt: ข้อผิดพลาดที่ไม่คาดคิด</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>ใส่รหัสผ่าน</target>

View File

@ -1956,6 +1956,14 @@ This cannot be undone!</source>
<target>Зашифроване повідомлення: несподівана помилка</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>Введіть пароль</target>

View File

@ -1966,6 +1966,14 @@ This cannot be undone!</source>
<target>加密消息:意外错误</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation error" xml:space="preserve">
<source>Encryption re-negotiation error</source>
<note>message decrypt error item</note>
</trans-unit>
<trans-unit id="Encryption re-negotiation failed." xml:space="preserve">
<source>Encryption re-negotiation failed.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enter Passcode" xml:space="preserve">
<source>Enter Passcode</source>
<target>输入密码</target>

View File

@ -119,11 +119,17 @@
"%@ %@" = "%@ %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ und %@ wurden verbunden";
"%@ and %@" = "%@ und %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ und %@ wurden mit Ihnen verbunden";
/* copied message info, <sender> at <time> */
"%@ at %@:" = "%1$@ an %2$@:";
/* No comment provided by engineer. */
"%@ connected" = "%@ wurde mit Ihnen verbunden";
/* notification title */
"%@ is connected!" = "%@ ist mit Ihnen verbunden!";
@ -140,7 +146,10 @@
"%@ wants to connect!" = "%@ will sich mit Ihnen verbinden!";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ und %lld weitere Mitglieder wurden verbunden";
"%@, %@ and %lld members" = "%@, %@ und %lld Mitglieder";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ und %lld weitere Mitglieder wurden mit Ihnen verbunden";
/* copied message info */
"%@:" = "%@:";
@ -178,9 +187,21 @@
/* No comment provided by engineer. */
"%lld file(s) with total size of %@" = "%lld Datei(en) mit einem Gesamtspeicherverbrauch von %@";
/* No comment provided by engineer. */
"%lld group events" = "%lld Gruppenereignisse";
/* No comment provided by engineer. */
"%lld members" = "%lld Mitglieder";
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld Nachrichten blockiert";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld Nachrichten als gelöscht markiert";
/* No comment provided by engineer. */
"%lld messages moderated by %@" = "%lld Nachrichten von %@ moderiert";
/* No comment provided by engineer. */
"%lld minutes" = "%lld Minuten";
@ -229,6 +250,9 @@
/* No comment provided by engineer. */
"~strike~" = "\\~durchstreichen~";
/* time to disappear */
"0 sec" = "0 sek";
/* No comment provided by engineer. */
"0s" = "0s";
@ -371,6 +395,9 @@
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Alle Nachrichten werden gelöscht - dies kann nicht rückgängig gemacht werden! Die Nachrichten werden NUR bei Ihnen gelöscht.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Alle neuen Nachrichten von %@ werden verborgen!";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Alle Ihre Kontakte bleiben verbunden.";
@ -434,6 +461,12 @@
/* No comment provided by engineer. */
"Already connected?" = "Sind Sie bereits verbunden?";
/* No comment provided by engineer. */
"Already connecting!" = "Bereits verbunden!";
/* No comment provided by engineer. */
"Already joining the group!" = "Sie sind bereits Mitglied der Gruppe!";
/* pref value */
"always" = "Immer";
@ -443,6 +476,9 @@
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Es wurde ein leeres Chat-Profil mit dem eingegebenen Namen erstellt und die App öffnet wie gewohnt.";
/* No comment provided by engineer. */
"and %lld other events" = "und %lld weitere Ereignisse";
/* No comment provided by engineer. */
"Answer call" = "Anruf annehmen";
@ -527,6 +563,18 @@
/* No comment provided by engineer. */
"Better messages" = "Verbesserungen bei Nachrichten";
/* No comment provided by engineer. */
"Block" = "Blockieren";
/* No comment provided by engineer. */
"Block member" = "Mitglied blockieren";
/* No comment provided by engineer. */
"Block member?" = "Mitglied blockieren?";
/* No comment provided by engineer. */
"blocked" = "blockiert";
/* No comment provided by engineer. */
"bold" = "fett";
@ -726,6 +774,18 @@
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "Mit den SimpleX Chat-Entwicklern verbinden.";
/* No comment provided by engineer. */
"Connect to yourself?" = "Mit Ihnen selbst verbinden?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Mit Ihnen selbst verbinden?\nDas ist Ihr eigener Einmal-Link!";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Mit Ihnen selbst verbinden?\nDas ist Ihre eigene SimpleX-Adresse!";
/* No comment provided by engineer. */
"Connect via contact address" = "Über die Kontakt-Adresse verbinden";
/* No comment provided by engineer. */
"Connect via link" = "Über einen Link verbinden";
@ -735,6 +795,9 @@
/* No comment provided by engineer. */
"Connect via one-time link" = "Über einen Einmal-Link verbinden";
/* No comment provided by engineer. */
"Connect with %@" = "Mit %@ verbinden";
/* No comment provided by engineer. */
"connected" = "Verbunden";
@ -831,6 +894,9 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Core Version: v%@";
/* No comment provided by engineer. */
"Correct name to %@?" = "Richtiger Name für %@?";
/* No comment provided by engineer. */
"Create" = "Erstellen";
@ -840,6 +906,9 @@
/* server test step */
"Create file" = "Datei erstellen";
/* No comment provided by engineer. */
"Create group" = "Gruppe erstellen";
/* No comment provided by engineer. */
"Create group link" = "Gruppenlink erstellen";
@ -852,6 +921,9 @@
/* No comment provided by engineer. */
"Create one-time invitation link" = "Einmal-Einladungslink erstellen";
/* No comment provided by engineer. */
"Create profile" = "Profil erstellen";
/* server test step */
"Create queue" = "Erzeuge Warteschlange";
@ -966,6 +1038,9 @@
/* chat item action */
"Delete" = "Löschen";
/* No comment provided by engineer. */
"Delete %lld messages?" = "%lld Nachrichten löschen?";
/* No comment provided by engineer. */
"Delete address" = "Adresse löschen";
@ -978,6 +1053,9 @@
/* No comment provided by engineer. */
"Delete all files" = "Alle Dateien löschen";
/* No comment provided by engineer. */
"Delete and notify contact" = "Kontakt löschen und benachrichtigen";
/* No comment provided by engineer. */
"Delete archive" = "Archiv löschen";
@ -999,6 +1077,9 @@
/* No comment provided by engineer. */
"Delete Contact" = "Kontakt löschen";
/* No comment provided by engineer. */
"Delete contact?\nThis cannot be undone!" = "Kontakt löschen?\nDas kann nicht rückgängig gemacht werden!";
/* No comment provided by engineer. */
"Delete database" = "Datenbank löschen";
@ -1074,6 +1155,9 @@
/* copied message info */
"Deleted at: %@" = "Gelöscht um: %@";
/* rcv direct event chat item */
"deleted contact" = "Gelöschter Kontakt";
/* rcv group event chat item */
"deleted group" = "Gruppe gelöscht";
@ -1305,6 +1389,9 @@
/* No comment provided by engineer. */
"Enter correct passphrase." = "Geben Sie das korrekte Passwort ein.";
/* No comment provided by engineer. */
"Enter group name…" = "Geben Sie den Gruppennamen ein…";
/* No comment provided by engineer. */
"Enter Passcode" = "Zugangscode eingeben";
@ -1323,6 +1410,9 @@
/* placeholder */
"Enter welcome message… (optional)" = "Geben Sie eine Begrüßungsmeldung ein … (optional)";
/* No comment provided by engineer. */
"Enter your name…" = "Geben Sie Ihren Namen ein…";
/* No comment provided by engineer. */
"error" = "Fehler";
@ -1494,6 +1584,9 @@
/* No comment provided by engineer. */
"Exit without saving" = "Beenden ohne Speichern";
/* chat item action */
"Expand" = "Erweitern";
/* No comment provided by engineer. */
"Export database" = "Datenbank exportieren";
@ -1581,6 +1674,9 @@
/* No comment provided by engineer. */
"Full name:" = "Vollständiger Name:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Vollständig dezentralisiert nur für Mitglieder sichtbar.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Komplett neu umgesetzt - arbeitet nun im Hintergrund!";
@ -1593,6 +1689,12 @@
/* No comment provided by engineer. */
"Group" = "Gruppe";
/* No comment provided by engineer. */
"Group already exists" = "Die Gruppe besteht bereits";
/* No comment provided by engineer. */
"Group already exists!" = "Die Gruppe besteht bereits!";
/* No comment provided by engineer. */
"group deleted" = "Gruppe gelöscht";
@ -1830,6 +1932,9 @@
/* invalid chat item */
"invalid data" = "Ungültige Daten";
/* No comment provided by engineer. */
"Invalid name!" = "Ungültiger Name!";
/* No comment provided by engineer. */
"Invalid server address!" = "Ungültige Serveradresse!";
@ -1888,7 +1993,7 @@
"It can happen when:\n1. The messages expired in the sending client after 2 days or on the server after 30 days.\n2. Message decryption failed, because you or your contact used old database backup.\n3. The connection was compromised." = "Dies kann unter folgenden Umständen passieren:\n1. Die Nachrichten verfallen auf dem sendenden Client-System nach 2 Tagen oder auf dem Server nach 30 Tagen.\n2. Die Nachrichten-Entschlüsselung ist fehlgeschlagen, da von Ihnen oder Ihrem Kontakt ein altes Datenbank-Backup genutzt wurde.\n3. Die Verbindung wurde kompromittiert.";
/* No comment provided by engineer. */
"It seems like you are already connected via this link. If it is not the case, there was an error (%@)." = "Es sieht so aus, dass Sie bereits über diesen Link verbunden sind. Wenn das nicht der Fall, gab es einen Fehler (%@).";
"It seems like you are already connected via this link. If it is not the case, there was an error (%@)." = "Es sieht so aus, als ob Sie bereits über diesen Link verbunden sind. Wenn das nicht der Fall ist, gab es einen Fehler (%@).";
/* No comment provided by engineer. */
"Italian interface" = "Italienische Bedienoberfläche";
@ -1908,9 +2013,18 @@
/* No comment provided by engineer. */
"Join group" = "Treten Sie der Gruppe bei";
/* No comment provided by engineer. */
"Join group?" = "Der Gruppe beitreten?";
/* No comment provided by engineer. */
"Join incognito" = "Inkognito beitreten";
/* No comment provided by engineer. */
"Join with current profile" = "Mit dem aktuellen Profil beitreten";
/* No comment provided by engineer. */
"Join your group?\nThis is your link for group %@!" = "Ihrer Gruppe beitreten?\nDas ist Ihr Link für die Gruppe %@!";
/* No comment provided by engineer. */
"Joining group" = "Der Gruppe beitreten";
@ -2055,6 +2169,9 @@
/* No comment provided by engineer. */
"Messages & files" = "Nachrichten";
/* No comment provided by engineer. */
"Messages from %@ will be shown!" = "Die Nachrichten von %@ werden angezeigt!";
/* No comment provided by engineer. */
"Migrating database archive…" = "Datenbank-Archiv wird migriert…";
@ -2306,6 +2423,9 @@
/* authentication reason */
"Open chat console" = "Chat-Konsole öffnen";
/* No comment provided by engineer. */
"Open group" = "Gruppe öffnen";
/* No comment provided by engineer. */
"Open Settings" = "Geräte-Einstellungen öffnen";
@ -2438,6 +2558,12 @@
/* No comment provided by engineer. */
"Profile image" = "Profilbild";
/* No comment provided by engineer. */
"Profile name" = "Profilname";
/* No comment provided by engineer. */
"Profile name:" = "Profilname:";
/* No comment provided by engineer. */
"Profile password" = "Passwort für Profil";
@ -2603,6 +2729,12 @@
/* No comment provided by engineer. */
"Renegotiate encryption?" = "Verschlüsselung neu aushandeln?";
/* No comment provided by engineer. */
"Repeat connection request?" = "Verbindungsanfrage wiederholen?";
/* No comment provided by engineer. */
"Repeat join request?" = "Verbindungsanfrage wiederholen?";
/* chat item action */
"Reply" = "Antwort";
@ -3044,6 +3176,9 @@
/* No comment provided by engineer. */
"Tap to activate profile." = "Tippen Sie auf das Profil um es zu aktivieren.";
/* No comment provided by engineer. */
"Tap to Connect" = "Zum Verbinden antippen";
/* No comment provided by engineer. */
"Tap to join" = "Zum Beitreten tippen";
@ -3170,6 +3305,12 @@
/* No comment provided by engineer. */
"This group no longer exists." = "Diese Gruppe existiert nicht mehr.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "Das ist Ihr eigener Einmal-Link!";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Das ist Ihre eigene SimpleX-Adresse!";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Diese Einstellung gilt für Nachrichten in Ihrem aktuellen Chat-Profil **%@**.";
@ -3195,7 +3336,7 @@
"To record voice message please grant permission to use Microphone." = "Bitte erlauben Sie die Nutzung des Mikrofons, um Sprachnachrichten aufnehmen zu können.";
/* No comment provided by engineer. */
"To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." = "Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite **Meine Chat-Profile** ein, um Ihr verborgenes Profil zu sehen.";
"To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." = "Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite **Ihre Chat-Profile** ein, um Ihr verborgenes Profil zu sehen.";
/* No comment provided by engineer. */
"To support instant push notifications the chat database has to be migrated." = "Um sofortige Push-Benachrichtigungen zu unterstützen, muss die Chat-Datenbank migriert werden.";
@ -3227,6 +3368,15 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Die Aufnahme einer Sprachnachricht ist nicht möglich";
/* No comment provided by engineer. */
"Unblock" = "Freigeben";
/* No comment provided by engineer. */
"Unblock member" = "Mitglied freigeben";
/* No comment provided by engineer. */
"Unblock member?" = "Mitglied freigeben?";
/* item status description */
"Unexpected error: %@" = "Unerwarteter Fehler: %@";
@ -3459,7 +3609,7 @@
"yes" = "Ja";
/* No comment provided by engineer. */
"You" = "Meine Daten";
"You" = "Ihre Daten";
/* No comment provided by engineer. */
"You accepted connection" = "Sie haben die Verbindung akzeptiert";
@ -3473,6 +3623,27 @@
/* No comment provided by engineer. */
"You are already connected to %@." = "Sie sind bereits mit %@ verbunden.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "Sie sind bereits mit %@ verbunden.";
/* No comment provided by engineer. */
"You are already connecting via this one-time link!" = "Sie sind bereits über diesen Einmal-Link verbunden!";
/* No comment provided by engineer. */
"You are already in group %@." = "Sie sind bereits Mitglied der Gruppe %@.";
/* No comment provided by engineer. */
"You are already joining the group %@." = "Sie sind bereits Mitglied der Gruppe %@.";
/* No comment provided by engineer. */
"You are already joining the group via this link!" = "Sie sind über diesen Link bereits Mitglied der Gruppe!";
/* No comment provided by engineer. */
"You are already joining the group via this link." = "Sie sind über diesen Link bereits Mitglied der Gruppe.";
/* No comment provided by engineer. */
"You are already joining the group!\nRepeat join request?" = "Sie sind bereits Mitglied dieser Gruppe!\nVerbindungsanfrage wiederholen?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "Sie sind mit dem Server verbunden, der für den Empfang von Nachrichten mit diesem Kontakt genutzt wird.";
@ -3548,6 +3719,12 @@
/* No comment provided by engineer. */
"You could not be verified; please try again." = "Sie konnten nicht überprüft werden; bitte versuchen Sie es erneut.";
/* No comment provided by engineer. */
"You have already requested connection via this address!" = "Sie haben über diese Adresse bereits eine Verbindung beantragt!";
/* No comment provided by engineer. */
"You have already requested connection!\nRepeat connection request?" = "Sie haben bereits ein Verbindungsanfrage beantragt!\nVerbindungsanfrage wiederholen?";
/* No comment provided by engineer. */
"You have no chats" = "Sie haben keine Chats";
@ -3590,6 +3767,9 @@
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Sie werden mit der Gruppe verbunden, sobald das Endgerät des Gruppen-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach!";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "Sie werden verbunden, sobald das Endgerät des Gruppenlink-Hosts online ist. Bitte warten oder schauen Sie später nochmal nach!";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "Sie werden verbunden, sobald Ihre Verbindungsanfrage akzeptiert wird. Bitte warten oder schauen Sie später nochmal nach!";
@ -3599,6 +3779,9 @@
/* No comment provided by engineer. */
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Sie müssen sich authentifizieren, wenn Sie die im Hintergrund befindliche App nach 30 Sekunden starten oder fortsetzen.";
/* No comment provided by engineer. */
"You will connect to all group members." = "Sie werden mit allen Gruppenmitgliedern verbunden.";
/* No comment provided by engineer. */
"You will still receive calls and notifications from muted profiles when they are active." = "Sie können Anrufe und Benachrichtigungen auch von stummgeschalteten Profilen empfangen, solange diese aktiv sind.";
@ -3630,7 +3813,7 @@
"Your chat database is not encrypted - set passphrase to encrypt it." = "Ihre Chat-Datenbank ist nicht verschlüsselt. Bitte legen Sie ein Passwort fest, um sie zu schützen.";
/* No comment provided by engineer. */
"Your chat profiles" = "Meine Chat-Profile";
"Your chat profiles" = "Ihre Chat-Profile";
/* No comment provided by engineer. */
"Your contact needs to be online for the connection to complete.\nYou can cancel this connection and remove the contact (and try later with a new link)." = "Damit die Verbindung hergestellt werden kann, muss Ihr Kontakt online sein.\nSie können diese Verbindung abbrechen und den Kontakt entfernen (und es später nochmals mit einem neuen Link versuchen).";
@ -3657,10 +3840,13 @@
"Your ICE servers" = "Ihre ICE-Server";
/* No comment provided by engineer. */
"Your preferences" = "Meine Präferenzen";
"Your preferences" = "Ihre Präferenzen";
/* No comment provided by engineer. */
"Your privacy" = "Meine Privatsphäre";
"Your privacy" = "Ihre Privatsphäre";
/* No comment provided by engineer. */
"Your profile" = "Mein Profil";
/* No comment provided by engineer. */
"Your profile **%@** will be shared." = "Ihr Profil **%@** wird geteilt.";
@ -3681,10 +3867,10 @@
"Your server address" = "Ihre Serveradresse";
/* No comment provided by engineer. */
"Your settings" = "Meine Einstellungen";
"Your settings" = "Ihre Einstellungen";
/* No comment provided by engineer. */
"Your SimpleX address" = "Meine SimpleX-Adresse";
"Your SimpleX address" = "Ihre SimpleX-Adresse";
/* No comment provided by engineer. */
"Your SMP servers" = "Ihre SMP-Server";

View File

@ -118,12 +118,18 @@
/* No comment provided by engineer. */
"%@ %@" = "%@ %@";
/* No comment provided by engineer. */
"%@ and %@" = "%@ et %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ et %@ sont connecté.es";
/* copied message info, <sender> at <time> */
"%@ at %@:" = "%1$@ à %2$@:";
/* No comment provided by engineer. */
"%@ connected" = "%@ connecté(e)";
/* notification title */
"%@ is connected!" = "%@ est connecté·e !";
@ -139,6 +145,9 @@
/* notification title */
"%@ wants to connect!" = "%@ veut se connecter !";
/* No comment provided by engineer. */
"%@, %@ and %lld members" = "%@, %@ et %lld membres";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ et %lld autres membres sont connectés";
@ -178,9 +187,21 @@
/* No comment provided by engineer. */
"%lld file(s) with total size of %@" = "%lld fichier·s pour une taille totale de %@";
/* No comment provided by engineer. */
"%lld group events" = "%lld événements de groupe";
/* No comment provided by engineer. */
"%lld members" = "%lld membres";
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld messages bloqués";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld messages marqués comme supprimés";
/* No comment provided by engineer. */
"%lld messages moderated by %@" = "%lld messages modérés par %@";
/* No comment provided by engineer. */
"%lld minutes" = "%lld minutes";
@ -229,6 +250,9 @@
/* No comment provided by engineer. */
"~strike~" = "\\~barré~";
/* time to disappear */
"0 sec" = "0 sec";
/* No comment provided by engineer. */
"0s" = "0s";
@ -371,6 +395,9 @@
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Tous les messages seront supprimés - impossible de revenir en arrière ! Les messages seront supprimés UNIQUEMENT pour vous.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Tous les nouveaux messages de %@ seront cachés !";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Tous vos contacts resteront connectés.";
@ -434,6 +461,12 @@
/* No comment provided by engineer. */
"Already connected?" = "Déjà connecté ?";
/* No comment provided by engineer. */
"Already connecting!" = "Déjà en connexion !";
/* No comment provided by engineer. */
"Already joining the group!" = "Groupe déjà rejoint !";
/* pref value */
"always" = "toujours";
@ -443,6 +476,9 @@
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Un profil de chat vierge portant le nom fourni est créé et l'application s'ouvre normalement.";
/* No comment provided by engineer. */
"and %lld other events" = "et %lld autres événements";
/* No comment provided by engineer. */
"Answer call" = "Répondre à l'appel";
@ -527,6 +563,18 @@
/* No comment provided by engineer. */
"Better messages" = "Meilleurs messages";
/* No comment provided by engineer. */
"Block" = "Bloquer";
/* No comment provided by engineer. */
"Block member" = "Bloquer ce membre";
/* No comment provided by engineer. */
"Block member?" = "Bloquer ce membre ?";
/* No comment provided by engineer. */
"blocked" = "blocké";
/* No comment provided by engineer. */
"bold" = "gras";
@ -726,6 +774,18 @@
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "se connecter aux developpeurs de SimpleX Chat.";
/* No comment provided by engineer. */
"Connect to yourself?" = "Se connecter à soi-même ?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Se connecter à soi-même ?\nIl s'agit de votre propre lien unique !";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Se connecter à soi-même ?\nC'est votre propre adresse SimpleX !";
/* No comment provided by engineer. */
"Connect via contact address" = "Se connecter via l'adresse de contact";
/* No comment provided by engineer. */
"Connect via link" = "Se connecter via un lien";
@ -735,6 +795,9 @@
/* No comment provided by engineer. */
"Connect via one-time link" = "Se connecter via un lien unique";
/* No comment provided by engineer. */
"Connect with %@" = "Se connecter avec %@";
/* No comment provided by engineer. */
"connected" = "connecté";
@ -831,6 +894,9 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Version du cœur : v%@";
/* No comment provided by engineer. */
"Correct name to %@?" = "Corriger le nom pour %@ ?";
/* No comment provided by engineer. */
"Create" = "Créer";
@ -840,6 +906,9 @@
/* server test step */
"Create file" = "Créer un fichier";
/* No comment provided by engineer. */
"Create group" = "Créer un groupe";
/* No comment provided by engineer. */
"Create group link" = "Créer un lien de groupe";
@ -852,6 +921,9 @@
/* No comment provided by engineer. */
"Create one-time invitation link" = "Créer un lien d'invitation unique";
/* No comment provided by engineer. */
"Create profile" = "Créer le profil";
/* server test step */
"Create queue" = "Créer une file d'attente";
@ -966,6 +1038,9 @@
/* chat item action */
"Delete" = "Supprimer";
/* No comment provided by engineer. */
"Delete %lld messages?" = "Supprimer %lld messages ?";
/* No comment provided by engineer. */
"Delete address" = "Supprimer l'adresse";
@ -978,6 +1053,9 @@
/* No comment provided by engineer. */
"Delete all files" = "Effacer tous les fichiers";
/* No comment provided by engineer. */
"Delete and notify contact" = "Supprimer et en informer le contact";
/* No comment provided by engineer. */
"Delete archive" = "Supprimer l'archive";
@ -999,6 +1077,9 @@
/* No comment provided by engineer. */
"Delete Contact" = "Supprimer le contact";
/* No comment provided by engineer. */
"Delete contact?\nThis cannot be undone!" = "Supprimer le contact ?\nCette opération ne peut être annulée !";
/* No comment provided by engineer. */
"Delete database" = "Supprimer la base de données";
@ -1074,6 +1155,9 @@
/* copied message info */
"Deleted at: %@" = "Supprimé à : %@";
/* rcv direct event chat item */
"deleted contact" = "contact supprimé";
/* rcv group event chat item */
"deleted group" = "groupe supprimé";
@ -1305,6 +1389,9 @@
/* No comment provided by engineer. */
"Enter correct passphrase." = "Entrez la phrase secrète correcte.";
/* No comment provided by engineer. */
"Enter group name…" = "Entrer un nom de groupe…";
/* No comment provided by engineer. */
"Enter Passcode" = "Entrer le code d'accès";
@ -1323,6 +1410,9 @@
/* placeholder */
"Enter welcome message… (optional)" = "Entrez un message de bienvenue… (facultatif)";
/* No comment provided by engineer. */
"Enter your name…" = "Entrez votre nom…";
/* No comment provided by engineer. */
"error" = "erreur";
@ -1494,6 +1584,9 @@
/* No comment provided by engineer. */
"Exit without saving" = "Quitter sans sauvegarder";
/* chat item action */
"Expand" = "Développer";
/* No comment provided by engineer. */
"Export database" = "Exporter la base de données";
@ -1581,6 +1674,9 @@
/* No comment provided by engineer. */
"Full name:" = "Nom complet :";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Entièrement décentralisé visible que par ses membres.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Entièrement réimplémenté - fonctionne en arrière-plan !";
@ -1593,6 +1689,12 @@
/* No comment provided by engineer. */
"Group" = "Groupe";
/* No comment provided by engineer. */
"Group already exists" = "Le groupe existe déjà";
/* No comment provided by engineer. */
"Group already exists!" = "Ce groupe existe déjà !";
/* No comment provided by engineer. */
"group deleted" = "groupe supprimé";
@ -1830,6 +1932,9 @@
/* invalid chat item */
"invalid data" = "données invalides";
/* No comment provided by engineer. */
"Invalid name!" = "Nom invalide !";
/* No comment provided by engineer. */
"Invalid server address!" = "Adresse de serveur invalide !";
@ -1908,9 +2013,18 @@
/* No comment provided by engineer. */
"Join group" = "Rejoindre le groupe";
/* No comment provided by engineer. */
"Join group?" = "Rejoindre le groupe ?";
/* No comment provided by engineer. */
"Join incognito" = "Rejoindre en incognito";
/* No comment provided by engineer. */
"Join with current profile" = "Rejoindre avec le profil actuel";
/* No comment provided by engineer. */
"Join your group?\nThis is your link for group %@!" = "Rejoindre votre groupe ?\nVoici votre lien pour le groupe %@ !";
/* No comment provided by engineer. */
"Joining group" = "Entrain de rejoindre le groupe";
@ -2055,6 +2169,9 @@
/* No comment provided by engineer. */
"Messages & files" = "Messages";
/* No comment provided by engineer. */
"Messages from %@ will be shown!" = "Les messages de %@ seront affichés !";
/* No comment provided by engineer. */
"Migrating database archive…" = "Migration de l'archive de la base de données…";
@ -2306,6 +2423,9 @@
/* authentication reason */
"Open chat console" = "Ouvrir la console du chat";
/* No comment provided by engineer. */
"Open group" = "Ouvrir le groupe";
/* No comment provided by engineer. */
"Open Settings" = "Ouvrir les Paramètres";
@ -2438,6 +2558,12 @@
/* No comment provided by engineer. */
"Profile image" = "Image de profil";
/* No comment provided by engineer. */
"Profile name" = "Nom du profil";
/* No comment provided by engineer. */
"Profile name:" = "Nom du profil :";
/* No comment provided by engineer. */
"Profile password" = "Mot de passe de profil";
@ -2603,6 +2729,12 @@
/* No comment provided by engineer. */
"Renegotiate encryption?" = "Renégocier le chiffrement?";
/* No comment provided by engineer. */
"Repeat connection request?" = "Répéter la demande de connexion ?";
/* No comment provided by engineer. */
"Repeat join request?" = "Répéter la requête d'adhésion ?";
/* chat item action */
"Reply" = "Répondre";
@ -3044,6 +3176,9 @@
/* No comment provided by engineer. */
"Tap to activate profile." = "Appuyez pour activer un profil.";
/* No comment provided by engineer. */
"Tap to Connect" = "Tapez pour vous connecter";
/* No comment provided by engineer. */
"Tap to join" = "Appuyez pour rejoindre";
@ -3170,6 +3305,12 @@
/* No comment provided by engineer. */
"This group no longer exists." = "Ce groupe n'existe plus.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "Voici votre propre lien unique !";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Voici votre propre adresse SimpleX !";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Ce paramètre s'applique aux messages de votre profil de chat actuel **%@**.";
@ -3227,6 +3368,15 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Impossible d'enregistrer un message vocal";
/* No comment provided by engineer. */
"Unblock" = "Débloquer";
/* No comment provided by engineer. */
"Unblock member" = "Débloquer ce membre";
/* No comment provided by engineer. */
"Unblock member?" = "Débloquer ce membre ?";
/* item status description */
"Unexpected error: %@" = "Erreur inattendue: %@";
@ -3473,6 +3623,27 @@
/* No comment provided by engineer. */
"You are already connected to %@." = "Vous êtes déjà connecté·e à %@ via ce lien.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "Vous êtes déjà en train de vous connecter à %@.";
/* No comment provided by engineer. */
"You are already connecting via this one-time link!" = "Vous êtes déjà connecté(e) via ce lien unique !";
/* No comment provided by engineer. */
"You are already in group %@." = "Vous êtes déjà dans le groupe %@.";
/* No comment provided by engineer. */
"You are already joining the group %@." = "Vous êtes déjà en train de rejoindre le groupe %@.";
/* No comment provided by engineer. */
"You are already joining the group via this link!" = "Vous êtes déjà en train de rejoindre le groupe via ce lien !";
/* No comment provided by engineer. */
"You are already joining the group via this link." = "Vous êtes déjà en train de rejoindre le groupe via ce lien.";
/* No comment provided by engineer. */
"You are already joining the group!\nRepeat join request?" = "Vous êtes déjà membre de ce groupe !\nRépéter la demande d'adhésion ?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "Vous êtes connecté·e au serveur utilisé pour recevoir les messages de ce contact.";
@ -3548,6 +3719,12 @@
/* No comment provided by engineer. */
"You could not be verified; please try again." = "Vous n'avez pas pu être vérifié·e; veuillez réessayer.";
/* No comment provided by engineer. */
"You have already requested connection via this address!" = "Vous avez déjà demandé une connexion via cette adresse !";
/* No comment provided by engineer. */
"You have already requested connection!\nRepeat connection request?" = "Vous avez déjà demandé une connexion !\nRépéter la demande de connexion ?";
/* No comment provided by engineer. */
"You have no chats" = "Vous n'avez aucune discussion";
@ -3590,6 +3767,9 @@
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Vous serez connecté·e au groupe lorsque l'appareil de l'hôte sera en ligne, veuillez attendre ou vérifier plus tard !";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "Vous serez connecté(e) lorsque l'appareil de l'hôte du lien de groupe sera en ligne, veuillez patienter ou vérifier plus tard !";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "Vous serez connecté·e lorsque votre demande de connexion sera acceptée, veuillez attendre ou vérifier plus tard !";
@ -3599,6 +3779,9 @@
/* No comment provided by engineer. */
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Il vous sera demandé de vous authentifier lorsque vous démarrez ou reprenez l'application après 30 secondes en arrière-plan.";
/* No comment provided by engineer. */
"You will connect to all group members." = "Vous vous connecterez à tous les membres du groupe.";
/* No comment provided by engineer. */
"You will still receive calls and notifications from muted profiles when they are active." = "Vous continuerez à recevoir des appels et des notifications des profils mis en sourdine lorsqu'ils sont actifs.";
@ -3662,6 +3845,9 @@
/* No comment provided by engineer. */
"Your privacy" = "Votre vie privée";
/* No comment provided by engineer. */
"Your profile" = "Votre profil";
/* No comment provided by engineer. */
"Your profile **%@** will be shared." = "Votre profil **%@** sera partagé.";

View File

@ -118,12 +118,18 @@
/* No comment provided by engineer. */
"%@ %@" = "%@ %@";
/* No comment provided by engineer. */
"%@ and %@" = "%@ e %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ e %@ sono connessi/e";
/* copied message info, <sender> at <time> */
"%@ at %@:" = "%1$@ alle %2$@:";
/* No comment provided by engineer. */
"%@ connected" = "%@ si è connesso/a";
/* notification title */
"%@ is connected!" = "%@ è connesso/a!";
@ -139,6 +145,9 @@
/* notification title */
"%@ wants to connect!" = "%@ si vuole connettere!";
/* No comment provided by engineer. */
"%@, %@ and %lld members" = "%@, %@ e %lld membri";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ e altri %lld membri sono connessi";
@ -178,9 +187,21 @@
/* No comment provided by engineer. */
"%lld file(s) with total size of %@" = "%lld file con dimensione totale di %@";
/* No comment provided by engineer. */
"%lld group events" = "%lld eventi del gruppo";
/* No comment provided by engineer. */
"%lld members" = "%lld membri";
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld messaggi bloccati";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld messaggi contrassegnati eliminati";
/* No comment provided by engineer. */
"%lld messages moderated by %@" = "%lld messaggi moderati da %@";
/* No comment provided by engineer. */
"%lld minutes" = "%lld minuti";
@ -229,6 +250,9 @@
/* No comment provided by engineer. */
"~strike~" = "\\~barrato~";
/* time to disappear */
"0 sec" = "0 sec";
/* No comment provided by engineer. */
"0s" = "0s";
@ -371,6 +395,9 @@
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Tutti i messaggi verranno eliminati, non è reversibile! I messaggi verranno eliminati SOLO per te.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Tutti i nuovi messaggi da %@ verrranno nascosti!";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Tutti i tuoi contatti resteranno connessi.";
@ -434,6 +461,12 @@
/* No comment provided by engineer. */
"Already connected?" = "Già connesso/a?";
/* No comment provided by engineer. */
"Already connecting!" = "Già in connessione!";
/* No comment provided by engineer. */
"Already joining the group!" = "Già in ingresso nel gruppo!";
/* pref value */
"always" = "sempre";
@ -443,6 +476,9 @@
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Viene creato un profilo di chat vuoto con il nome scelto e l'app si apre come al solito.";
/* No comment provided by engineer. */
"and %lld other events" = "e altri %lld eventi";
/* No comment provided by engineer. */
"Answer call" = "Rispondi alla chiamata";
@ -527,6 +563,18 @@
/* No comment provided by engineer. */
"Better messages" = "Messaggi migliorati";
/* No comment provided by engineer. */
"Block" = "Blocca";
/* No comment provided by engineer. */
"Block member" = "Blocca membro";
/* No comment provided by engineer. */
"Block member?" = "Bloccare il membro?";
/* No comment provided by engineer. */
"blocked" = "bloccato";
/* No comment provided by engineer. */
"bold" = "grassetto";
@ -622,7 +670,7 @@
"changed address for you" = "indirizzo cambiato per te";
/* rcv group event chat item */
"changed role of %@ to %@" = "cambiato il ruolo di %1$@ in %2$@";
"changed role of %@ to %@" = "ha cambiato il ruolo di %1$@ in %2$@";
/* rcv group event chat item */
"changed your role to %@" = "cambiato il tuo ruolo in %@";
@ -726,6 +774,18 @@
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "connettiti agli sviluppatori di SimpleX Chat.";
/* No comment provided by engineer. */
"Connect to yourself?" = "Connettersi a te stesso?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Connettersi a te stesso?\nQuesto è il tuo link una tantum!";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Connettersi a te stesso?\nQuesto è il tuo indirizzo SimpleX!";
/* No comment provided by engineer. */
"Connect via contact address" = "Connettere via indirizzo del contatto";
/* No comment provided by engineer. */
"Connect via link" = "Connetti via link";
@ -735,6 +795,9 @@
/* No comment provided by engineer. */
"Connect via one-time link" = "Connetti via link una tantum";
/* No comment provided by engineer. */
"Connect with %@" = "Connettersi con %@";
/* No comment provided by engineer. */
"connected" = "connesso/a";
@ -831,6 +894,9 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Versione core: v%@";
/* No comment provided by engineer. */
"Correct name to %@?" = "Correggere il nome a %@?";
/* No comment provided by engineer. */
"Create" = "Crea";
@ -840,6 +906,9 @@
/* server test step */
"Create file" = "Crea file";
/* No comment provided by engineer. */
"Create group" = "Crea gruppo";
/* No comment provided by engineer. */
"Create group link" = "Crea link del gruppo";
@ -852,6 +921,9 @@
/* No comment provided by engineer. */
"Create one-time invitation link" = "Crea link di invito una tantum";
/* No comment provided by engineer. */
"Create profile" = "Crea profilo";
/* server test step */
"Create queue" = "Crea coda";
@ -966,6 +1038,9 @@
/* chat item action */
"Delete" = "Elimina";
/* No comment provided by engineer. */
"Delete %lld messages?" = "Eliminare %lld messaggi?";
/* No comment provided by engineer. */
"Delete address" = "Elimina indirizzo";
@ -978,6 +1053,9 @@
/* No comment provided by engineer. */
"Delete all files" = "Elimina tutti i file";
/* No comment provided by engineer. */
"Delete and notify contact" = "Elimina e avvisa il contatto";
/* No comment provided by engineer. */
"Delete archive" = "Elimina archivio";
@ -999,6 +1077,9 @@
/* No comment provided by engineer. */
"Delete Contact" = "Elimina contatto";
/* No comment provided by engineer. */
"Delete contact?\nThis cannot be undone!" = "Eliminare il contatto?\nNon è reversibile!";
/* No comment provided by engineer. */
"Delete database" = "Elimina database";
@ -1074,6 +1155,9 @@
/* copied message info */
"Deleted at: %@" = "Eliminato il: %@";
/* rcv direct event chat item */
"deleted contact" = "contatto eliminato";
/* rcv group event chat item */
"deleted group" = "gruppo eliminato";
@ -1305,6 +1389,9 @@
/* No comment provided by engineer. */
"Enter correct passphrase." = "Inserisci la password giusta.";
/* No comment provided by engineer. */
"Enter group name…" = "Inserisci il nome del gruppo…";
/* No comment provided by engineer. */
"Enter Passcode" = "Inserisci il codice di accesso";
@ -1323,6 +1410,9 @@
/* placeholder */
"Enter welcome message… (optional)" = "Inserisci il messaggio di benvenuto… (facoltativo)";
/* No comment provided by engineer. */
"Enter your name…" = "Inserisci il tuo nome…";
/* No comment provided by engineer. */
"error" = "errore";
@ -1494,6 +1584,9 @@
/* No comment provided by engineer. */
"Exit without saving" = "Esci senza salvare";
/* chat item action */
"Expand" = "Espandi";
/* No comment provided by engineer. */
"Export database" = "Esporta database";
@ -1581,6 +1674,9 @@
/* No comment provided by engineer. */
"Full name:" = "Nome completo:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Completamente decentralizzato: visibile solo ai membri.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Completamente reimplementato - funziona in secondo piano!";
@ -1593,6 +1689,12 @@
/* No comment provided by engineer. */
"Group" = "Gruppo";
/* No comment provided by engineer. */
"Group already exists" = "Il gruppo esiste già";
/* No comment provided by engineer. */
"Group already exists!" = "Il gruppo esiste già!";
/* No comment provided by engineer. */
"group deleted" = "gruppo eliminato";
@ -1830,6 +1932,9 @@
/* invalid chat item */
"invalid data" = "dati non validi";
/* No comment provided by engineer. */
"Invalid name!" = "Nome non valido!";
/* No comment provided by engineer. */
"Invalid server address!" = "Indirizzo del server non valido!";
@ -1908,9 +2013,18 @@
/* No comment provided by engineer. */
"Join group" = "Entra nel gruppo";
/* No comment provided by engineer. */
"Join group?" = "Entrare nel gruppo?";
/* No comment provided by engineer. */
"Join incognito" = "Entra in incognito";
/* No comment provided by engineer. */
"Join with current profile" = "Entra con il profilo attuale";
/* No comment provided by engineer. */
"Join your group?\nThis is your link for group %@!" = "Entrare nel tuo gruppo?\nQuesto è il tuo link per il gruppo %@!";
/* No comment provided by engineer. */
"Joining group" = "Ingresso nel gruppo";
@ -2055,6 +2169,9 @@
/* No comment provided by engineer. */
"Messages & files" = "Messaggi";
/* No comment provided by engineer. */
"Messages from %@ will be shown!" = "I messaggi da %@ verranno mostrati!";
/* No comment provided by engineer. */
"Migrating database archive…" = "Migrazione archivio del database…";
@ -2306,6 +2423,9 @@
/* authentication reason */
"Open chat console" = "Apri la console della chat";
/* No comment provided by engineer. */
"Open group" = "Apri gruppo";
/* No comment provided by engineer. */
"Open Settings" = "Apri le impostazioni";
@ -2438,6 +2558,12 @@
/* No comment provided by engineer. */
"Profile image" = "Immagine del profilo";
/* No comment provided by engineer. */
"Profile name" = "Nome del profilo";
/* No comment provided by engineer. */
"Profile name:" = "Nome del profilo:";
/* No comment provided by engineer. */
"Profile password" = "Password del profilo";
@ -2603,6 +2729,12 @@
/* No comment provided by engineer. */
"Renegotiate encryption?" = "Rinegoziare la crittografia?";
/* No comment provided by engineer. */
"Repeat connection request?" = "Ripetere la richiesta di connessione?";
/* No comment provided by engineer. */
"Repeat join request?" = "Ripetere la richiesta di ingresso?";
/* chat item action */
"Reply" = "Rispondi";
@ -3044,6 +3176,9 @@
/* No comment provided by engineer. */
"Tap to activate profile." = "Tocca per attivare il profilo.";
/* No comment provided by engineer. */
"Tap to Connect" = "Tocca per connettere";
/* No comment provided by engineer. */
"Tap to join" = "Tocca per entrare";
@ -3170,6 +3305,12 @@
/* No comment provided by engineer. */
"This group no longer exists." = "Questo gruppo non esiste più.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "Questo è il tuo link una tantum!";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Questo è il tuo indirizzo SimpleX!";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Questa impostazione si applica ai messaggi del profilo di chat attuale **%@**.";
@ -3227,6 +3368,15 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Impossibile registrare il messaggio vocale";
/* No comment provided by engineer. */
"Unblock" = "Sblocca";
/* No comment provided by engineer. */
"Unblock member" = "Sblocca membro";
/* No comment provided by engineer. */
"Unblock member?" = "Sbloccare il membro?";
/* item status description */
"Unexpected error: %@" = "Errore imprevisto: % @";
@ -3473,6 +3623,27 @@
/* No comment provided by engineer. */
"You are already connected to %@." = "Sei già connesso/a a %@.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "Ti stai già connettendo a %@.";
/* No comment provided by engineer. */
"You are already connecting via this one-time link!" = "Ti stai già connettendo tramite questo link una tantum!";
/* No comment provided by engineer. */
"You are already in group %@." = "Sei già nel gruppo %@.";
/* No comment provided by engineer. */
"You are already joining the group %@." = "Stai già entrando nel gruppo %@.";
/* No comment provided by engineer. */
"You are already joining the group via this link!" = "Stai già entrando nel gruppo tramite questo link!";
/* No comment provided by engineer. */
"You are already joining the group via this link." = "Stai già entrando nel gruppo tramite questo link.";
/* No comment provided by engineer. */
"You are already joining the group!\nRepeat join request?" = "Stai già entrando nel gruppo!\nRipetere la richiesta di ingresso?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "Sei connesso/a al server usato per ricevere messaggi da questo contatto.";
@ -3548,6 +3719,12 @@
/* No comment provided by engineer. */
"You could not be verified; please try again." = "Non è stato possibile verificarti, riprova.";
/* No comment provided by engineer. */
"You have already requested connection via this address!" = "Hai già richiesto la connessione tramite questo indirizzo!";
/* No comment provided by engineer. */
"You have already requested connection!\nRepeat connection request?" = "Hai già richiesto la connessione!\nRipetere la richiesta di connessione?";
/* No comment provided by engineer. */
"You have no chats" = "Non hai chat";
@ -3590,6 +3767,9 @@
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Verrai connesso/a al gruppo quando il dispositivo dell'host del gruppo sarà in linea, attendi o controlla più tardi!";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "Verrai connesso/a quando il dispositivo dell'host del gruppo sarà in linea, attendi o controlla più tardi!";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "Verrai connesso/a quando la tua richiesta di connessione verrà accettata, attendi o controlla più tardi!";
@ -3599,6 +3779,9 @@
/* No comment provided by engineer. */
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Dovrai autenticarti quando avvii o riapri l'app dopo 30 secondi in secondo piano.";
/* No comment provided by engineer. */
"You will connect to all group members." = "Ti connetterai a tutti i membri del gruppo.";
/* No comment provided by engineer. */
"You will still receive calls and notifications from muted profiles when they are active." = "Continuerai a ricevere chiamate e notifiche da profili silenziati quando sono attivi.";
@ -3662,6 +3845,9 @@
/* No comment provided by engineer. */
"Your privacy" = "La tua privacy";
/* No comment provided by engineer. */
"Your profile" = "Il tuo profilo";
/* No comment provided by engineer. */
"Your profile **%@** will be shared." = "Il tuo profilo **%@** verrà condiviso.";

View File

@ -118,12 +118,18 @@
/* No comment provided by engineer. */
"%@ %@" = "%@ %@";
/* No comment provided by engineer. */
"%@ and %@" = "%@ en %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ en %@ verbonden";
/* copied message info, <sender> at <time> */
"%@ at %@:" = "%1$@ bij %2$@:";
/* No comment provided by engineer. */
"%@ connected" = "%@ verbonden";
/* notification title */
"%@ is connected!" = "%@ is verbonden!";
@ -139,6 +145,9 @@
/* notification title */
"%@ wants to connect!" = "%@ wil verbinding maken!";
/* No comment provided by engineer. */
"%@, %@ and %lld members" = "%@, %@ en %lld leden";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ en %lld andere leden hebben verbinding gemaakt";
@ -178,9 +187,21 @@
/* No comment provided by engineer. */
"%lld file(s) with total size of %@" = "%lld bestand(en) met een totale grootte van %@";
/* No comment provided by engineer. */
"%lld group events" = "%lld groep gebeurtenissen";
/* No comment provided by engineer. */
"%lld members" = "%lld leden";
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld berichten geblokkeerd";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld berichten gemarkeerd als verwijderd";
/* No comment provided by engineer. */
"%lld messages moderated by %@" = "%lld berichten gemodereerd door %@";
/* No comment provided by engineer. */
"%lld minutes" = "%lld minuten";
@ -229,6 +250,9 @@
/* No comment provided by engineer. */
"~strike~" = "\\~staking~";
/* time to disappear */
"0 sec" = "0 sec";
/* No comment provided by engineer. */
"0s" = "0s";
@ -371,6 +395,9 @@
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Alle berichten worden verwijderd, dit kan niet ongedaan worden gemaakt! De berichten worden ALLEEN voor jou verwijderd.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Alle nieuwe berichten van %@ worden verborgen!";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Al uw contacten blijven verbonden.";
@ -434,6 +461,12 @@
/* No comment provided by engineer. */
"Already connected?" = "Al verbonden?";
/* No comment provided by engineer. */
"Already connecting!" = "Al bezig met verbinden!";
/* No comment provided by engineer. */
"Already joining the group!" = "Al lid van de groep!";
/* pref value */
"always" = "altijd";
@ -443,6 +476,9 @@
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Er wordt een leeg chatprofiel met de opgegeven naam gemaakt en de app wordt zoals gewoonlijk geopend.";
/* No comment provided by engineer. */
"and %lld other events" = "en %lld andere gebeurtenissen";
/* No comment provided by engineer. */
"Answer call" = "Beantwoord oproep";
@ -527,6 +563,18 @@
/* No comment provided by engineer. */
"Better messages" = "Betere berichten";
/* No comment provided by engineer. */
"Block" = "Blokkeren";
/* No comment provided by engineer. */
"Block member" = "Lid blokkeren";
/* No comment provided by engineer. */
"Block member?" = "Lid blokkeren?";
/* No comment provided by engineer. */
"blocked" = "geblokkeerd";
/* No comment provided by engineer. */
"bold" = "vetgedrukt";
@ -597,7 +645,7 @@
"Change lock mode" = "Wijzig de vergrendelings modus";
/* No comment provided by engineer. */
"Change member role?" = "Rol van gebruiker wijzigen?";
"Change member role?" = "Rol van lid wijzigen?";
/* authentication reason */
"Change passcode" = "Toegangscode wijzigen";
@ -726,6 +774,18 @@
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "maak verbinding met SimpleX Chat-ontwikkelaars.";
/* No comment provided by engineer. */
"Connect to yourself?" = "Verbinding maken met jezelf?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Verbinding maken met jezelf?\nDit is uw eigen eenmalige link!";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Verbinding maken met jezelf?\nDit is uw eigen SimpleX adres!";
/* No comment provided by engineer. */
"Connect via contact address" = "Verbinding maken via contactadres";
/* No comment provided by engineer. */
"Connect via link" = "Maak verbinding via link";
@ -735,6 +795,9 @@
/* No comment provided by engineer. */
"Connect via one-time link" = "Verbinden via een eenmalige link?";
/* No comment provided by engineer. */
"Connect with %@" = "Verbonden met %@";
/* No comment provided by engineer. */
"connected" = "verbonden";
@ -831,6 +894,9 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Core versie: v% @";
/* No comment provided by engineer. */
"Correct name to %@?" = "Juiste naam voor %@?";
/* No comment provided by engineer. */
"Create" = "Maak";
@ -840,6 +906,9 @@
/* server test step */
"Create file" = "Bestand maken";
/* No comment provided by engineer. */
"Create group" = "Groep aanmaken";
/* No comment provided by engineer. */
"Create group link" = "Groep link maken";
@ -852,6 +921,9 @@
/* No comment provided by engineer. */
"Create one-time invitation link" = "Maak een eenmalige uitnodiging link";
/* No comment provided by engineer. */
"Create profile" = "Maak een profiel aan";
/* server test step */
"Create queue" = "Maak een wachtrij";
@ -966,6 +1038,9 @@
/* chat item action */
"Delete" = "Verwijderen";
/* No comment provided by engineer. */
"Delete %lld messages?" = "%lld berichten verwijderen?";
/* No comment provided by engineer. */
"Delete address" = "Adres verwijderen";
@ -978,6 +1053,9 @@
/* No comment provided by engineer. */
"Delete all files" = "Verwijder alle bestanden";
/* No comment provided by engineer. */
"Delete and notify contact" = "Contact verwijderen en op de hoogte stellen";
/* No comment provided by engineer. */
"Delete archive" = "Archief verwijderen";
@ -999,6 +1077,9 @@
/* No comment provided by engineer. */
"Delete Contact" = "Verwijder contact";
/* No comment provided by engineer. */
"Delete contact?\nThis cannot be undone!" = "Verwijder contact?\nDit kan niet ongedaan gemaakt worden!";
/* No comment provided by engineer. */
"Delete database" = "Database verwijderen";
@ -1074,6 +1155,9 @@
/* copied message info */
"Deleted at: %@" = "Verwijderd om: %@";
/* rcv direct event chat item */
"deleted contact" = "verwijderd contact";
/* rcv group event chat item */
"deleted group" = "verwijderde groep";
@ -1305,6 +1389,9 @@
/* No comment provided by engineer. */
"Enter correct passphrase." = "Voer het juiste wachtwoord in.";
/* No comment provided by engineer. */
"Enter group name…" = "Groep naam invoeren…";
/* No comment provided by engineer. */
"Enter Passcode" = "Voer toegangscode in";
@ -1323,6 +1410,9 @@
/* placeholder */
"Enter welcome message… (optional)" = "Voer welkomst bericht in... (optioneel)";
/* No comment provided by engineer. */
"Enter your name…" = "Vul uw naam in…";
/* No comment provided by engineer. */
"error" = "fout";
@ -1339,7 +1429,7 @@
"Error accessing database file" = "Fout bij toegang tot database bestand";
/* No comment provided by engineer. */
"Error adding member(s)" = "Fout bij het toevoegen van gebruiker(s)";
"Error adding member(s)" = "Fout bij het toevoegen van leden";
/* No comment provided by engineer. */
"Error changing address" = "Fout bij wijzigen van adres";
@ -1417,7 +1507,7 @@
"Error receiving file" = "Fout bij ontvangen van bestand";
/* No comment provided by engineer. */
"Error removing member" = "Fout bij verwijderen van gebruiker";
"Error removing member" = "Fout bij verwijderen van lid";
/* No comment provided by engineer. */
"Error saving %@ servers" = "Fout bij opslaan van %@ servers";
@ -1494,6 +1584,9 @@
/* No comment provided by engineer. */
"Exit without saving" = "Afsluiten zonder opslaan";
/* chat item action */
"Expand" = "Uitbreiden";
/* No comment provided by engineer. */
"Export database" = "Database exporteren";
@ -1581,6 +1674,9 @@
/* No comment provided by engineer. */
"Full name:" = "Volledige naam:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "Volledig gedecentraliseerd alleen zichtbaar voor leden.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "Volledig opnieuw geïmplementeerd - werk op de achtergrond!";
@ -1593,6 +1689,12 @@
/* No comment provided by engineer. */
"Group" = "Groep";
/* No comment provided by engineer. */
"Group already exists" = "Groep bestaat al";
/* No comment provided by engineer. */
"Group already exists!" = "Groep bestaat al!";
/* No comment provided by engineer. */
"group deleted" = "groep verwijderd";
@ -1830,6 +1932,9 @@
/* invalid chat item */
"invalid data" = "ongeldige gegevens";
/* No comment provided by engineer. */
"Invalid name!" = "Ongeldige naam!";
/* No comment provided by engineer. */
"Invalid server address!" = "Ongeldig server adres!";
@ -1908,9 +2013,18 @@
/* No comment provided by engineer. */
"Join group" = "Word lid van groep";
/* No comment provided by engineer. */
"Join group?" = "Deelnemen aan groep?";
/* No comment provided by engineer. */
"Join incognito" = "Doe incognito mee";
/* No comment provided by engineer. */
"Join with current profile" = "Word lid met huidig profiel";
/* No comment provided by engineer. */
"Join your group?\nThis is your link for group %@!" = "Sluit u aan bij uw groep?\nDit is jouw link voor groep %@!";
/* No comment provided by engineer. */
"Joining group" = "Deel nemen aan groep";
@ -2008,22 +2122,22 @@
"Max 30 seconds, received instantly." = "Max 30 seconden, direct ontvangen.";
/* member role */
"member" = "gebruiker";
"member" = "lid";
/* No comment provided by engineer. */
"Member" = "Gebruiker";
"Member" = "Lid";
/* rcv group event chat item */
"member connected" = "is toegetreden";
/* No comment provided by engineer. */
"Member role will be changed to \"%@\". All group members will be notified." = "De rol van gebruiker wordt gewijzigd in \"%@\". Alle groepsleden worden op de hoogte gebracht.";
"Member role will be changed to \"%@\". All group members will be notified." = "De rol van lid wordt gewijzigd in \"%@\". Alle groepsleden worden op de hoogte gebracht.";
/* No comment provided by engineer. */
"Member role will be changed to \"%@\". The member will receive a new invitation." = "De rol van gebruiker wordt gewijzigd in \"%@\". Het lid ontvangt een nieuwe uitnodiging.";
"Member role will be changed to \"%@\". The member will receive a new invitation." = "De rol van lid wordt gewijzigd in \"%@\". Het lid ontvangt een nieuwe uitnodiging.";
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Gebruiker wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!";
"Member will be removed from group - this cannot be undone!" = "Lid wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!";
/* item status text */
"Message delivery error" = "Fout bij bezorging van bericht";
@ -2055,6 +2169,9 @@
/* No comment provided by engineer. */
"Messages & files" = "Berichten";
/* No comment provided by engineer. */
"Messages from %@ will be shown!" = "Berichten van %@ worden getoond!";
/* No comment provided by engineer. */
"Migrating database archive…" = "Database archief migreren…";
@ -2262,7 +2379,7 @@
"Only group owners can change group preferences." = "Alleen groep eigenaren kunnen groep voorkeuren wijzigen.";
/* No comment provided by engineer. */
"Only group owners can enable files and media." = "Alleen groepseigenaren kunnen bestanden en media inschakelen.";
"Only group owners can enable files and media." = "Alleen groep eigenaren kunnen bestanden en media inschakelen.";
/* No comment provided by engineer. */
"Only group owners can enable voice messages." = "Alleen groep eigenaren kunnen spraak berichten inschakelen.";
@ -2306,6 +2423,9 @@
/* authentication reason */
"Open chat console" = "Chat console openen";
/* No comment provided by engineer. */
"Open group" = "Open groep";
/* No comment provided by engineer. */
"Open Settings" = "Open instellingen";
@ -2438,6 +2558,12 @@
/* No comment provided by engineer. */
"Profile image" = "profielfoto";
/* No comment provided by engineer. */
"Profile name" = "Profielnaam";
/* No comment provided by engineer. */
"Profile name:" = "Profielnaam:";
/* No comment provided by engineer. */
"Profile password" = "Profiel wachtwoord";
@ -2577,10 +2703,10 @@
"Remove" = "Verwijderen";
/* No comment provided by engineer. */
"Remove member" = "Gebruiker verwijderen";
"Remove member" = "Lid verwijderen";
/* No comment provided by engineer. */
"Remove member?" = "Gebruiker verwijderen?";
"Remove member?" = "Lid verwijderen?";
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "Wachtwoord van de keychain verwijderen?";
@ -2603,6 +2729,12 @@
/* No comment provided by engineer. */
"Renegotiate encryption?" = "Heronderhandelen over versleuteling?";
/* No comment provided by engineer. */
"Repeat connection request?" = "Verbindingsverzoek herhalen?";
/* No comment provided by engineer. */
"Repeat join request?" = "Deelnameverzoek herhalen?";
/* chat item action */
"Reply" = "Antwoord";
@ -2667,7 +2799,7 @@
"Save and notify contact" = "Opslaan en Contact melden";
/* No comment provided by engineer. */
"Save and notify group members" = "Opslaan en Groep leden melden";
"Save and notify group members" = "Opslaan en groep leden melden";
/* No comment provided by engineer. */
"Save and update group profile" = "Groep profiel opslaan en bijwerken";
@ -3045,10 +3177,13 @@
"Tap to activate profile." = "Tik om profiel te activeren.";
/* No comment provided by engineer. */
"Tap to join" = "Tik om mee te doen";
"Tap to Connect" = "Tik om verbinding te maken";
/* No comment provided by engineer. */
"Tap to join incognito" = "Tik om incognito deel te nemen";
"Tap to join" = "Tik om lid te worden";
/* No comment provided by engineer. */
"Tap to join incognito" = "Tik om incognito lid te worden";
/* No comment provided by engineer. */
"Tap to start a new chat" = "Tik om een nieuw gesprek te starten";
@ -3170,6 +3305,12 @@
/* No comment provided by engineer. */
"This group no longer exists." = "Deze groep bestaat niet meer.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "Dit is uw eigen eenmalige link!";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "Dit is uw eigen SimpleX adres!";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "Deze instelling is van toepassing op berichten in je huidige chat profiel **%@**.";
@ -3227,6 +3368,15 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Kan spraakbericht niet opnemen";
/* No comment provided by engineer. */
"Unblock" = "Deblokkeren";
/* No comment provided by engineer. */
"Unblock member" = "Lid deblokkeren";
/* No comment provided by engineer. */
"Unblock member?" = "Lid deblokkeren?";
/* item status description */
"Unexpected error: %@" = "Onverwachte fout: %@";
@ -3473,6 +3623,27 @@
/* No comment provided by engineer. */
"You are already connected to %@." = "U bent al verbonden met %@.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "U maakt al verbinding met %@.";
/* No comment provided by engineer. */
"You are already connecting via this one-time link!" = "Je maakt al verbinding via deze eenmalige link!";
/* No comment provided by engineer. */
"You are already in group %@." = "Je zit al in groep %@.";
/* No comment provided by engineer. */
"You are already joining the group %@." = "Je bent al lid van de groep %@.";
/* No comment provided by engineer. */
"You are already joining the group via this link!" = "Je wordt al lid van de groep via deze link!";
/* No comment provided by engineer. */
"You are already joining the group via this link." = "Je wordt al lid van de groep via deze link.";
/* No comment provided by engineer. */
"You are already joining the group!\nRepeat join request?" = "Je sluit je al aan bij de groep!\nDeelnameverzoek herhalen?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "U bent verbonden met de server die wordt gebruikt om berichten van dit contact te ontvangen.";
@ -3548,6 +3719,12 @@
/* No comment provided by engineer. */
"You could not be verified; please try again." = "U kon niet worden geverifieerd; probeer het opnieuw.";
/* No comment provided by engineer. */
"You have already requested connection via this address!" = "U heeft al een verbinding aangevraagd via dit adres!";
/* No comment provided by engineer. */
"You have already requested connection!\nRepeat connection request?" = "Je hebt al verbinding aangevraagd!\nVerbindingsverzoek herhalen?";
/* No comment provided by engineer. */
"You have no chats" = "Je hebt geen gesprekken";
@ -3590,6 +3767,9 @@
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Je wordt verbonden met de groep wanneer het apparaat van de groep host online is, even geduld a.u.b. of controleer het later!";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "U wordt verbonden wanneer het apparaat van de groep link host online is. Wacht even of controleer het later opnieuw!";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "U wordt verbonden wanneer uw verbindingsverzoek wordt geaccepteerd, even geduld a.u.b. of controleer later!";
@ -3599,6 +3779,9 @@
/* No comment provided by engineer. */
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "U moet zich authenticeren wanneer u de app na 30 seconden op de achtergrond start of hervat.";
/* No comment provided by engineer. */
"You will connect to all group members." = "Je maakt verbinding met alle leden.";
/* No comment provided by engineer. */
"You will still receive calls and notifications from muted profiles when they are active." = "U ontvangt nog steeds oproepen en meldingen van gedempte profielen wanneer deze actief zijn.";
@ -3662,6 +3845,9 @@
/* No comment provided by engineer. */
"Your privacy" = "Uw privacy";
/* No comment provided by engineer. */
"Your profile" = "Jouw profiel";
/* No comment provided by engineer. */
"Your profile **%@** will be shared." = "Uw profiel **%@** wordt gedeeld.";

View File

@ -118,12 +118,18 @@
/* No comment provided by engineer. */
"%@ %@" = "%@ %@";
/* No comment provided by engineer. */
"%@ and %@" = "%@ i %@";
/* No comment provided by engineer. */
"%@ and %@ connected" = "%@ i %@ połączeni";
/* copied message info, <sender> at <time> */
"%@ at %@:" = "%1$@ o %2$@:";
/* No comment provided by engineer. */
"%@ connected" = "%@ połączony";
/* notification title */
"%@ is connected!" = "%@ jest połączony!";
@ -139,6 +145,9 @@
/* notification title */
"%@ wants to connect!" = "%@ chce się połączyć!";
/* No comment provided by engineer. */
"%@, %@ and %lld members" = "%@, %@ i %lld członków";
/* No comment provided by engineer. */
"%@, %@ and %lld other members connected" = "%@, %@ i %lld innych członków połączeni";
@ -178,9 +187,21 @@
/* No comment provided by engineer. */
"%lld file(s) with total size of %@" = "%lld plik(i) o całkowitym rozmiarze %@";
/* No comment provided by engineer. */
"%lld group events" = "%lld wydarzeń grupy";
/* No comment provided by engineer. */
"%lld members" = "%lld członków";
/* No comment provided by engineer. */
"%lld messages blocked" = "%lld wiadomości zablokowanych";
/* No comment provided by engineer. */
"%lld messages marked deleted" = "%lld wiadomości oznaczonych do usunięcia";
/* No comment provided by engineer. */
"%lld messages moderated by %@" = "%lld wiadomości zmoderowanych przez %@";
/* No comment provided by engineer. */
"%lld minutes" = "%lld minut";
@ -229,6 +250,9 @@
/* No comment provided by engineer. */
"~strike~" = "\\~strajk~";
/* time to disappear */
"0 sec" = "0 sek";
/* No comment provided by engineer. */
"0s" = "0s";
@ -371,6 +395,9 @@
/* No comment provided by engineer. */
"All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." = "Wszystkie wiadomości zostaną usunięte - nie można tego cofnąć! Wiadomości zostaną usunięte TYLKO dla Ciebie.";
/* No comment provided by engineer. */
"All new messages from %@ will be hidden!" = "Wszystkie nowe wiadomości z %@ zostaną ukryte!";
/* No comment provided by engineer. */
"All your contacts will remain connected." = "Wszystkie Twoje kontakty pozostaną połączone.";
@ -434,6 +461,12 @@
/* No comment provided by engineer. */
"Already connected?" = "Już połączony?";
/* No comment provided by engineer. */
"Already connecting!" = "Już połączony!";
/* No comment provided by engineer. */
"Already joining the group!" = "Już dołączono do grupy!";
/* pref value */
"always" = "zawsze";
@ -443,6 +476,9 @@
/* No comment provided by engineer. */
"An empty chat profile with the provided name is created, and the app opens as usual." = "Tworzony jest pusty profil czatu o podanej nazwie, a aplikacja otwiera się jak zwykle.";
/* No comment provided by engineer. */
"and %lld other events" = "i %lld innych wydarzeń";
/* No comment provided by engineer. */
"Answer call" = "Odbierz połączenie";
@ -527,6 +563,18 @@
/* No comment provided by engineer. */
"Better messages" = "Lepsze wiadomości";
/* No comment provided by engineer. */
"Block" = "Zablokuj";
/* No comment provided by engineer. */
"Block member" = "Zablokuj członka";
/* No comment provided by engineer. */
"Block member?" = "Zablokować członka?";
/* No comment provided by engineer. */
"blocked" = "zablokowany";
/* No comment provided by engineer. */
"bold" = "pogrubiona";
@ -726,6 +774,18 @@
/* No comment provided by engineer. */
"connect to SimpleX Chat developers." = "połącz się z deweloperami SimpleX Chat.";
/* No comment provided by engineer. */
"Connect to yourself?" = "Połączyć się ze sobą?";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own one-time link!" = "Połączyć się ze sobą?\nTo jest twój jednorazowy link!";
/* No comment provided by engineer. */
"Connect to yourself?\nThis is your own SimpleX address!" = "Połączyć się ze sobą?\nTo jest twój własny adres SimpleX!";
/* No comment provided by engineer. */
"Connect via contact address" = "Połącz przez adres kontaktowy";
/* No comment provided by engineer. */
"Connect via link" = "Połącz się przez link";
@ -735,6 +795,9 @@
/* No comment provided by engineer. */
"Connect via one-time link" = "Połącz przez jednorazowy link";
/* No comment provided by engineer. */
"Connect with %@" = "Połącz z %@";
/* No comment provided by engineer. */
"connected" = "połączony";
@ -831,6 +894,9 @@
/* No comment provided by engineer. */
"Core version: v%@" = "Wersja rdzenia: v%@";
/* No comment provided by engineer. */
"Correct name to %@?" = "Poprawić imię na %@?";
/* No comment provided by engineer. */
"Create" = "Utwórz";
@ -840,6 +906,9 @@
/* server test step */
"Create file" = "Utwórz plik";
/* No comment provided by engineer. */
"Create group" = "Utwórz grupę";
/* No comment provided by engineer. */
"Create group link" = "Utwórz link do grupy";
@ -852,6 +921,9 @@
/* No comment provided by engineer. */
"Create one-time invitation link" = "Utwórz jednorazowy link do zaproszenia";
/* No comment provided by engineer. */
"Create profile" = "Utwórz profil";
/* server test step */
"Create queue" = "Utwórz kolejkę";
@ -966,6 +1038,9 @@
/* chat item action */
"Delete" = "Usuń";
/* No comment provided by engineer. */
"Delete %lld messages?" = "Usunąć %lld wiadomości?";
/* No comment provided by engineer. */
"Delete address" = "Usuń adres";
@ -978,6 +1053,9 @@
/* No comment provided by engineer. */
"Delete all files" = "Usuń wszystkie pliki";
/* No comment provided by engineer. */
"Delete and notify contact" = "Usuń i powiadom kontakt";
/* No comment provided by engineer. */
"Delete archive" = "Usuń archiwum";
@ -999,6 +1077,9 @@
/* No comment provided by engineer. */
"Delete Contact" = "Usuń Kontakt";
/* No comment provided by engineer. */
"Delete contact?\nThis cannot be undone!" = "Usunąć kontakt?\nTo nie może być cofnięte!";
/* No comment provided by engineer. */
"Delete database" = "Usuń bazę danych";
@ -1074,6 +1155,9 @@
/* copied message info */
"Deleted at: %@" = "Usunięto o: %@";
/* rcv direct event chat item */
"deleted contact" = "usunięto kontakt";
/* rcv group event chat item */
"deleted group" = "usunięta grupa";
@ -1305,6 +1389,9 @@
/* No comment provided by engineer. */
"Enter correct passphrase." = "Wprowadź poprawne hasło.";
/* No comment provided by engineer. */
"Enter group name…" = "Wpisz nazwę grupy…";
/* No comment provided by engineer. */
"Enter Passcode" = "Wprowadź Pin";
@ -1323,6 +1410,9 @@
/* placeholder */
"Enter welcome message… (optional)" = "Wpisz wiadomość powitalną… (opcjonalne)";
/* No comment provided by engineer. */
"Enter your name…" = "Wpisz swoją nazwę…";
/* No comment provided by engineer. */
"error" = "błąd";
@ -1494,6 +1584,9 @@
/* No comment provided by engineer. */
"Exit without saving" = "Wyjdź bez zapisywania";
/* chat item action */
"Expand" = "Rozszerz";
/* No comment provided by engineer. */
"Export database" = "Eksportuj bazę danych";
@ -1581,6 +1674,9 @@
/* No comment provided by engineer. */
"Full name:" = "Pełna nazwa:";
/* No comment provided by engineer. */
"Fully decentralized visible only to members." = "W pełni zdecentralizowana widoczna tylko dla członków.";
/* No comment provided by engineer. */
"Fully re-implemented - work in background!" = "W pełni ponownie zaimplementowany - praca w tle!";
@ -1593,6 +1689,12 @@
/* No comment provided by engineer. */
"Group" = "Grupa";
/* No comment provided by engineer. */
"Group already exists" = "Grupa już istnieje";
/* No comment provided by engineer. */
"Group already exists!" = "Grupa już istnieje!";
/* No comment provided by engineer. */
"group deleted" = "grupa usunięta";
@ -1830,6 +1932,9 @@
/* invalid chat item */
"invalid data" = "nieprawidłowe dane";
/* No comment provided by engineer. */
"Invalid name!" = "Nieprawidłowa nazwa!";
/* No comment provided by engineer. */
"Invalid server address!" = "Nieprawidłowy adres serwera!";
@ -1908,9 +2013,18 @@
/* No comment provided by engineer. */
"Join group" = "Dołącz do grupy";
/* No comment provided by engineer. */
"Join group?" = "Dołączyć do grupy?";
/* No comment provided by engineer. */
"Join incognito" = "Dołącz incognito";
/* No comment provided by engineer. */
"Join with current profile" = "Dołącz z obecnym profilem";
/* No comment provided by engineer. */
"Join your group?\nThis is your link for group %@!" = "Dołączyć do twojej grupy?\nTo jest twój link do grupy %@!";
/* No comment provided by engineer. */
"Joining group" = "Dołączanie do grupy";
@ -2055,6 +2169,9 @@
/* No comment provided by engineer. */
"Messages & files" = "Wiadomości i pliki";
/* No comment provided by engineer. */
"Messages from %@ will be shown!" = "Wiadomości od %@ zostaną pokazane!";
/* No comment provided by engineer. */
"Migrating database archive…" = "Migrowanie archiwum bazy danych…";
@ -2306,6 +2423,9 @@
/* authentication reason */
"Open chat console" = "Otwórz konsolę czatu";
/* No comment provided by engineer. */
"Open group" = "Grupa otwarta";
/* No comment provided by engineer. */
"Open Settings" = "Otwórz Ustawienia";
@ -2438,6 +2558,12 @@
/* No comment provided by engineer. */
"Profile image" = "Zdjęcie profilowe";
/* No comment provided by engineer. */
"Profile name" = "Nazwa profilu";
/* No comment provided by engineer. */
"Profile name:" = "Nazwa profilu:";
/* No comment provided by engineer. */
"Profile password" = "Hasło profilu";
@ -2603,6 +2729,12 @@
/* No comment provided by engineer. */
"Renegotiate encryption?" = "Renegocjować szyfrowanie?";
/* No comment provided by engineer. */
"Repeat connection request?" = "Powtórzyć prośbę połączenia?";
/* No comment provided by engineer. */
"Repeat join request?" = "Powtórzyć prośbę dołączenia?";
/* chat item action */
"Reply" = "Odpowiedz";
@ -3044,6 +3176,9 @@
/* No comment provided by engineer. */
"Tap to activate profile." = "Dotknij, aby aktywować profil.";
/* No comment provided by engineer. */
"Tap to Connect" = "Dotknij aby połączyć";
/* No comment provided by engineer. */
"Tap to join" = "Dotknij, aby dołączyć";
@ -3170,6 +3305,12 @@
/* No comment provided by engineer. */
"This group no longer exists." = "Ta grupa już nie istnieje.";
/* No comment provided by engineer. */
"This is your own one-time link!" = "To jest twój jednorazowy link!";
/* No comment provided by engineer. */
"This is your own SimpleX address!" = "To jest twój własny adres SimpleX!";
/* No comment provided by engineer. */
"This setting applies to messages in your current chat profile **%@**." = "To ustawienie dotyczy wiadomości Twojego bieżącego profilu czatu **%@**.";
@ -3227,6 +3368,15 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Nie można nagrać wiadomości głosowej";
/* No comment provided by engineer. */
"Unblock" = "Odblokuj";
/* No comment provided by engineer. */
"Unblock member" = "Odblokuj członka";
/* No comment provided by engineer. */
"Unblock member?" = "Odblokować członka?";
/* item status description */
"Unexpected error: %@" = "Nieoczekiwany błąd: %@";
@ -3473,6 +3623,27 @@
/* No comment provided by engineer. */
"You are already connected to %@." = "Jesteś już połączony z %@.";
/* No comment provided by engineer. */
"You are already connecting to %@." = "Już się łączysz z %@.";
/* No comment provided by engineer. */
"You are already connecting via this one-time link!" = "Już jesteś połączony z tym jednorazowym linkiem!";
/* No comment provided by engineer. */
"You are already in group %@." = "Już jesteś w grupie %@.";
/* No comment provided by engineer. */
"You are already joining the group %@." = "Już dołączasz do grupy %@.";
/* No comment provided by engineer. */
"You are already joining the group via this link!" = "Już dołączasz do grupy przez ten link!";
/* No comment provided by engineer. */
"You are already joining the group via this link." = "Już dołączasz do grupy przez ten link.";
/* No comment provided by engineer. */
"You are already joining the group!\nRepeat join request?" = "Już dołączasz do grupy!\nPowtórzyć prośbę dołączenia?";
/* No comment provided by engineer. */
"You are connected to the server used to receive messages from this contact." = "Jesteś połączony z serwerem używanym do odbierania wiadomości od tego kontaktu.";
@ -3548,6 +3719,12 @@
/* No comment provided by engineer. */
"You could not be verified; please try again." = "Nie można zweryfikować użytkownika; proszę spróbować ponownie.";
/* No comment provided by engineer. */
"You have already requested connection via this address!" = "Już prosiłeś o połączenie na ten adres!";
/* No comment provided by engineer. */
"You have already requested connection!\nRepeat connection request?" = "Już prosiłeś o połączenie!\nPowtórzyć prośbę połączenia?";
/* No comment provided by engineer. */
"You have no chats" = "Nie masz czatów";
@ -3590,6 +3767,9 @@
/* No comment provided by engineer. */
"You will be connected to group when the group host's device is online, please wait or check later!" = "Zostaniesz połączony do grupy, gdy urządzenie gospodarza grupy będzie online, proszę czekać lub sprawdzić później!";
/* No comment provided by engineer. */
"You will be connected when group link host's device is online, please wait or check later!" = "Zostaniesz połączony, gdy urządzenie hosta grupy będzie online, proszę czekać lub sprawdzić później!";
/* No comment provided by engineer. */
"You will be connected when your connection request is accepted, please wait or check later!" = "Zostaniesz połączony, gdy Twoje żądanie połączenia zostanie zaakceptowane, proszę czekać lub sprawdzić później!";
@ -3599,6 +3779,9 @@
/* No comment provided by engineer. */
"You will be required to authenticate when you start or resume the app after 30 seconds in background." = "Uwierzytelnienie będzie wymagane przy uruchamianiu lub wznawianiu aplikacji po 30 sekundach w tle.";
/* No comment provided by engineer. */
"You will connect to all group members." = "Zostaniesz połączony ze wszystkimi członkami grupy.";
/* No comment provided by engineer. */
"You will still receive calls and notifications from muted profiles when they are active." = "Nadal będziesz otrzymywać połączenia i powiadomienia z wyciszonych profili, gdy są one aktywne.";
@ -3662,6 +3845,9 @@
/* No comment provided by engineer. */
"Your privacy" = "Twoja prywatność";
/* No comment provided by engineer. */
"Your profile" = "Twój profil";
/* No comment provided by engineer. */
"Your profile **%@** will be shared." = "Twój profil **%@** zostanie udostępniony.";

View File

@ -3,11 +3,11 @@
<string name="app_name">SimpleX</string>
<string name="thousand_abbreviation">k</string>
<!-- Connect via Link - MainActivity.kt -->
<string name="connect_via_contact_link">Über den Kontakt-Link verbinden?</string>
<string name="connect_via_invitation_link">Über den Einladungslink verbinden\?</string>
<string name="connect_via_group_link">Über den Gruppen-Link verbinden?</string>
<string name="connect_via_contact_link">Über die Kontakt-Adresse verbinden?</string>
<string name="connect_via_invitation_link">Über den Einmal-Link verbinden?</string>
<string name="connect_via_group_link">Der Gruppe beitreten?</string>
<string name="profile_will_be_sent_to_contact_sending_link">Ihr Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben.</string>
<string name="you_will_join_group">Sie werden der Gruppe beitreten, auf die sich dieser Link bezieht, und sich mit deren Gruppenmitgliedern verbinden.</string>
<string name="you_will_join_group">Sie werden mit allen Gruppenmitgliedern verbunden.</string>
<string name="connect_via_link_verb">Verbinden</string>
<!-- Server info - ChatModel.kt -->
<string name="server_connected">Verbunden</string>
@ -21,7 +21,7 @@
<string name="marked_deleted_description">als gelöscht markiert</string>
<string name="sending_files_not_yet_supported">Das Senden von Dateien wird noch nicht unterstützt</string>
<string name="receiving_files_not_yet_supported">Der Empfang von Dateien wird noch nicht unterstützt</string>
<string name="sender_you_pronoun">Meine Daten</string>
<string name="sender_you_pronoun">Ihre Daten</string>
<string name="unknown_message_format">Unbekanntes Nachrichtenformat</string>
<string name="invalid_message_format">Unzulässiges Nachrichtenformat</string>
<!-- PendingContactConnection - ChatModel.kt -->
@ -344,8 +344,8 @@
<string name="create_one_time_link">Einmal-Einladungslink erstellen</string>
<string name="one_time_link">Einmal-Einladungslink</string>
<!-- settings - SettingsView.kt -->
<string name="your_settings">Meine Einstellungen</string>
<string name="your_simplex_contact_address">Meine SimpleX-Adresse</string>
<string name="your_settings">Ihre Einstellungen</string>
<string name="your_simplex_contact_address">Ihre SimpleX-Adresse</string>
<string name="database_passphrase_and_export">Datenbank-Passwort &amp; -Export</string>
<string name="about_simplex_chat">Über SimpleX Chat</string>
<string name="how_to_use_simplex_chat">Wie man SimpleX nutzt</string>
@ -418,7 +418,7 @@
<string name="share_link">Link teilen</string>
<string name="delete_address">Adresse löschen</string>
<!-- User profile details - UserProfileView.kt -->
<string name="display_name__field">Angezeigter Name:</string>
<string name="display_name__field">Profilname:</string>
<string name="full_name__field">Vollständiger Name:</string>
<string name="your_current_profile">Mein aktuelles Chat-Profil</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt. SimpleX-Server können Ihr Profil nicht sehen.</string>
@ -437,7 +437,7 @@
<string name="your_profile_is_stored_on_your_device">Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert.</string>
<string name="profile_is_only_shared_with_your_contacts">Das Profil wird nur mit Ihren Kontakten geteilt.</string>
<string name="display_name_cannot_contain_whitespace">Der angezeigte Name darf keine Leerzeichen enthalten.</string>
<string name="display_name">Angezeigter Name</string>
<string name="display_name">Geben Sie Ihren Namen ein:</string>
<string name="create_profile_button">Erstellen</string>
<string name="about_simplex">Über SimpleX</string>
<!-- markdown demo - MarkdownHelpView.kt -->
@ -553,7 +553,7 @@
\n3. Die Verbindung wurde kompromittiert.</string>
<!-- Privacy settings -->
<string name="privacy_and_security">Datenschutz &amp; Sicherheit</string>
<string name="your_privacy">Meine Privatsphäre</string>
<string name="your_privacy">Ihre Privatsphäre</string>
<string name="protect_app_screen">App-Bildschirm schützen</string>
<string name="auto_accept_images">Bilder automatisch akzeptieren</string>
<string name="send_link_previews">Link-Vorschau senden</string>
@ -712,7 +712,7 @@
<string name="group_invitation_expired">Die Gruppeneinladung ist abgelaufen</string>
<!-- Group event chat items -->
<string name="rcv_group_event_member_added">hat %1$s eingeladen.</string>
<string name="rcv_group_event_member_connected">beigetreten</string>
<string name="rcv_group_event_member_connected">verbunden</string>
<string name="rcv_group_event_member_left">hat die Gruppe verlassen</string>
<string name="rcv_group_event_changed_member_role">änderte die Rolle von %s auf %s</string>
<string name="rcv_group_event_changed_your_role">änderte Ihre Rolle auf %s</string>
@ -813,8 +813,8 @@
<string name="switch_receiving_address">Empfängeradresse wechseln</string>
<!-- AddGroupView.kt -->
<string name="create_secret_group_title">Geheime Gruppe erstellen</string>
<string name="group_is_decentralized">Die Gruppe ist vollständig dezentralisiert sie ist nur für Mitglieder sichtbar.</string>
<string name="group_display_name_field">Anzeigename der Gruppe:</string>
<string name="group_is_decentralized">Vollständig dezentralisiert nur für Mitglieder sichtbar.</string>
<string name="group_display_name_field">Geben Sie den Gruppennamen ein:</string>
<string name="group_full_name_field">Vollständiger Gruppenname:</string>
<string name="group_main_profile_sent">Ihr Chat-Profil wird an die Gruppenmitglieder gesendet</string>
<!-- GroupProfileView.kt -->
@ -1001,7 +1001,7 @@
<string name="network_session_mode_transport_isolation">Transport-Isolation</string>
<string name="users_delete_question">Chat-Profil löschen\?</string>
<string name="error_deleting_user">Fehler beim Löschen des Benutzerprofils</string>
<string name="your_chat_profiles">Meine Chat-Profile</string>
<string name="your_chat_profiles">Ihre Chat-Profile</string>
<string name="network_session_mode_entity">Verbindung</string>
<string name="network_session_mode_user">Chat-Profil</string>
<string name="delete_files_and_media_for_all_users">Dateien für alle Chat-Profile löschen</string>
@ -1084,7 +1084,7 @@
<string name="you_will_still_receive_calls_and_ntfs">Sie können Anrufe und Benachrichtigungen auch von stummgeschalteten Profilen empfangen, solange diese aktiv sind.</string>
<string name="group_welcome_title">Begrüßungsmeldung</string>
<string name="you_can_hide_or_mute_user_profile">Sie können ein Benutzerprofil verbergen oder stummschalten für das Menü gedrückt halten.</string>
<string name="to_reveal_profile_enter_password">Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite \"Meine Chat-Profile\" ein, um Ihr verborgenes Profil zu sehen.</string>
<string name="to_reveal_profile_enter_password">Geben Sie ein vollständiges Passwort in das Suchfeld auf der Seite \"Ihre Chat-Profile\" ein, um Ihr verborgenes Profil zu sehen.</string>
<string name="invalid_migration_confirmation">Migrations-Bestätigung ungültig</string>
<string name="upgrade_and_open_chat">Aktualisieren und den Chat öffnen</string>
<string name="confirm_database_upgrades">Datenbank-Aktualisierungen bestätigen</string>
@ -1451,9 +1451,9 @@
<string name="system_restricted_background_desc">SimpleX kann nicht im Hintergrund ablaufen. Sie erhalten Benachrichtigungen nur dann, solange die App läuft.</string>
<string name="system_restricted_background_in_call_desc">Die App kann nach einer Minute im Hintergrund geschlossen werden.</string>
<string name="system_restricted_background_warn"><![CDATA[Wählen Sie bitte in den App-Einstellungen <b>App-Akkuverbrauch</b> / <b>Unbeschränkt</b> , um Benachrichtigungen zu aktivieren.]]></string>
<string name="rcv_group_event_n_members_connected">%s, %s und %d weitere Mitglieder wurden verbunden</string>
<string name="rcv_group_event_2_members_connected">%s und %s wurden verbunden</string>
<string name="rcv_group_event_3_members_connected">%s, %s und %s wurden verbunden</string>
<string name="rcv_group_event_n_members_connected">%s, %s und %d weitere Mitglieder wurden mit Ihnen verbunden</string>
<string name="rcv_group_event_2_members_connected">%s und %s wurden mit Ihnen verbunden</string>
<string name="rcv_group_event_3_members_connected">%s, %s und %s wurden mit Ihnen verbunden</string>
<string name="privacy_message_draft">Nachrichtenentwurf</string>
<string name="privacy_show_last_messages">Letzte Nachrichten anzeigen</string>
<string name="database_will_be_encrypted_and_passphrase_stored_in_settings">Die Datenbank wird verschlüsselt und das Passwort in den Einstellungen gespeichert.</string>
@ -1487,4 +1487,59 @@
\n- Schneller und stabiler.</string>
<string name="member_contact_send_direct_message">Direktnachricht senden</string>
<string name="rcv_group_event_member_created_contact">Direkt miteinander verbunden</string>
<string name="expand_verb">Erweitern</string>
<string name="connect_plan_repeat_connection_request">Verbindungsanfrage wiederholen?</string>
<string name="rcv_direct_event_contact_deleted">Gelöschter Kontakt</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Sie sind bereits mit %1$s verbunden.</string>
<string name="error_alert_title">Fehler</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Sie sind über diesen Link bereits Mitglied der Gruppe.</string>
<string name="create_group_button">Gruppe erstellen</string>
<string name="create_another_profile_button">Profil erstellen</string>
<string name="group_members_2">%s und %s</string>
<string name="connect_plan_join_your_group">Ihrer Gruppe beitreten?</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Sie sind bereits Mitglied in der Gruppe %1$s.</string>
<string name="connect_plan_this_is_your_own_one_time_link">Das ist Ihr eigener Einmal-Link!</string>
<string name="marked_deleted_items_description">%d Nachrichten als gelöscht markiert</string>
<string name="connect_plan_group_already_exists">Gruppe besteht bereits!</string>
<string name="connect_plan_already_connecting">Bereits verbunden!</string>
<string name="video_decoding_exception_desc">Das Video kann nicht dekodiert werden. Bitte probieren Sie ein anderes Video aus, oder kontaktieren Sie die Entwickler.</string>
<string name="rcv_group_event_1_member_connected">%s wurde mit Ihnen verbunden</string>
<string name="rcv_group_and_other_events">und %d weitere Ereignisse</string>
<string name="connect_plan_connect_via_link">Über einen Link verbinden?</string>
<string name="connect_plan_already_joining_the_group">Sie sind bereits Mitglied der Gruppe!</string>
<string name="group_members_n">%s, %s und %d Mitglieder</string>
<string name="moderated_items_description">%d Nachrichten von %s moderiert</string>
<string name="unblock_member_button">Mitglied freigeben</string>
<string name="connect_plan_connect_to_yourself">Mit Ihnen selbst verbinden?</string>
<string name="contact_tap_to_connect">Zum Verbinden antippen</string>
<string name="connect_plan_you_are_already_in_group_vName">Sie sind bereits Mitglied in der Gruppe %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">Das ist Ihre eigene SimpleX-Adresse!</string>
<string name="correct_name_to">Richtiger Name für %s?</string>
<string name="delete_messages__question">%d Nachrichten löschen?</string>
<string name="connect_with_contact_name_question">Mit %1$s verbinden?</string>
<string name="remove_member_button">Mitglied entfernen</string>
<string name="block_member_confirmation">Blockieren</string>
<string name="unblock_member_question">Mitglied freigeben?</string>
<string name="blocked_items_description">%d Nachrichten blockiert</string>
<string name="block_member_button">Mitglied blockieren</string>
<string name="connect_plan_repeat_join_request">Verbindungsanfrage wiederholen?</string>
<string name="button_remove_member_question">Mitglied entfernen?</string>
<string name="delete_and_notify_contact">Kontakt löschen und benachrichtigen</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Sie sind bereits über diesen Einmal-Link verbunden!</string>
<string name="connect_plan_open_group">Gruppe öffnen</string>
<string name="unblock_member_desc">Die Nachrichten von %s werden angezeigt!</string>
<string name="error_sending_message_contact_invitation">Fehler beim Senden der Einladung</string>
<string name="non_content_uri_alert_text">Sie haben einen ungültigen Datei-Pfad geteilt. Bitte melden Sie diesen Fehler den App-Entwicklern.</string>
<string name="block_member_question">Mitglied blockieren?</string>
<string name="rcv_group_events_count">%d Gruppenereignisse</string>
<string name="invalid_name">Ungültiger Name!</string>
<string name="connect_plan_this_is_your_link_for_group_vName">Das ist Ihr Link für die Gruppe %1$s!</string>
<string name="unblock_member_confirmation">Freigeben</string>
<string name="non_content_uri_alert_title">Ungültiger Datei-Pfad</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Sie haben über diese Adresse bereits eine Verbindung beantragt!</string>
<string name="terminal_always_visible">Die Konsole in einem neuen Fenster anzeigen</string>
<string name="block_member_desc">Alle neuen Nachrichten von %s werden ausgeblendet!</string>
<string name="blocked_item_description">blockiert</string>
<string name="encryption_renegotiation_error">Fehler bei der Neuverhandlung der Verschlüsselung</string>
<string name="alert_text_encryption_renegotiation_failed">Neuverhandlung der Verschlüsselung fehlgeschlagen</string>
</resources>

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="thousand_abbreviation">k</string>
<string name="connect_via_contact_link">Se connecter via le lien du contact \?</string>
<string name="connect_via_contact_link">Se connecter via l\'adresse du contact ?</string>
<string name="app_name">SimpleX</string>
<string name="profile_will_be_sent_to_contact_sending_link">Votre profil va être envoyé au contact qui vous a envoyé ce lien.</string>
<string name="you_will_join_group">Vous allez rejoindre le groupe correspondant à ce lien et être mis en relation avec les autres membres du groupe.</string>
<string name="you_will_join_group">Vous vous connecterez à tous les membres du groupe.</string>
<string name="connect_via_link_verb">Se connecter</string>
<string name="connect_via_group_link">Se connecter via le lien du groupe \?</string>
<string name="connect_via_invitation_link">Se connecter via un lien d\'invitation \?</string>
<string name="connect_via_group_link">Rejoindre le groupe ?</string>
<string name="connect_via_invitation_link">Se connecter via un lien unique ?</string>
<string name="server_error">erreur</string>
<string name="server_connecting">connexion</string>
<string name="server_connected">connecté</string>
@ -427,7 +427,7 @@
<string name="all_your_contacts_will_remain_connected">Tous vos contacts resteront connectés.</string>
<string name="share_link">Partager le lien</string>
<string name="delete_address">Supprimer l\'adresse</string>
<string name="display_name__field">Nom affiché :</string>
<string name="display_name__field">Nom du profil :</string>
<string name="full_name__field">Nom complet :</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Votre profil est stocké sur votre appareil et partagé uniquement avec vos contacts. Les serveurs SimpleX ne peuvent pas voir votre profil.</string>
<string name="delete_image">Supprimer l\'image</string>
@ -436,7 +436,7 @@
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">La plateforme de messagerie et d\'applications qui protège votre vie privée et votre sécurité.</string>
<string name="we_do_not_store_contacts_or_messages_on_servers">Nous ne stockons aucun de vos contacts ou messages (une fois délivrés) sur les serveurs.</string>
<string name="create_profile">Créer le profil</string>
<string name="display_name">Nom affiché</string>
<string name="display_name">Saisissez votre nom :</string>
<string name="how_to_use_markdown">Comment utiliser markdown</string>
<string name="a_plus_b">a + b</string>
<string name="colored_text">coloré</string>
@ -835,7 +835,7 @@
<string name="feature_received_prohibited">reçu, non autorisé</string>
<string name="allow_your_contacts_to_send_disappearing_messages">Autorise votre contact à envoyer des messages éphémères.</string>
<string name="conn_level_desc_direct">directe</string>
<string name="group_is_decentralized">Le groupe est entièrement décentralisé il n\'est visible que par ses membres.</string>
<string name="group_is_decentralized">Entièrement décentralisé visible que par ses membres.</string>
<string name="group_members_can_send_disappearing">Les membres du groupes peuvent envoyer des messages éphémères.</string>
<string name="network_options_revert">Revenir en arrière</string>
<string name="prohibit_sending_disappearing_messages">Interdire lenvoi de messages éphémères.</string>
@ -849,7 +849,7 @@
<string name="only_your_contact_can_send_disappearing">Seulement votre contact peut envoyer des messages éphémères.</string>
<string name="both_you_and_your_contact_can_send_disappearing">Vous et votre contact êtes tous deux en mesure d\'envoyer des messages éphémères.</string>
<string name="voice_messages_are_prohibited">Les messages vocaux sont interdits dans ce groupe.</string>
<string name="group_display_name_field">Nom affiché du groupe :</string>
<string name="group_display_name_field">Saisir le nom du groupe :</string>
<string name="conn_level_desc_indirect">indirecte (%1$s)</string>
<string name="info_row_group">Groupe</string>
<string name="info_row_connection">Connexion</string>
@ -1406,4 +1406,59 @@
<string name="compose_send_direct_message_to_connect">Envoyer un message direct pour vous connecter</string>
<string name="member_contact_send_direct_message">envoyer un message direct</string>
<string name="rcv_group_event_member_created_contact">s\'est connecté.e de manière directe</string>
<string name="expand_verb">Développer</string>
<string name="connect_plan_repeat_connection_request">Répéter la demande de connexion ?</string>
<string name="rcv_direct_event_contact_deleted">contact supprimé</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Vous êtes déjà connecté(e) à %1$s.</string>
<string name="error_alert_title">Erreur</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Vous êtes déjà en train de rejoindre le groupe via ce lien.</string>
<string name="create_group_button">Créer un groupe</string>
<string name="create_another_profile_button">Créer le profil</string>
<string name="group_members_2">%s et %s</string>
<string name="connect_plan_join_your_group">Rejoindre votre groupe ?</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Vous êtes déjà en train de rejoindre le groupe %1$s.</string>
<string name="connect_plan_this_is_your_own_one_time_link">Voici votre propre lien unique !</string>
<string name="marked_deleted_items_description">%d messages marqués comme supprimés</string>
<string name="connect_plan_group_already_exists">Ce groupe existe déjà !</string>
<string name="connect_plan_already_connecting">Déjà en connexion !</string>
<string name="video_decoding_exception_desc">La vidéo ne peut pas être décodée. Veuillez essayer une autre vidéo ou contacter les développeurs.</string>
<string name="rcv_group_event_1_member_connected">%s connecté(e)</string>
<string name="rcv_group_and_other_events">et %d autres événements</string>
<string name="connect_plan_connect_via_link">Se connecter via un lien ?</string>
<string name="connect_plan_already_joining_the_group">Groupe déjà rejoint !</string>
<string name="group_members_n">%s, %s et %d membres</string>
<string name="moderated_items_description">%d messages modérés par %s</string>
<string name="unblock_member_button">Débloquer ce membre</string>
<string name="connect_plan_connect_to_yourself">Se connecter à soi-même ?</string>
<string name="contact_tap_to_connect">Tapez pour vous connecter</string>
<string name="connect_plan_you_are_already_in_group_vName">Vous êtes déjà dans le groupe %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">Voici votre propre adresse SimpleX !</string>
<string name="correct_name_to">Corriger le nom pour %s ?</string>
<string name="delete_messages__question">Supprimer %d messages ?</string>
<string name="connect_with_contact_name_question">Se connecter avec %1$s ?</string>
<string name="remove_member_button">Retirer le membre</string>
<string name="block_member_confirmation">Bloquer</string>
<string name="unblock_member_question">Débloquer ce membre ?</string>
<string name="blocked_items_description">%d messages bloqués</string>
<string name="block_member_button">Bloquer ce membre</string>
<string name="connect_plan_repeat_join_request">Répéter la requête d\'adhésion ?</string>
<string name="button_remove_member_question">Retirer ce membre?</string>
<string name="delete_and_notify_contact">Supprimer et en informer le contact</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Vous êtes déjà connecté(e) via ce lien unique !</string>
<string name="connect_plan_open_group">Ouvrir le groupe</string>
<string name="unblock_member_desc">Les messages de %s seront affichés !</string>
<string name="error_sending_message_contact_invitation">Erreur lors de l\'envoi de l\'invitation</string>
<string name="non_content_uri_alert_text">Vous avez partagé un chemin de fichier non valide. Signalez le problème aux développeurs de l\'application.</string>
<string name="block_member_question">Bloquer ce membre ?</string>
<string name="rcv_group_events_count">%d événements de groupe</string>
<string name="invalid_name">Nom invalide !</string>
<string name="connect_plan_this_is_your_link_for_group_vName">Voici votre lien pour le groupe %1$s !</string>
<string name="unblock_member_confirmation">Débloquer</string>
<string name="non_content_uri_alert_title">Chemin du fichier invalide</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Vous avez déjà demandé une connexion via cette adresse !</string>
<string name="terminal_always_visible">Afficher la console dans une nouvelle fenêtre</string>
<string name="block_member_desc">Tous les nouveaux messages provenant de %s seront cachés !</string>
<string name="blocked_item_description">blocké</string>
<string name="encryption_renegotiation_error">Erreur lors de la renégociation du chiffrement</string>
<string name="alert_text_encryption_renegotiation_failed">La renégociation du chiffrement a échoué.</string>
</resources>

View File

@ -11,8 +11,8 @@
<string name="waiting_for_image">In attesa dell\'immagine</string>
<string name="app_name">SimpleX</string>
<string name="thousand_abbreviation">k</string>
<string name="connect_via_invitation_link">Connettere via link di invito\?</string>
<string name="connect_via_group_link">Connettere via link del gruppo\?</string>
<string name="connect_via_invitation_link">Connettere via link una tantum?</string>
<string name="connect_via_group_link">Entrare nel gruppo?</string>
<string name="profile_will_be_sent_to_contact_sending_link">Il tuo profilo verrà inviato al contatto da cui hai ricevuto questo link.</string>
<string name="connect_via_link_verb">Connetti</string>
<string name="server_connected">connesso</string>
@ -200,9 +200,9 @@
<string name="confirm_verb">Conferma</string>
<string name="reset_verb">Ripristina</string>
<string name="ok">OK</string>
<string name="connect_via_contact_link">Connettere via link del contatto\?</string>
<string name="connect_via_contact_link">Connettere via indirizzo del contatto?</string>
<string name="trying_to_connect_to_server_to_receive_messages_with_error">Tentativo di connessione al server usato per ricevere messaggi da questo contatto (errore: %1$s).</string>
<string name="you_will_join_group">Entrerai in un gruppo a cui si riferisce questo link e ti connetterai ai suoi membri.</string>
<string name="you_will_join_group">Ti connetterai a tutti i membri del gruppo.</string>
<string name="connection_local_display_name">connessione %1$d</string>
<string name="simplex_link_mode_description">Descrizione</string>
<string name="simplex_link_connection">via %1$s</string>
@ -291,7 +291,7 @@
<string name="database_passphrase_is_required">La password del database è necessaria per aprire la chat.</string>
<string name="delete_group_menu_action">Elimina</string>
<string name="direct_messages_are_prohibited_in_chat">I messaggi diretti tra i membri sono vietati in questo gruppo.</string>
<string name="display_name">Nome da mostrare</string>
<string name="display_name">Inserisci il tuo nome:</string>
<string name="add_new_contact_to_create_one_time_QR_code"><![CDATA[<b>Aggiungi un contatto</b>: per creare il tuo codice QR una tantum per il tuo contatto.]]></string>
<string name="scan_QR_code_to_connect_to_contact_who_shows_QR_code"><![CDATA[<b>Scansiona codice QR</b>: per connetterti al contatto che ti mostra il codice QR.]]></string>
<string name="choose_file">File</string>
@ -346,7 +346,7 @@
<string name="create_profile_button">Crea</string>
<string name="create_profile">Crea profilo</string>
<string name="delete_image">Elimina immagine</string>
<string name="display_name__field">Nome da mostrare:</string>
<string name="display_name__field">Nome del profilo:</string>
<string name="display_name_cannot_contain_whitespace">Il nome da mostrare non può contenere spazi.</string>
<string name="edit_image">Modifica immagine</string>
<string name="exit_without_saving">Esci senza salvare</string>
@ -415,7 +415,7 @@
<string name="file_with_path">File: %s</string>
<string name="icon_descr_group_inactive">Gruppo inattivo</string>
<string name="rcv_conn_event_switch_queue_phase_completed">indirizzo cambiato per te</string>
<string name="rcv_group_event_changed_member_role">cambiato il ruolo di %s in %s</string>
<string name="rcv_group_event_changed_member_role">ha cambiato il ruolo di %s in %s</string>
<string name="rcv_group_event_changed_your_role">cambiato il tuo ruolo in %s</string>
<string name="rcv_conn_event_switch_queue_phase_changing">cambio indirizzo…</string>
<string name="snd_conn_event_switch_queue_phase_changing_for_member">cambio indirizzo per %s…</string>
@ -458,7 +458,7 @@
<string name="error_removing_member">Errore nella rimozione del membro</string>
<string name="error_saving_group_profile">Errore nel salvataggio del profilo del gruppo</string>
<string name="info_row_group">Gruppo</string>
<string name="group_display_name_field">Nome da mostrare del gruppo:</string>
<string name="group_display_name_field">Inserisci il nome del gruppo:</string>
<string name="group_profile_is_stored_on_members_devices">Il profilo del gruppo è memorizzato sui dispositivi dei membri, non sui server.</string>
<string name="chat_preferences_always">sempre</string>
<string name="both_you_and_your_contacts_can_delete">Sia tu che il tuo contatto potete eliminare irreversibilmente i messaggi inviati.</string>
@ -828,7 +828,7 @@
<string name="switch_receiving_address">Cambia indirizzo di ricezione</string>
<string name="theme_system">Sistema</string>
<string name="network_option_tcp_connection_timeout">Scadenza connessione TCP</string>
<string name="group_is_decentralized">Il gruppo è completamente decentralizzato: è visibile solo ai membri.</string>
<string name="group_is_decentralized">Completamente decentralizzato: visibile solo ai membri.</string>
<string name="member_role_will_be_changed_with_notification">Il ruolo verrà cambiato in \"%s\". Tutti i membri del gruppo riceveranno una notifica.</string>
<string name="member_role_will_be_changed_with_invitation">Il ruolo verrà cambiato in \"%s\". Il membro riceverà un nuovo invito.</string>
<string name="update_network_settings_confirmation">Aggiorna</string>
@ -1406,4 +1406,59 @@
<string name="compose_send_direct_message_to_connect">Invia messaggio diretto per connetterti</string>
<string name="member_contact_send_direct_message">invia messaggio diretto</string>
<string name="rcv_group_event_member_created_contact">si è connesso/a direttamente</string>
<string name="expand_verb">Espandi</string>
<string name="connect_plan_repeat_connection_request">Ripetere la richiesta di connessione?</string>
<string name="rcv_direct_event_contact_deleted">contatto eliminato</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Ti stai già connettendo a %1$s.</string>
<string name="error_alert_title">Errore</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Stai già entrando nel gruppo tramite questo link.</string>
<string name="create_group_button">Crea gruppo</string>
<string name="create_another_profile_button">Crea profilo</string>
<string name="group_members_2">%s e %s</string>
<string name="connect_plan_join_your_group">Entrare nel tuo gruppo?</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Stai già entrando nel gruppo %1$s.</string>
<string name="connect_plan_this_is_your_own_one_time_link">Questo è il tuo link una tantum!</string>
<string name="marked_deleted_items_description">%d messaggi contrassegnati eliminati</string>
<string name="connect_plan_group_already_exists">Il gruppo esiste già!</string>
<string name="connect_plan_already_connecting">Già in connessione!</string>
<string name="video_decoding_exception_desc">Il video non può essere decodificato. Prova un video diverso o contatta gli sviluppatori.</string>
<string name="rcv_group_event_1_member_connected">%s si è connesso/a</string>
<string name="rcv_group_and_other_events">e altri %d eventi</string>
<string name="connect_plan_connect_via_link">Connettere via link?</string>
<string name="connect_plan_already_joining_the_group">Stai già entrando nel gruppo!</string>
<string name="group_members_n">%s, %s e %d membri</string>
<string name="moderated_items_description">%d messaggi moderati da %s</string>
<string name="unblock_member_button">Sblocca membro</string>
<string name="connect_plan_connect_to_yourself">Connettersi a te stesso?</string>
<string name="contact_tap_to_connect">Tocca per connettere</string>
<string name="connect_plan_you_are_already_in_group_vName">Sei già nel gruppo %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">Questo è il tuo indirizzo SimpleX!</string>
<string name="correct_name_to">Correggere il nome a %s?</string>
<string name="delete_messages__question">Eliminare %d messaggi?</string>
<string name="connect_with_contact_name_question">Connettersi con %1$s?</string>
<string name="remove_member_button">Rimuovi membro</string>
<string name="block_member_confirmation">Blocca</string>
<string name="unblock_member_question">Sbloccare il membro?</string>
<string name="blocked_items_description">%d messaggi bloccati</string>
<string name="block_member_button">Blocca membro</string>
<string name="connect_plan_repeat_join_request">Ripetere la richiesta di ingresso?</string>
<string name="button_remove_member_question">Rimuovere il membro?</string>
<string name="delete_and_notify_contact">Elimina e avvisa il contatto</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Ti stai già connettendo tramite questo link una tantum!</string>
<string name="connect_plan_open_group">Apri gruppo</string>
<string name="unblock_member_desc">I messaggi da %s verranno mostrati!</string>
<string name="error_sending_message_contact_invitation">Errore di invio dell\'invito</string>
<string name="non_content_uri_alert_text">Hai condiviso un percorso di file non valido. Segnala il problema agli sviluppatori dell\'app.</string>
<string name="block_member_question">Bloccare il membro?</string>
<string name="rcv_group_events_count">%d eventi del gruppo</string>
<string name="invalid_name">Nome non valido!</string>
<string name="connect_plan_this_is_your_link_for_group_vName">Questo è il tuo link per il gruppo %1$s!</string>
<string name="unblock_member_confirmation">Sblocca</string>
<string name="non_content_uri_alert_title">Percorso file non valido</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Hai già richiesto la connessione tramite questo indirizzo!</string>
<string name="terminal_always_visible">Mostra console in una nuova finestra</string>
<string name="block_member_desc">Tutti i nuovi messaggi di %s verranno nascosti!</string>
<string name="blocked_item_description">bloccato</string>
<string name="encryption_renegotiation_error">Errore di rinegoziazione crittografia</string>
<string name="alert_text_encryption_renegotiation_failed">Rinegoziazione crittografia fallita.</string>
</resources>

View File

@ -155,9 +155,9 @@
<string name="connect_via_link_verb">Verbind</string>
<string name="server_connected">verbonden</string>
<string name="server_connecting">Verbinden</string>
<string name="connect_via_contact_link">Verbinden via contact link\?</string>
<string name="connect_via_group_link">Verbinden via groep link\?</string>
<string name="connect_via_invitation_link">Verbinden via uitnodiging link\?</string>
<string name="connect_via_contact_link">Verbinden via contact link?</string>
<string name="connect_via_group_link">Deelnemen aan groep?</string>
<string name="connect_via_invitation_link">Verbinden via eenmalige link?</string>
<string name="notification_preview_mode_contact">Contact naam</string>
<string name="notification_preview_somebody">Contact verborgen:</string>
<string name="image_decoding_exception_title">Decodeerfout</string>
@ -261,7 +261,7 @@
<string name="desktop_scan_QR_code_from_app_via_scan_QR_code"><![CDATA[💻 desktop: scan weergegeven QR-code vanuit de app, via <b>Scan QR-code</b>.]]></string>
<string name="settings_developer_tools">Ontwikkel gereedschap</string>
<string name="auth_device_authentication_is_disabled_turning_off">Apparaatverificatie is uitgeschakeld. SimpleX Vergrendelen uitschakelen.</string>
<string name="display_name">Weergavenaam</string>
<string name="display_name">Vul uw naam in:</string>
<string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Apparaatverificatie is niet ingeschakeld. Je kunt SimpleX Vergrendelen inschakelen via Instellingen zodra je apparaatverificatie hebt ingeschakeld.</string>
<string name="direct_messages_are_prohibited_in_chat">Directe berichten tussen leden zijn verboden in deze groep.</string>
<string name="total_files_count_and_size">%d bestand(en) met een totale grootte van %s</string>
@ -273,7 +273,7 @@
<string name="timed_messages">Verdwijnende berichten</string>
<string name="smp_server_test_disconnect">Verbinding verbreken</string>
<string name="icon_descr_server_status_disconnected">Verbinding verbroken</string>
<string name="display_name__field">Weergavenaam:</string>
<string name="display_name__field">Profielnaam:</string>
<string name="display_name_cannot_contain_whitespace">Weergavenaam mag geen spatie bevatten.</string>
<string name="ttl_min">%d min</string>
<string name="ttl_months">%d maanden</string>
@ -300,7 +300,7 @@
<string name="error_importing_database">Fout bij het importeren van de chat database</string>
<string name="encrypt_database_question">Database versleutelen\?</string>
<string name="alert_title_no_group">Groep niet gevonden!</string>
<string name="group_display_name_field">Weergave naam groep:</string>
<string name="group_display_name_field">Groep naam invoeren:</string>
<string name="failed_to_create_user_duplicate_title">Dubbele weergavenaam!</string>
<string name="error_sending_message">Fout bij verzenden van bericht</string>
<string name="failed_to_active_user_title">Fout bij wisselen van profiel!</string>
@ -340,7 +340,7 @@
<string name="error_deleting_link_for_group">Fout bij verwijderen groep link</string>
<string name="group_link">Groep link</string>
<string name="error_changing_role">Fout bij wisselen van rol</string>
<string name="error_removing_member">Fout bij verwijderen van gebruiker</string>
<string name="error_removing_member">Fout bij verwijderen van lid</string>
<string name="info_row_group">Groep</string>
<string name="group_full_name_field">Volledige naam groep:</string>
<string name="group_preferences">Groep voorkeuren</string>
@ -362,7 +362,7 @@
<string name="button_edit_group_profile">Groep profiel bewerken</string>
<string name="network_option_enable_tcp_keep_alive">Schakel TCP keep-alive in</string>
<string name="encrypt_database">Versleutelen</string>
<string name="error_adding_members">Fout bij het toevoegen van gebruiker(s)</string>
<string name="error_adding_members">Fout bij het toevoegen van leden</string>
<string name="smp_servers_enter_manually">Voer de server handmatig in</string>
<string name="error_accepting_contact_request">Fout bij het accepteren van een contactverzoek</string>
<string name="group_invitation_expired">Groep uitnodiging verlopen</string>
@ -482,12 +482,12 @@
\n3. De verbinding is verbroken.</string>
<string name="joining_group">Deel nemen aan groep</string>
<string name="leave_group_button">Verlaten</string>
<string name="group_member_role_member">Gebruiker</string>
<string name="group_member_role_member">Lid</string>
<string name="image_descr_link_preview">link voorbeeld afbeelding</string>
<string name="member_info_section_title_member">GEBRUIKER</string>
<string name="member_info_section_title_member">LID</string>
<string name="settings_section_title_messages">BERICHTEN EN BESTANDEN</string>
<string name="mobile_tap_open_in_mobile_app_then_tap_connect_in_app"><![CDATA[📱 mobiel: tik op <b>Openen in mobiele app</b> en tik vervolgens op <b>Verbinden</b> in de app.]]></string>
<string name="member_will_be_removed_from_group_cannot_be_undone">Gebruiker wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!</string>
<string name="member_will_be_removed_from_group_cannot_be_undone">Lid wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!</string>
<string name="message_delivery_error_title">Fout bij bezorging van bericht</string>
<string name="delete_message_mark_deleted_warning">Bericht wordt gemarkeerd voor verwijdering. De ontvanger(s) kunnen dit bericht onthullen.</string>
<string name="network_status">Netwerk status</string>
@ -717,7 +717,7 @@
<string name="save_and_notify_contact">Opslaan en Contact melden</string>
<string name="your_current_profile">Je huidige profiel</string>
<string name="save_and_notify_contacts">Opslaan en Contacten melden</string>
<string name="save_and_notify_group_members">Opslaan en Groepsleden melden</string>
<string name="save_and_notify_group_members">Opslaan en groepsleden melden</string>
<string name="strikethrough_text">staking</string>
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Het berichten- en applicatieplatform dat uw privacy en veiligheid beschermt.</string>
<string name="profile_is_only_shared_with_your_contacts">Het profiel wordt alleen gedeeld met uw contacten.</string>
@ -775,7 +775,7 @@
<string name="member_role_will_be_changed_with_notification">De rol wordt gewijzigd in \"%s\". Iedereen in de groep wordt op de hoogte gebracht.</string>
<string name="receiving_via">Ontvang via</string>
<string name="save_group_profile">Groep profiel opslaan</string>
<string name="group_is_decentralized">De groep is volledig gedecentraliseerd het is alleen zichtbaar voor de leden.</string>
<string name="group_is_decentralized">Volledig gedecentraliseerd alleen zichtbaar voor leden.</string>
<string name="network_option_tcp_connection_timeout">Timeout van TCP-verbinding</string>
<string name="voice_messages">Spraak berichten</string>
<string name="voice_prohibited_in_this_chat">Spraak berichten zijn verboden in dit gesprek.</string>
@ -791,10 +791,10 @@
<string name="database_restore_error">Databasefout herstellen</string>
<string name="unknown_error">Onbekende fout</string>
<string name="wrong_passphrase_title">Verkeerd wachtwoord!</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">U bent uitgenodigd voor de groep. Word lid om in contact te komen met groepsleden.</string>
<string name="group_invitation_tap_to_join">Tik om mee te doen</string>
<string name="group_invitation_tap_to_join_incognito">Tik om incognito deel te nemen</string>
<string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Je bent lid geworden van deze groep. Verbinding maken met uitnodigend groepslid.</string>
<string name="you_are_invited_to_group_join_to_connect_with_group_members">U bent uitgenodigd voor de groep. Word lid om in contact te komen met de groepsleden.</string>
<string name="group_invitation_tap_to_join">Tik om lid te worden</string>
<string name="group_invitation_tap_to_join_incognito">Tik om incognito lid te worden</string>
<string name="youve_accepted_group_invitation_connecting_to_inviting_group_member">Je bent lid geworden van deze groep. Verbinding maken met uitnodigend lid.</string>
<string name="you_sent_group_invitation">Je hebt een groep uitnodiging verzonden</string>
<string name="snd_group_event_user_left">jij bent vertrokken</string>
<string name="snd_conn_event_switch_queue_phase_completed">je bent van adres veranderd</string>
@ -802,7 +802,7 @@
<string name="skip_inviting_button">Sla het uitnodigen van leden over</string>
<string name="num_contacts_selected">%d contact(en) geselecteerd</string>
<string name="remove_member_confirmation">Verwijderen</string>
<string name="button_remove_member">Gebruiker verwijderen</string>
<string name="button_remove_member">Lid verwijderen</string>
<string name="role_in_group">Rol</string>
<string name="button_send_direct_message">Direct bericht sturen</string>
<string name="member_role_will_be_changed_with_invitation">De rol wordt gewijzigd in \"%s\". De gebruiker ontvangt een nieuwe uitnodiging.</string>
@ -831,7 +831,7 @@
<string name="app_name">SimpleX</string>
<string name="connected_to_server_to_receive_messages_from_contact">U bent verbonden met de server die wordt gebruikt om berichten van dit contact te ontvangen.</string>
<string name="profile_will_be_sent_to_contact_sending_link">Je profiel wordt verzonden naar het contact van wie je deze link hebt ontvangen.</string>
<string name="you_will_join_group">U wordt lid van de groep waar deze link naar verwijst en maakt verbinding met de groepsleden.</string>
<string name="you_will_join_group">Je maakt verbinding met alle groepsleden.</string>
<string name="notifications_mode_off">Uitvoeren bij geopende app</string>
<string name="settings_notification_preview_mode_title">Toon voorbeeld</string>
<string name="ntf_channel_calls">SimpleX Chat oproepen</string>
@ -949,7 +949,7 @@
<string name="integrity_msg_skipped">%1$d bericht(en) overgeslagen</string>
<string name="moderated_description">gemodereerd</string>
<string name="moderated_item_description">gemodereerd door %s</string>
<string name="delete_member_message__question">Bericht van lid verwijderen\?</string>
<string name="delete_member_message__question">Bericht van lid verwijderen?</string>
<string name="moderate_verb">Modereren</string>
<string name="moderate_message_will_be_deleted_warning">Het bericht wordt verwijderd voor alle leden.</string>
<string name="moderate_message_will_be_marked_warning">Het bericht wordt gemarkeerd als gemodereerd voor alle leden.</string>
@ -1263,7 +1263,7 @@
<string name="abort_switch_receiving_address">Annuleer het wijzigen van het adres</string>
<string name="abort_switch_receiving_address_confirm">Afbreken</string>
<string name="no_filtered_chats">Geen gefilterde gesprekken</string>
<string name="only_owners_can_enable_files_and_media">Alleen groepseigenaren kunnen bestanden en media inschakelen.</string>
<string name="only_owners_can_enable_files_and_media">Alleen groep eigenaren kunnen bestanden en media inschakelen.</string>
<string name="files_are_prohibited_in_group">Bestanden en media zijn verboden in deze groep.</string>
<string name="favorite_chat">Favoriet</string>
<string name="files_and_media_prohibited">Bestanden en media verboden!</string>
@ -1404,4 +1404,59 @@
<string name="compose_send_direct_message_to_connect">Stuur een direct bericht om verbinding te maken</string>
<string name="member_contact_send_direct_message">stuur een direct bericht</string>
<string name="rcv_group_event_member_created_contact">direct verbonden</string>
<string name="expand_verb">Uitbreiden</string>
<string name="connect_plan_repeat_connection_request">Verbindingsverzoek herhalen?</string>
<string name="rcv_direct_event_contact_deleted">verwijderd contact</string>
<string name="error_alert_title">Fout</string>
<string name="create_group_button">Groep aanmaken</string>
<string name="create_another_profile_button">Maak een profiel aan</string>
<string name="group_members_2">%s en %s</string>
<string name="connect_plan_join_your_group">Deelnemen aan uw groep?</string>
<string name="marked_deleted_items_description">%d berichten gemarkeerd als verwijderd</string>
<string name="connect_plan_group_already_exists">Groep bestaat al!</string>
<string name="connect_plan_already_connecting">Al bezig met verbinden!</string>
<string name="video_decoding_exception_desc">De video kan niet worden gedecodeerd. Probeer een andere video of neem contact op met de ontwikkelaars.</string>
<string name="rcv_group_event_1_member_connected">%s verbonden</string>
<string name="rcv_group_and_other_events">en %d andere gebeurtenissen</string>
<string name="connect_plan_connect_via_link">Verbinden via link?</string>
<string name="connect_plan_already_joining_the_group">Al lid van de groep!</string>
<string name="group_members_n">%s, %s en %d leden</string>
<string name="moderated_items_description">%d berichten gemodereerd door %s</string>
<string name="connect_plan_connect_to_yourself">Verbinding maken met jezelf?</string>
<string name="contact_tap_to_connect">Tik om verbinding te maken</string>
<string name="correct_name_to">Juiste naam voor %s?</string>
<string name="delete_messages__question">%d berichten verwijderen?</string>
<string name="connect_with_contact_name_question">Verbinding maken met %1$s?</string>
<string name="remove_member_button">Lid verwijderen</string>
<string name="block_member_confirmation">Blokkeren</string>
<string name="blocked_items_description">%d berichten geblokkeerd</string>
<string name="block_member_button">Lid blokkeren</string>
<string name="connect_plan_repeat_join_request">Deelnameverzoek herhalen?</string>
<string name="button_remove_member_question">Lid verwijderen?</string>
<string name="delete_and_notify_contact">Contact verwijderen en op de hoogte stellen</string>
<string name="connect_plan_open_group">Open groep</string>
<string name="unblock_member_desc">Berichten van %s worden getoond!</string>
<string name="error_sending_message_contact_invitation">Fout bij verzenden van uitnodiging</string>
<string name="block_member_question">Lid blokkeren?</string>
<string name="rcv_group_events_count">%d groep gebeurtenissen</string>
<string name="invalid_name">Ongeldige naam!</string>
<string name="non_content_uri_alert_title">Ongeldig bestandspad</string>
<string name="terminal_always_visible">Console in nieuw venster weergeven</string>
<string name="block_member_desc">Alle nieuwe berichten van %s worden verborgen!</string>
<string name="blocked_item_description">geblokkeerd</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Je bent al verbonden met %1$s.</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Je wordt al lid van de groep via deze link.</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Je bent al lid van de groep %1$s.</string>
<string name="connect_plan_this_is_your_own_one_time_link">Dit is uw eigen eenmalige link!</string>
<string name="unblock_member_button">Lid deblokkeren</string>
<string name="connect_plan_you_are_already_in_group_vName">Je zit al in groep %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">Dit is uw eigen SimpleX adres!</string>
<string name="unblock_member_question">Lid deblokkeren?</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Je maakt al verbinding via deze eenmalige link!</string>
<string name="non_content_uri_alert_text">Je hebt een ongeldig bestandslocatie gedeeld. Rapporteer het probleem aan de app-ontwikkelaars.</string>
<string name="connect_plan_this_is_your_link_for_group_vName">Dit is jouw link voor groep %1$s!</string>
<string name="unblock_member_confirmation">Deblokkeren</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">U heeft al een verbinding aangevraagd via dit adres!</string>
<string name="encryption_renegotiation_error">Fout bij heronderhandeling van codering</string>
<string name="alert_text_encryption_renegotiation_failed">Opnieuw onderhandelen over de codering is mislukt.</string>
</resources>

View File

@ -9,9 +9,9 @@
<string name="display_name_connecting">łączenie…</string>
<string name="display_name_connection_established">połączenie ustanowione</string>
<string name="connection_local_display_name">połączenie %1$d</string>
<string name="connect_via_contact_link">Połączyć się przez link kontaktowy\?</string>
<string name="connect_via_group_link">Połącz się przez link grupowy\?</string>
<string name="connect_via_invitation_link">Połączyć się przez link zapraszający\?</string>
<string name="connect_via_contact_link">Połączyć się przez adres kontaktowy?</string>
<string name="connect_via_group_link">Dołączyć do grupy?</string>
<string name="connect_via_invitation_link">Połączyć się przez link jednorazowy?</string>
<string name="deleted_description">usunięty</string>
<string name="server_error">błąd</string>
<string name="invalid_chat">nieprawidłowy czat</string>
@ -367,7 +367,7 @@
<string name="delete_address">Usuń adres</string>
<string name="delete_address__question">Usunąć adres\?</string>
<string name="delete_image">Usuń obraz</string>
<string name="display_name__field">Wyświetlana nazwa:</string>
<string name="display_name__field">Nazwa profilu:</string>
<string name="edit_image">Edytuj obraz</string>
<string name="exit_without_saving">Wyjdź bez zapisywania</string>
<string name="full_name__field">Pełna nazwa:</string>
@ -723,7 +723,7 @@
<string name="error_removing_member">Błąd usuwania członka</string>
<string name="section_title_for_console">DLA KONSOLI</string>
<string name="info_row_group">Grupa</string>
<string name="group_display_name_field">Wyświetlana nazwa grupy:</string>
<string name="group_display_name_field">Wprowadź nazwę grupy:</string>
<string name="group_full_name_field">Pełna nazwa grupy:</string>
<string name="info_row_local_name">Nazwa lokalna</string>
<string name="member_info_section_title_member">CZŁONEK</string>
@ -741,7 +741,7 @@
<string name="conn_stats_section_title_servers">SERWERY</string>
<string name="switch_verb">Przełącz</string>
<string name="switch_receiving_address">Zmień adres odbioru</string>
<string name="group_is_decentralized">Grupa jest w pełni zdecentralizowana jest widoczna tylko dla członków.</string>
<string name="group_is_decentralized">W pełni zdecentralizowana widoczna tylko dla członków.</string>
<string name="member_role_will_be_changed_with_invitation">Rola zostanie zmieniona na \"%s\". Członek otrzyma nowe zaproszenie.</string>
<string name="group_welcome_title">Wiadomość powitalna</string>
<string name="cant_delete_user_profile">Nie można usunąć profilu użytkownika!</string>
@ -1033,7 +1033,7 @@
<string name="snd_group_event_member_deleted">usunąłeś %1$s</string>
<string name="your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it">Twój profil jest przechowywany na Twoim urządzeniu i udostępniany tylko Twoim kontaktom. Serwery SimpleX nie widzą Twojego profilu.</string>
<string name="description_you_shared_one_time_link_incognito">udostępniłeś jednorazowy link incognito</string>
<string name="you_will_join_group">Dołączysz do grupy, do której odnosi się ten link i połączysz się z jej członkami.</string>
<string name="you_will_join_group">Zostaniesz połączony ze wszystkimi członkami grupy.</string>
<string name="your_SMP_servers">Twoje serwery SMP</string>
<string name="you_will_be_connected_when_your_connection_request_is_accepted">Zostaniesz połączony, gdy Twoje żądanie połączenia zostanie zaakceptowane, proszę czekać lub sprawdzić później!</string>
<string name="error_loading_smp_servers">Błąd ładowania serwerów SMP</string>
@ -1406,4 +1406,59 @@
<string name="compose_send_direct_message_to_connect">Wyślij wiadomość bezpośrednią aby połączyć</string>
<string name="member_contact_send_direct_message">wyślij wiadomość bezpośrednią</string>
<string name="rcv_group_event_member_created_contact">połącz bezpośrednio</string>
<string name="rcv_direct_event_contact_deleted">usunięto kontakt</string>
<string name="create_group_button">Utwórz grupę</string>
<string name="create_another_profile_button">Utwórz profil</string>
<string name="marked_deleted_items_description">%d wiadomości oznaczonych do usunięcia</string>
<string name="connect_plan_already_connecting">Już połączony!</string>
<string name="rcv_group_and_other_events">i %d innych wydarzeń</string>
<string name="connect_plan_connect_via_link">Połączyć przez link?</string>
<string name="connect_plan_already_joining_the_group">Już dołączono do grupy!</string>
<string name="moderated_items_description">%d wiadomości zmoderowanych przez %s</string>
<string name="connect_plan_connect_to_yourself">Połączyć się ze sobą?</string>
<string name="correct_name_to">Poprawić nazwę do %s?</string>
<string name="delete_messages__question">Usunąć %d wiadomości?</string>
<string name="connect_with_contact_name_question">Połączyć z %1$s?</string>
<string name="block_member_confirmation">Zablokuj</string>
<string name="blocked_items_description">%d wiadomości zablokowanych</string>
<string name="block_member_button">Zablokuj członka</string>
<string name="delete_and_notify_contact">Usuń i powiadom kontakt</string>
<string name="block_member_question">Zablokować członka?</string>
<string name="rcv_group_events_count">%d wydarzeń grupy</string>
<string name="block_member_desc">Wszystkie nowe wiadomości z %s będą ukryte!</string>
<string name="blocked_item_description">zablokowany</string>
<string name="expand_verb">Rozszerz</string>
<string name="connect_plan_repeat_connection_request">Powtórzyć prośbę połączenia?</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Już jesteś połączony z %1$s.</string>
<string name="error_alert_title">Błąd</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Już dołączasz do grupy przez ten link.</string>
<string name="group_members_2">%s i %s</string>
<string name="connect_plan_join_your_group">Dołączyć do twojej grupy?</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Już dołączasz do grupy %1$s.</string>
<string name="connect_plan_this_is_your_own_one_time_link">To jest twój jednorazowy link!</string>
<string name="connect_plan_group_already_exists">Grupa już istnieje!</string>
<string name="video_decoding_exception_desc">Wideo nie może zostać zdekodowane, spróbuj inne wideo lub skontaktuj się z deweloperami.</string>
<string name="rcv_group_event_1_member_connected">%s połączony</string>
<string name="group_members_n">%s, %s i %d członków</string>
<string name="unblock_member_button">Odblokuj członka</string>
<string name="contact_tap_to_connect">Dotknij aby połączyć</string>
<string name="connect_plan_you_are_already_in_group_vName">Już jesteś w grupie %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">To jest twój własny adres SimpleX!</string>
<string name="remove_member_button">Usuń członka</string>
<string name="unblock_member_question">Odblokować członka?</string>
<string name="connect_plan_repeat_join_request">Powtórzyć prośbę dołączenia?</string>
<string name="button_remove_member_question">Usunąć członka?</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Już jesteś połączony z tym jednorazowym linkiem!</string>
<string name="connect_plan_open_group">Grupa otwarta</string>
<string name="unblock_member_desc">Wiadomości z %s zostaną wyświetlone!</string>
<string name="error_sending_message_contact_invitation">Błąd wysyłania zaproszenia</string>
<string name="non_content_uri_alert_text">Udostępniłeś nieprawidłową ścieżkę pliku. Zgłoś problem do deweloperów aplikacji.</string>
<string name="invalid_name">Nieprawidłowa nazwa!</string>
<string name="connect_plan_this_is_your_link_for_group_vName">To jest twój link zaproszenia do grupy %1$s!</string>
<string name="unblock_member_confirmation">Odblokuj</string>
<string name="non_content_uri_alert_title">Nieprawidłowa ścieżka pliku</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Już prosiłeś o połączenie na ten adres!</string>
<string name="terminal_always_visible">Pokaż konsolę w nowym oknie</string>
<string name="encryption_renegotiation_error">Błąd renegocjacji szyfrowania</string>
<string name="alert_text_encryption_renegotiation_failed">Renegocjacja szyfrowania nie powiodła się.</string>
</resources>

View File

@ -116,11 +116,11 @@
<string name="app_name">SimpleX</string>
<string name="both_you_and_your_contact_can_make_calls">Дзвонити можете як ви, так і ваш контакт.</string>
<string name="thousand_abbreviation">k</string>
<string name="connect_via_contact_link">Підключитися за контактним посиланням\?</string>
<string name="connect_via_invitation_link">Підключитися за посиланням-запрошенням\?</string>
<string name="connect_via_group_link">Підключитися за груповим посиланням\?</string>
<string name="connect_via_contact_link">Підключитися через контактну адресу?</string>
<string name="connect_via_invitation_link">Підключитися за одноразовим посиланням?</string>
<string name="connect_via_group_link">Приєднатися до групи?</string>
<string name="profile_will_be_sent_to_contact_sending_link">Ваш профіль буде надіслано контакту, від якого ви отримали це посилання.</string>
<string name="you_will_join_group">Ви приєднаєтеся до групи, на яку посилається це посилання, і з\'єднаєтеся з її учасниками.</string>
<string name="you_will_join_group">Ви з\'єднаєтеся з усіма учасниками групи.</string>
<string name="connect_via_link_verb">Підключіться</string>
<string name="server_connected">підключений</string>
<string name="server_error">помилка</string>
@ -265,7 +265,7 @@
<string name="full_name__field">Повне ім\'я:</string>
<string name="you_control_your_chat">Ви керуєте своїм чатом!</string>
<string name="the_messaging_and_app_platform_protecting_your_privacy_and_security">Платформа для обміну повідомленнями та додатків, що захищає вашу конфіденційність і безпеку.</string>
<string name="display_name">Відображуване ім\'я</string>
<string name="display_name">Введіть своє ім\'я:</string>
<string name="callstatus_in_progress">виклик у процесі</string>
<string name="callstate_starting">починаючи…</string>
<string name="first_platform_without_user_ids">Перша платформа без жодних ідентифікаторів користувачів приватна за дизайном.</string>
@ -411,7 +411,7 @@
<string name="v4_5_multiple_chat_profiles">Кілька профілів чату</string>
<string name="core_version">Основна версія: v%s</string>
<string name="delete_address__question">Видалити адресу\?</string>
<string name="display_name__field">Відображуване ім\'я:</string>
<string name="display_name__field">Ім\'я профілю:</string>
<string name="callstate_waiting_for_confirmation">чекаємо на підтвердження…</string>
<string name="privacy_redefined">Переосмислення конфіденційності</string>
<string name="people_can_connect_only_via_links_you_share">Люди можуть підключатися до вас лише за посиланнями, якими ви ділитеся.</string>
@ -488,7 +488,7 @@
<string name="delete_link">Видалити посилання</string>
<string name="switch_verb">Перемикач</string>
<string name="error_changing_role">Помилка, що змінює роль</string>
<string name="group_display_name_field">Відображувана назва групи:</string>
<string name="group_display_name_field">Введіть назву групи:</string>
<string name="group_full_name_field">Повна назва групи:</string>
<string name="error_saving_group_profile">Помилка збереження профілю групи</string>
<string name="network_options_reset_to_defaults">Скидання до налаштувань за замовчуванням</string>
@ -643,7 +643,8 @@
<string name="use_simplex_chat_servers__question">Використовуєте сервери SimpleX Chat\?</string>
<string name="enter_one_ICE_server_per_line">Сервери ICE (по одному на лінію)</string>
<string name="error_saving_ICE_servers">Помилка збереження серверів ICE</string>
<string name="network_use_onion_hosts_required_desc">Для з\'єднання будуть потрібні хости onion.</string>
<string name="network_use_onion_hosts_required_desc">Onion hosts will be required for connection.
\nPlease note: you will not be able to connect to the servers without .onion address.</string>
<string name="network_use_onion_hosts_prefer_desc_in_alert">Onion хости будуть використовуватися за наявності.</string>
<string name="network_use_onion_hosts_required_desc_in_alert">Для з\'єднання будуть потрібні хости onion.</string>
<string name="show_developer_options">Показати опції розробника</string>
@ -1101,7 +1102,7 @@
<string name="enter_welcome_message">Введіть вітальне повідомлення…</string>
<string name="switch_receiving_address">Змінити адресу отримання</string>
<string name="create_secret_group_title">Створити секретну групу</string>
<string name="group_is_decentralized">Група повністю децентралізована - її бачать лише учасники.</string>
<string name="group_is_decentralized">Повністю децентралізована - видима лише для учасників.</string>
<string name="network_option_tcp_connection_timeout">Тайм-аут підключення TCP</string>
<string name="dont_show_again">Більше не показувати</string>
<string name="color_secondary">Вторинний</string>
@ -1372,4 +1373,90 @@
<string name="sync_connection_force_question">Переузгодьте шифрування\?</string>
<string name="sync_connection_force_desc">Шифрування працює і нова угода про шифрування не потрібна. Це може призвести до помилок з\'єднання!</string>
<string name="group_members_can_send_files">Учасники групи можуть надсилати файли та медіа.</string>
<string name="database_will_be_encrypted_and_passphrase_stored_in_settings">База даних буде зашифрована, а ключова фраза збережена в налаштуваннях.</string>
<string name="expand_verb">Розгорнути</string>
<string name="connect_plan_repeat_connection_request">Повторити запит на підключення?</string>
<string name="encryption_renegotiation_error">Помилка повторного узгодження шифрування</string>
<string name="rcv_direct_event_contact_deleted">видалений контакт</string>
<string name="connect_plan_you_are_already_connecting_to_vName">Ви вже з\'єднані з %1$s.</string>
<string name="rcv_group_event_open_chat">Відкрити</string>
<string name="v5_3_encrypt_local_files">Шифрування збережених файлів і носіїв</string>
<string name="error_alert_title">Помилка</string>
<string name="error_creating_member_contact">Помилка при створенні контакту користувача</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">Ви вже приєдналися до групи за цим посиланням.</string>
<string name="create_group_button">Створити групу</string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>Зверніть увагу</b>: ретранслятори повідомлень і файлів підключаються через проксі SOCKS. Дзвінки та надсилання попередніх переглядів посилань використовують пряме з’єднання.]]></string>
<string name="create_another_profile_button">Створити профіль</string>
<string name="group_members_2">%s та %s</string>
<string name="connect_plan_join_your_group">Приєднатися до групи?</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">Ви вже приєдналися до групи %1$s.</string>
<string name="encrypt_local_files">Шифрування локальних файлів</string>
<string name="connect_plan_this_is_your_own_one_time_link">Це ваше власне одноразове посилання!</string>
<string name="marked_deleted_items_description">%d повідомлень позначено як видалені</string>
<string name="v5_3_new_desktop_app">Новий десктопний застосунок!</string>
<string name="v5_3_new_interface_languages">6 нових мов інтерфейсу</string>
<string name="connect_plan_group_already_exists">Група вже існує!</string>
<string name="v5_3_encrypt_local_files_descr">Застосунок шифрує нові локальні файли (крім відео).</string>
<string name="connect_plan_already_connecting">Вже під\'єднуємося!</string>
<string name="you_can_change_it_later">Випадкова фраза зберігається у налаштуваннях у вигляді відкритого тексту.
\nВи можете змінити його пізніше.</string>
<string name="compose_send_direct_message_to_connect">Надішліть пряме повідомлення, щоб підключитися</string>
<string name="video_decoding_exception_desc">Відео не може бути декодовано. Будь ласка, спробуйте інше відео або зверніться до розробників.</string>
<string name="rcv_group_event_1_member_connected">%s підключено</string>
<string name="rcv_group_and_other_events">ще інших подій - %d</string>
<string name="v5_3_discover_join_groups">Знаходьте та приєднуйтесь до груп</string>
<string name="connect_plan_connect_via_link">Підключитися за посиланням?</string>
<string name="database_encryption_will_be_updated_in_settings">Пароль для шифрування бази даних буде оновлено і збережено в налаштуваннях.</string>
<string name="connect_plan_already_joining_the_group">Вже долучаємось до групи!</string>
<string name="group_members_n">члени %s, %s та %d</string>
<string name="moderated_items_description">%d повідомлень модерує %s</string>
<string name="remove_passphrase_from_settings">Видалити парольну фразу з налаштувань?</string>
<string name="unblock_member_button">Розблокувати</string>
<string name="use_random_passphrase">Використовуйте випадкову парольну фразу</string>
<string name="connect_plan_connect_to_yourself">Підключитися до себе?</string>
<string name="save_passphrase_in_settings">Зберегти парольну фразу в налаштуваннях</string>
<string name="v5_3_simpler_incognito_mode">Спрощений режим інкогніто</string>
<string name="contact_tap_to_connect">Натисніть, щоб підключитися</string>
<string name="setup_database_passphrase">Ключова фраза для налаштування бази даних</string>
<string name="connect_plan_you_are_already_in_group_vName">Ви вже в групі %1$s.</string>
<string name="connect_plan_this_is_your_own_simplex_address">Це ваша власна SimpleX адреса!</string>
<string name="alert_text_encryption_renegotiation_failed">Повторне узгодження шифрування не вдалося.</string>
<string name="correct_name_to">Виправити ім\'я на %s?</string>
<string name="delete_messages__question">Видалити %d повідомлень?</string>
<string name="connect_with_contact_name_question">Підключитися до %1$s?</string>
<string name="remove_member_button">Видалити учасника</string>
<string name="set_database_passphrase">Встановити пароль до бази даних</string>
<string name="block_member_confirmation">Заблокувати</string>
<string name="unblock_member_question">Розблокувати учасника?</string>
<string name="blocked_items_description">%d повідомлень заблоковано</string>
<string name="block_member_button">Заблокувати учасника</string>
<string name="open_database_folder">Відкрийте теку з базою даних</string>
<string name="connect_plan_repeat_join_request">Повторити запит на приєднання?</string>
<string name="button_remove_member_question">Видалити учасника?</string>
<string name="delete_and_notify_contact">Видалити та повідомити контакт</string>
<string name="v5_3_new_interface_languages_descr">Арабська, Болгарська, Фінська, Іврит, Тайська та Українська завдяки користувачам і Weblate.</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">Ви вже підключаєтеся за цим одноразовим посиланням!</string>
<string name="connect_plan_open_group">Відкрити групу</string>
<string name="unblock_member_desc">Будуть показані повідомлення від %s!</string>
<string name="v5_3_new_desktop_app_descr">Створіть новий профіль у десктопному застосунку. 💻</string>
<string name="error_sending_message_contact_invitation">Помилка надсилання запрошення</string>
<string name="passphrase_will_be_saved_in_settings">Після зміни пароля або перезапуску програми він буде збережений у налаштуваннях у вигляді відкритого тексту.</string>
<string name="non_content_uri_alert_text">Ви надали невірний шлях до файлу. Повідомте про проблему розробникам програми.</string>
<string name="block_member_question">Заблокувати учасника?</string>
<string name="rcv_group_events_count">%d групових подій</string>
<string name="invalid_name">Неправильне ім\'я!</string>
<string name="v5_3_simpler_incognito_mode_descr">Увімкніть інкогніто при підключенні.</string>
<string name="connect_plan_this_is_your_link_for_group_vName">Це ваше посилання для групи %1$s!</string>
<string name="unblock_member_confirmation">Розблокувати</string>
<string name="non_content_uri_alert_title">Неправильний шлях до файлу</string>
<string name="v5_3_discover_join_groups_descr">- підключитися до служби каталогів (БЕТА)!
\n- квитанції про доставку (до 20 учасників).
\n- швидше і стабільніше.</string>
<string name="settings_is_storing_in_clear_text">Пароль зберігається у налаштуваннях у вигляді відкритого тексту.</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Ви вже надсилали запит на підключення за цією адресою!</string>
<string name="member_contact_send_direct_message">надіслати пряме повідомлення</string>
<string name="terminal_always_visible">Показати консоль у новому вікні</string>
<string name="block_member_desc">Всі повідомлення від %s будуть приховані</string>
<string name="rcv_group_event_member_created_contact">підключений безпосередньо</string>
<string name="blocked_item_description">заблоковано</string>
</resources>

View File

@ -62,9 +62,9 @@
<string name="delete_message__question">删除消息?</string>
<string name="delete_messages">删除消息</string>
<string name="info_row_connection">连接</string>
<string name="connect_via_invitation_link">通过邀请链接进行连接?</string>
<string name="connect_via_contact_link">通过联系人链接进行连接?</string>
<string name="connect_via_group_link">通过群组链接连接</string>
<string name="connect_via_invitation_link">通过一次性链接进行连接?</string>
<string name="connect_via_contact_link">通过联系人地址进行连接?</string>
<string name="connect_via_group_link">加群吗</string>
<string name="connect_via_link_or_qr">通过群组链接/二维码连接</string>
<string name="always_use_relay">总是通过中继连接</string>
<string name="allow_your_contacts_irreversibly_delete">允许您的联系人不可撤回地删除已发送消息。</string>
@ -358,7 +358,7 @@
<string name="core_version">核心版本: v%s</string>
<string name="display_name__field">显示名:</string>
<string name="full_name__field">全名:</string>
<string name="display_name">显示名</string>
<string name="display_name">输入你的名字:</string>
<string name="callstate_ended">已结束</string>
<string name="group_member_status_group_deleted">群组已删除</string>
<string name="delete_group_for_all_members_cannot_undo_warning">将为所有成员删除群组——此操作无法撤消!</string>
@ -410,7 +410,7 @@
<string name="error_saving_ICE_servers">保存 ICE 服务器错误</string>
<string name="error_sending_message">发送消息错误</string>
<string name="simplex_link_mode_full">完整链接</string>
<string name="group_display_name_field">群组显示</string>
<string name="group_display_name_field">输入群组名:</string>
<string name="group_invitation_expired">群组邀请已过期</string>
<string name="delete_group_for_self_cannot_undo_warning">将为您删除群组——此操作无法撤消!</string>
<string name="group_profile_is_stored_on_members_devices">群组资料存储在成员的设备上,而不是服务器上。</string>
@ -735,7 +735,7 @@
<string name="is_not_verified">%s 未验证</string>
<string name="v4_5_italian_interface_descr">感谢用户——通过 Weblate 做出贡献!</string>
<string name="first_platform_without_user_ids">第一个没有任何用户标识符的平台——专为隐私保护设计。</string>
<string name="group_is_decentralized">该小组是完全分散式的——它只对成员可见。</string>
<string name="group_is_decentralized">完全去中心化 - 仅对成员可见。</string>
<string name="image_decoding_exception_desc">图像无法解码。 请尝试不同的图像或联系开发者。</string>
<string name="theme">主题</string>
<string name="delete_files_and_media_desc">此操作无法撤消——所有接收和发送的文件和媒体都将被删除。 低分辨率图片将保留。</string>
@ -918,7 +918,7 @@
<string name="conn_level_desc_indirect">间接(%1$s</string>
<string name="you_can_also_connect_by_clicking_the_link"><![CDATA[您也可以通过点击链接进行连接。 如果它在浏览器中打开,请单击<b>在移动应用程序中打开</b>按钮。]]></string>
<string name="app_name">SimpleX</string>
<string name="you_will_join_group">您将加入此链接指向的群组并连接到其群组成员。</string>
<string name="you_will_join_group">你将连接到所有群成员。</string>
<string name="description_via_group_link">通过群组链接</string>
<string name="description_via_one_time_link">通过一次性链接</string>
<string name="description_via_contact_address_link">通过联系地址链接</string>
@ -1406,4 +1406,59 @@
<string name="compose_send_direct_message_to_connect">发送私信来连接</string>
<string name="member_contact_send_direct_message">发送私信</string>
<string name="rcv_group_event_member_created_contact">已直连</string>
<string name="expand_verb">展开</string>
<string name="connect_plan_repeat_connection_request">重复连接请求吗?</string>
<string name="rcv_direct_event_contact_deleted">已删除联系人</string>
<string name="connect_plan_you_are_already_connecting_to_vName">你已经在连接到 %1$s。</string>
<string name="error_alert_title">错误</string>
<string name="connect_plan_you_are_already_joining_the_group_via_this_link">你已经在通过此链接加入该群。</string>
<string name="create_group_button">建群</string>
<string name="create_another_profile_button">创建个人资料</string>
<string name="group_members_2">%s 和 %s</string>
<string name="connect_plan_join_your_group">加入你的群吗?</string>
<string name="connect_plan_you_are_already_joining_the_group_vName">你已经在加入 %1$s 群。</string>
<string name="connect_plan_this_is_your_own_one_time_link">这是你自己的一次性链接!</string>
<string name="marked_deleted_items_description">%d 条消息被标记为删除</string>
<string name="connect_plan_group_already_exists">群已存在!</string>
<string name="connect_plan_already_connecting">已经在连接了!</string>
<string name="video_decoding_exception_desc">无法解码该视频。请尝试不同视频或联络开发者。</string>
<string name="rcv_group_event_1_member_connected">%s 已连接</string>
<string name="rcv_group_and_other_events">及其他 %d 个事件</string>
<string name="connect_plan_connect_via_link">通过链接进行连接吗?</string>
<string name="connect_plan_already_joining_the_group">已经加入了该群组!</string>
<string name="group_members_n">%s、 %s 和 %d 名成员</string>
<string name="moderated_items_description">%s 审核了 %d 条消息</string>
<string name="unblock_member_button">解封成员</string>
<string name="connect_plan_connect_to_yourself">连接到你自己?</string>
<string name="contact_tap_to_connect">轻按连接</string>
<string name="connect_plan_you_are_already_in_group_vName">你已经在%1$s 群内。</string>
<string name="connect_plan_this_is_your_own_simplex_address">这是你自己的 SimpleX 地址!</string>
<string name="correct_name_to">更正名称为 %s?</string>
<string name="delete_messages__question">删除 %d 条消息吗?</string>
<string name="connect_with_contact_name_question">和 %1$s 连接吗?</string>
<string name="remove_member_button">删除成员</string>
<string name="block_member_confirmation">封禁</string>
<string name="unblock_member_question">解封成员吗?</string>
<string name="blocked_items_description">拦截了 %d 条消息</string>
<string name="block_member_button">封禁成员</string>
<string name="connect_plan_repeat_join_request">重复加入请求吗?</string>
<string name="button_remove_member_question">删除成员吗?</string>
<string name="delete_and_notify_contact">删除并通知联系人</string>
<string name="connect_plan_you_are_already_connecting_via_this_one_time_link">你已经在通过这个一次性链接进行连接!</string>
<string name="connect_plan_open_group">打开群</string>
<string name="unblock_member_desc">将显示来自 %s 的消息!</string>
<string name="error_sending_message_contact_invitation">发送邀请出错</string>
<string name="non_content_uri_alert_text">你分享了无效的文件路径。请将此问题报告给应用开发者。</string>
<string name="block_member_question">封禁成员吗?</string>
<string name="rcv_group_events_count">%d 个群事件</string>
<string name="invalid_name">无效名称!</string>
<string name="connect_plan_this_is_your_link_for_group_vName">这是给你的 %1$s 群链接!</string>
<string name="unblock_member_confirmation">解封</string>
<string name="non_content_uri_alert_title">无效的文件路径</string>
<string name="connect_plan_you_have_already_requested_connection_via_this_address">你已经请求通过此地址进行连接!</string>
<string name="terminal_always_visible">在新窗口中显示控制台</string>
<string name="block_member_desc">所有来自 %s 的新消息都将被隐藏!</string>
<string name="blocked_item_description">已封禁</string>
<string name="encryption_renegotiation_error">加密重协商错误</string>
<string name="alert_text_encryption_renegotiation_failed">加密重协商失败了。</string>
</resources>

View File

@ -29,10 +29,6 @@ import java.io.File
val simplexWindowState = SimplexWindowState()
fun showApp() = application {
// TODO: remove after update to compose 1.5.0+
// See: https://github.com/JetBrains/compose-multiplatform/issues/3366#issuecomment-1643799976
System.setProperty("compose.scrolling.smooth.enabled", "false")
// For some reason on Linux actual width will be 10.dp less after specifying it here. If we specify 1366,
// it will show 1356. But after that we can still update it to 1366 by changing window state. Just making it +10 now here
val width = if (desktopPlatform.isLinux()) 1376.dp else 1366.dp

View File

@ -120,6 +120,7 @@ library
Simplex.Chat.Migrations.M20231019_indexes
Simplex.Chat.Migrations.M20231030_xgrplinkmem_received
Simplex.Chat.Migrations.M20231107_indexes
Simplex.Chat.Migrations.M20231113_group_forward
Simplex.Chat.Mobile
Simplex.Chat.Mobile.File
Simplex.Chat.Mobile.Shared

View File

@ -28,6 +28,7 @@ import Data.Bifunctor (bimap, first)
import qualified Data.ByteString.Base64 as B64
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as LB
import Data.Char
import Data.Constraint (Dict (..))
import Data.Either (fromRight, rights)
@ -140,7 +141,8 @@ defaultChatConfig =
cleanupManagerInterval = 30 * 60, -- 30 minutes
cleanupManagerStepDelay = 3 * 1000000, -- 3 seconds
ciExpirationInterval = 30 * 60 * 1000000, -- 30 minutes
coreApi = False
coreApi = False,
highlyAvailable = False
}
_defaultSMPServers :: NonEmpty SMPServerWithAuth
@ -184,9 +186,9 @@ createChatDatabase filePrefix key confirmMigrations = runExceptT $ do
pure ChatDatabase {chatStore, agentStore}
newChatController :: ChatDatabase -> Maybe User -> ChatConfig -> ChatOpts -> IO ChatController
newChatController ChatDatabase {chatStore, agentStore} user cfg@ChatConfig {agentConfig = aCfg, defaultServers, inlineFiles, tempDir} ChatOpts {coreOptions = CoreChatOpts {smpServers, xftpServers, networkConfig, logLevel, logConnections, logServerHosts, logFile, tbqSize}, optFilesFolder, showReactions, allowInstantFiles, autoAcceptFileSize} = do
newChatController ChatDatabase {chatStore, agentStore} user cfg@ChatConfig {agentConfig = aCfg, defaultServers, inlineFiles, tempDir} ChatOpts {coreOptions = CoreChatOpts {smpServers, xftpServers, networkConfig, logLevel, logConnections, logServerHosts, logFile, tbqSize, highlyAvailable}, optFilesFolder, showReactions, allowInstantFiles, autoAcceptFileSize} = do
let inlineFiles' = if allowInstantFiles || autoAcceptFileSize > 0 then inlineFiles else inlineFiles {sendChunks = 0, receiveInstant = False}
config = cfg {logLevel, showReactions, tbqSize, subscriptionEvents = logConnections, hostEvents = logServerHosts, defaultServers = configServers, inlineFiles = inlineFiles', autoAcceptFileSize}
config = cfg {logLevel, showReactions, tbqSize, subscriptionEvents = logConnections, hostEvents = logServerHosts, defaultServers = configServers, inlineFiles = inlineFiles', autoAcceptFileSize, highlyAvailable}
firstTime = dbNew chatStore
currentUser <- newTVarIO user
servers <- agentServers config
@ -1563,7 +1565,7 @@ processChatCommand = \case
gVar <- asks idsDrg
subMode <- chatReadVar subscriptionMode
(agentConnId, cReq) <- withAgent $ \a -> createConnection a (aUserId user) True SCMInvitation Nothing subMode
member <- withStore $ \db -> createNewContactMember db gVar user groupId contact memRole agentConnId cReq subMode
member <- withStore $ \db -> createNewContactMember db gVar user gInfo contact memRole agentConnId cReq subMode
sendInvitation member cReq
pure $ CRSentGroupInvitation user gInfo contact member
Just member@GroupMember {groupMemberId, memberStatus, memberRole = mRole}
@ -3220,7 +3222,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
MSG meta _msgFlags msgBody -> do
cmdId <- createAckCmd conn
withAckMessage agentConnId cmdId meta $ do
(_conn', _) <- saveRcvMSG conn (ConnectionId connId) meta msgBody cmdId
(_conn', _) <- saveDirectRcvMSG conn meta cmdId msgBody
pure False
SENT msgId ->
sentMsgDeliveryEvent conn msgId
@ -3251,14 +3253,13 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
MSG msgMeta _msgFlags msgBody -> do
cmdId <- createAckCmd conn
withAckMessage agentConnId cmdId msgMeta $ do
(conn', msg@RcvMessage {chatMsgEvent = ACME _ event}) <- saveRcvMSG conn (ConnectionId connId) msgMeta msgBody cmdId
(conn', msg@RcvMessage {chatMsgEvent = ACME _ event}) <- saveDirectRcvMSG conn msgMeta cmdId msgBody
let ct' = ct {activeConn = Just conn'} :: Contact
assertDirectAllowed user MDRcv ct' $ toCMEventTag event
updateChatLock "directMessage" event
case event of
XMsgNew mc -> newContentMessage ct' mc msg msgMeta
XMsgFileDescr sharedMsgId fileDescr -> messageFileDescription ct' sharedMsgId fileDescr msgMeta
XMsgFileCancel sharedMsgId -> cancelMessageFile ct' sharedMsgId msgMeta
XMsgUpdate sharedMsgId mContent ttl live -> messageUpdate ct' sharedMsgId mContent msg msgMeta ttl live
XMsgDel sharedMsgId _ -> messageDelete ct' sharedMsgId msg msgMeta
XMsgReact sharedMsgId _ reaction add -> directMsgReaction ct' sharedMsgId reaction add msg msgMeta
@ -3335,10 +3336,11 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
ci <- saveSndChatItem user (CDDirectSnd ct) msg (CISndMsgContent mc)
toView $ CRNewChatItem user (AChatItem SCTDirect SMDSnd (DirectChat ct) ci)
forM_ groupId_ $ \groupId -> do
groupInfo <- withStore $ \db -> getGroupInfo db user groupId
subMode <- chatReadVar subscriptionMode
gVar <- asks idsDrg
groupConnIds <- createAgentConnectionAsync user CFCreateConnGrpInv True SCMInvitation subMode
withStore $ \db -> createNewContactMemberAsync db gVar user groupId ct gLinkMemRole groupConnIds (fromJVersionRange peerChatVRange) subMode
gVar <- asks idsDrg
withStore $ \db -> createNewContactMemberAsync db gVar user groupInfo ct gLinkMemRole groupConnIds (fromJVersionRange peerChatVRange) subMode
_ -> pure ()
Just (gInfo, m@GroupMember {activeConn}) ->
when (maybe False ((== ConnReady) . connStatus) activeConn) $ do
@ -3508,61 +3510,118 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
withStore' $ \db -> updateIntroStatus db introId GMIntroSent
_ -> do
-- TODO notify member who forwarded introduction - question - where it is stored? There is via_contact but probably there should be via_member in group_members table
let memCategory = memberCategory m
withStore' (\db -> getViaGroupContact db user m) >>= \case
Nothing -> do
notifyMemberConnected gInfo m Nothing
let connectedIncognito = memberIncognito membership
when (memberCategory m == GCPreMember) $ probeMatchingMemberContact m connectedIncognito
when (memCategory == GCPreMember) $ probeMatchingMemberContact m connectedIncognito
Just ct@Contact {activeConn} ->
forM_ activeConn $ \Connection {connStatus} ->
when (connStatus == ConnReady) $ do
notifyMemberConnected gInfo m $ Just ct
let connectedIncognito = contactConnIncognito ct || incognitoMembership gInfo
when (memberCategory m == GCPreMember) $ probeMatchingContactsAndMembers ct connectedIncognito True
when (memCategory == GCPreMember) $ probeMatchingContactsAndMembers ct connectedIncognito True
sendXGrpMemCon memCategory
where
sendXGrpMemCon = \case
GCPreMember ->
forM_ (invitedByGroupMemberId membership) $ \hostId -> do
host <- withStore $ \db -> getGroupMember db user groupId hostId
forM_ (memberConn host) $ \hostConn ->
void $ sendDirectMessage hostConn (XGrpMemCon m.memberId) (GroupId groupId)
GCPostMember ->
forM_ (invitedByGroupMemberId m) $ \invitingMemberId -> do
im <- withStore $ \db -> getGroupMember db user groupId invitingMemberId
forM_ (memberConn im) $ \imConn ->
void $ sendDirectMessage imConn (XGrpMemCon m.memberId) (GroupId groupId)
_ -> messageWarning "sendXGrpMemCon: member category GCPreMember or GCPostMember is expected"
MSG msgMeta _msgFlags msgBody -> do
cmdId <- createAckCmd conn
withAckMessage agentConnId cmdId msgMeta $ do
(conn', msg@RcvMessage {chatMsgEvent = ACME _ event}) <- saveRcvMSG conn (GroupId groupId) msgMeta msgBody cmdId
let m' = m {activeConn = Just conn'} :: GroupMember
updateChatLock "groupMessage" event
case event of
XMsgNew mc -> canSend m' $ newGroupContentMessage gInfo m' mc msg msgMeta
XMsgFileDescr sharedMsgId fileDescr -> canSend m' $ groupMessageFileDescription gInfo m' sharedMsgId fileDescr msgMeta
XMsgFileCancel sharedMsgId -> cancelGroupMessageFile gInfo m' sharedMsgId msgMeta
XMsgUpdate sharedMsgId mContent ttl live -> canSend m' $ groupMessageUpdate gInfo m' sharedMsgId mContent msg msgMeta ttl live
XMsgDel sharedMsgId memberId -> groupMessageDelete gInfo m' sharedMsgId memberId msg msgMeta
XMsgReact sharedMsgId (Just memberId) reaction add -> groupMsgReaction gInfo m' sharedMsgId memberId reaction add msg msgMeta
-- TODO discontinue XFile
XFile fInv -> processGroupFileInvitation' gInfo m' fInv msg msgMeta
XFileCancel sharedMsgId -> xFileCancelGroup gInfo m' sharedMsgId msgMeta
XFileAcptInv sharedMsgId fileConnReq_ fName -> xFileAcptInvGroup gInfo m' sharedMsgId fileConnReq_ fName msgMeta
-- XInfo p -> xInfoMember gInfo m' p -- TODO use for member profile update
XGrpLinkMem p -> xGrpLinkMem gInfo m' conn' p
XGrpMemNew memInfo -> xGrpMemNew gInfo m' memInfo msg msgMeta
XGrpMemIntro memInfo -> xGrpMemIntro gInfo m' memInfo
XGrpMemInv memId introInv -> xGrpMemInv gInfo m' memId introInv
XGrpMemFwd memInfo introInv -> xGrpMemFwd gInfo m' memInfo introInv
XGrpMemRole memId memRole -> xGrpMemRole gInfo m' memId memRole msg msgMeta
XGrpMemDel memId -> xGrpMemDel gInfo m' memId msg msgMeta
XGrpLeave -> xGrpLeave gInfo m' msg msgMeta
XGrpDel -> xGrpDel gInfo m' msg msgMeta
XGrpInfo p' -> xGrpInfo gInfo m' p' msg msgMeta
XGrpDirectInv connReq mContent_ -> canSend m' $ xGrpDirectInv gInfo m' conn' connReq mContent_ msg msgMeta
XInfoProbe probe -> xInfoProbe (COMGroupMember m') probe
XInfoProbeCheck probeHash -> xInfoProbeCheck (COMGroupMember m') probeHash
XInfoProbeOk probe -> xInfoProbeOk (COMGroupMember m') probe
BFileChunk sharedMsgId chunk -> bFileChunkGroup gInfo sharedMsgId chunk msgMeta
_ -> messageError $ "unsupported message: " <> T.pack (show event)
currentMemCount <- withStore' $ \db -> getGroupCurrentMembersCount db user gInfo
let GroupInfo {chatSettings = ChatSettings {sendRcpts}} = gInfo
pure $
fromMaybe (sendRcptsSmallGroups user) sendRcpts
&& hasDeliveryReceipt (toCMEventTag event)
&& currentMemCount <= smallGroupsRcptsMemLimit
tryChatError (processChatMessage cmdId) >>= \case
Right (ACMsg _ chatMsg, withRcpt) -> do
ackMsg agentConnId cmdId msgMeta $ if withRcpt then Just "" else Nothing
when (membership.memberRole >= GRAdmin) $ forwardMsg_ chatMsg
Left e -> ackMsg agentConnId cmdId msgMeta Nothing >> throwError e
where
canSend mem a
| memberRole (mem :: GroupMember) <= GRObserver = messageError "member is not allowed to send messages"
| otherwise = a
processChatMessage :: Int64 -> m (AChatMessage, Bool)
processChatMessage cmdId = do
msg@(ACMsg _ chatMsg) <- parseAChatMessage conn msgMeta msgBody
checkIntegrity chatMsg `catchChatError` \_ -> pure ()
(msg,) <$> processEvent cmdId chatMsg
brokerTs = metaBrokerTs msgMeta
checkIntegrity :: ChatMessage e -> m ()
checkIntegrity ChatMessage {chatMsgEvent} = do
when checkForEvent $ checkIntegrityCreateItem (CDGroupRcv gInfo m) msgMeta
where
checkForEvent = case chatMsgEvent of
XMsgNew _ -> True
XFileCancel _ -> True
XFileAcptInv {} -> True
XGrpMemNew _ -> True
XGrpMemRole {} -> True
XGrpMemDel _ -> True
XGrpLeave -> True
XGrpDel -> True
XGrpInfo _ -> True
XGrpDirectInv {} -> True
_ -> False
processEvent :: MsgEncodingI e => CommandId -> ChatMessage e -> m Bool
processEvent cmdId chatMsg = do
(m', conn', msg@RcvMessage {chatMsgEvent = ACME _ event}) <- saveGroupRcvMsg user groupId m conn msgMeta cmdId msgBody chatMsg
updateChatLock "groupMessage" event
case event of
XMsgNew mc -> memberCanSend m' $ newGroupContentMessage gInfo m' mc msg brokerTs
XMsgFileDescr sharedMsgId fileDescr -> memberCanSend m' $ groupMessageFileDescription gInfo m' sharedMsgId fileDescr
XMsgUpdate sharedMsgId mContent ttl live -> memberCanSend m' $ groupMessageUpdate gInfo m' sharedMsgId mContent msg brokerTs ttl live
XMsgDel sharedMsgId memberId -> groupMessageDelete gInfo m' sharedMsgId memberId msg brokerTs
XMsgReact sharedMsgId (Just memberId) reaction add -> groupMsgReaction gInfo m' sharedMsgId memberId reaction add msg brokerTs
-- TODO discontinue XFile
XFile fInv -> processGroupFileInvitation' gInfo m' fInv msg brokerTs
XFileCancel sharedMsgId -> xFileCancelGroup gInfo m' sharedMsgId
XFileAcptInv sharedMsgId fileConnReq_ fName -> xFileAcptInvGroup gInfo m' sharedMsgId fileConnReq_ fName
XInfo p -> xInfoMember gInfo m' p
XGrpLinkMem p -> xGrpLinkMem gInfo m' conn' p
XGrpMemNew memInfo -> xGrpMemNew gInfo m' memInfo msg brokerTs
XGrpMemIntro memInfo -> xGrpMemIntro gInfo m' memInfo
XGrpMemInv memId introInv -> xGrpMemInv gInfo m' memId introInv
XGrpMemFwd memInfo introInv -> xGrpMemFwd gInfo m' memInfo introInv
XGrpMemRole memId memRole -> xGrpMemRole gInfo m' memId memRole msg brokerTs
XGrpMemCon memId -> xGrpMemCon gInfo m' memId
XGrpMemDel memId -> xGrpMemDel gInfo m' memId msg brokerTs
XGrpLeave -> xGrpLeave gInfo m' msg brokerTs
XGrpDel -> xGrpDel gInfo m' msg brokerTs
XGrpInfo p' -> xGrpInfo gInfo m' p' msg brokerTs
XGrpDirectInv connReq mContent_ -> memberCanSend m' $ xGrpDirectInv gInfo m' conn' connReq mContent_ msg brokerTs
XGrpMsgForward memberId msg' msgTs -> xGrpMsgForward gInfo m' memberId msg' msgTs
XInfoProbe probe -> xInfoProbe (COMGroupMember m') probe
XInfoProbeCheck probeHash -> xInfoProbeCheck (COMGroupMember m') probeHash
XInfoProbeOk probe -> xInfoProbeOk (COMGroupMember m') probe
BFileChunk sharedMsgId chunk -> bFileChunkGroup gInfo sharedMsgId chunk msgMeta
_ -> messageError $ "unsupported message: " <> T.pack (show event)
checkSendRcpt event
checkSendRcpt :: ChatMsgEvent e -> m Bool
checkSendRcpt event = do
currentMemCount <- withStore' $ \db -> getGroupCurrentMembersCount db user gInfo
let GroupInfo {chatSettings = ChatSettings {sendRcpts}} = gInfo
pure $
fromMaybe (sendRcptsSmallGroups user) sendRcpts
&& hasDeliveryReceipt (toCMEventTag event)
&& currentMemCount <= smallGroupsRcptsMemLimit
forwardMsg_ :: MsgEncodingI e => ChatMessage e -> m ()
forwardMsg_ chatMsg =
forM_ (forwardedGroupMsg chatMsg) $ \chatMsg' -> do
ChatConfig {highlyAvailable} <- asks config
-- members introduced to this invited member
introducedMembers <- if memberCategory m == GCInviteeMember
then withStore' $ \db -> getForwardIntroducedMembers db user m highlyAvailable
else pure []
-- invited members to which this member was introduced
invitedMembers <- withStore' $ \db -> getForwardInvitedMembers db user m highlyAvailable
let ms = introducedMembers <> invitedMembers
msg = XGrpMsgForward m.memberId chatMsg' brokerTs
unless (null ms) $
void $ sendGroupMessage user gInfo ms msg
RCVD msgMeta msgRcpt ->
withAckMessage' agentConnId conn msgMeta $
groupMsgReceived gInfo m conn msgMeta msgRcpt
@ -3821,6 +3880,11 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
_ -> toView $ CRReceivedContactRequest user cReq
_ -> pure ()
memberCanSend :: GroupMember -> m () -> m ()
memberCanSend GroupMember {memberRole} a
| memberRole <= GRObserver = messageError "member is not allowed to send messages"
| otherwise = a
incAuthErrCounter :: ConnectionEntity -> Connection -> AgentErrorType -> m ()
incAuthErrCounter connEntity conn err = do
case err of
@ -3864,7 +3928,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
withAckMessage cId cmdId msgMeta $ action $> False
withAckMessage :: ConnId -> CommandId -> MsgMeta -> m Bool -> m ()
withAckMessage cId cmdId MsgMeta {recipient = (msgId, _)} action = do
withAckMessage cId cmdId msgMeta action = do
-- [async agent commands] command should be asynchronous, continuation is ackMsgDeliveryEvent
-- TODO catching error and sending ACK after an error, particularly if it is a database error, will result in the message not processed (and no notification to the user).
-- Possible solutions are:
@ -3872,10 +3936,11 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
-- 2) stabilize database
-- 3) show screen of death to the user asking to restart
tryChatError action >>= \case
Right withRcpt -> ack $ if withRcpt then Just "" else Nothing
Left e -> ack Nothing >> throwError e
where
ack rcpt = withAgent $ \a -> ackMessageAsync a (aCorrId cmdId) cId msgId rcpt
Right withRcpt -> ackMsg cId cmdId msgMeta $ if withRcpt then Just "" else Nothing
Left e -> ackMsg cId cmdId msgMeta Nothing >> throwError e
ackMsg :: ConnId -> CommandId -> MsgMeta -> Maybe MsgReceiptInfo -> m ()
ackMsg cId cmdId MsgMeta {recipient = (msgId, _)} rcpt = withAgent $ \a -> ackMessageAsync a (aCorrId cmdId) cId msgId rcpt
ackMsgDeliveryEvent :: Connection -> CommandId -> m ()
ackMsgDeliveryEvent Connection {connId} ackCmdId =
@ -3995,8 +4060,9 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
newChatItem (CIRcvMsgContent content) (snd <$> file_) timed_ live
autoAcceptFile file_
where
brokerTs = metaBrokerTs msgMeta
newChatItem ciContent ciFile_ timed_ live = do
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ msgMeta ciContent ciFile_ timed_ live
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs ciContent ciFile_ timed_ live
reactions <- maybe (pure []) (\sharedMsgId -> withStore' $ \db -> getDirectCIReactions db ct sharedMsgId) sharedMsgId_
toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci {reactions})
@ -4011,8 +4077,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
fileId <- withStore $ \db -> getFileIdBySharedMsgId db userId contactId sharedMsgId
processFDMessage fileId fileDescr
groupMessageFileDescription :: GroupInfo -> GroupMember -> SharedMsgId -> FileDescr -> MsgMeta -> m ()
groupMessageFileDescription GroupInfo {groupId} _m sharedMsgId fileDescr _msgMeta = do
groupMessageFileDescription :: GroupInfo -> GroupMember -> SharedMsgId -> FileDescr -> m ()
groupMessageFileDescription GroupInfo {groupId} _m sharedMsgId fileDescr = do
fileId <- withStore $ \db -> getGroupFileIdBySharedMsgId db userId groupId sharedMsgId
processFDMessage fileId fileDescr
@ -4030,17 +4096,6 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
(RFSAccepted _, Just XFTPRcvFile {}) -> receiveViaCompleteFD user fileId rfd cryptoArgs
_ -> pure ()
cancelMessageFile :: Contact -> SharedMsgId -> MsgMeta -> m ()
cancelMessageFile ct _sharedMsgId msgMeta = do
checkIntegrityCreateItem (CDDirectRcv ct) msgMeta
-- find the original chat item and file
-- mark file as cancelled, remove description if exists
pure ()
cancelGroupMessageFile :: GroupInfo -> GroupMember -> SharedMsgId -> MsgMeta -> m ()
cancelGroupMessageFile _gInfo _m _sharedMsgId _msgMeta = do
pure ()
processFileInvitation :: Maybe FileInvitation -> MsgContent -> (DB.Connection -> FileInvitation -> Maybe InlineFileMode -> Integer -> ExceptT StoreError IO RcvFileTransfer) -> m (Maybe (RcvFileTransfer, CIFile 'MDRcv))
processFileInvitation fInv_ mc createRcvFT = forM fInv_ $ \fInv@FileInvitation {fileName, fileSize} -> do
ChatConfig {fileChunkSize} <- asks config
@ -4067,13 +4122,13 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
-- received an update from the sender, so that it can be referenced later (e.g. by broadcast delete).
-- Chat item and update message which created it will have different sharedMsgId in this case...
let timed_ = rcvContactCITimed ct ttl
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg (Just sharedMsgId) msgMeta content Nothing timed_ live
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg (Just sharedMsgId) brokerTs content Nothing timed_ live
ci' <- withStore' $ \db -> do
createChatItemVersion db (chatItemId' ci) brokerTs mc
updateDirectChatItem' db user contactId ci content live Nothing
toView $ CRChatItemUpdated user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci')
where
MsgMeta {broker = (_, brokerTs)} = msgMeta
brokerTs = metaBrokerTs msgMeta
content = CIRcvMsgContent mc
live = fromMaybe False live_
updateRcvChatItem = do
@ -4128,8 +4183,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
else pure Nothing
mapM_ toView cr_
groupMsgReaction :: GroupInfo -> GroupMember -> SharedMsgId -> MemberId -> MsgReaction -> Bool -> RcvMessage -> MsgMeta -> m ()
groupMsgReaction g@GroupInfo {groupId} m sharedMsgId itemMemberId reaction add RcvMessage {msgId} MsgMeta {broker = (_, brokerTs)} = do
groupMsgReaction :: GroupInfo -> GroupMember -> SharedMsgId -> MemberId -> MsgReaction -> Bool -> RcvMessage -> UTCTime -> m ()
groupMsgReaction g@GroupInfo {groupId} m sharedMsgId itemMemberId reaction add RcvMessage {msgId} brokerTs = do
when (groupFeatureAllowed SGFReactions g) $ do
rs <- withStore' $ \db -> getGroupReactions db g m itemMemberId sharedMsgId False
when (reactionAllowed add reaction rs) $ do
@ -4158,8 +4213,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
ChatErrorStore (SEChatItemSharedMsgIdNotFound sharedMsgId) -> handle sharedMsgId
e -> throwError e
newGroupContentMessage :: GroupInfo -> GroupMember -> MsgContainer -> RcvMessage -> MsgMeta -> m ()
newGroupContentMessage gInfo m@GroupMember {memberId, memberRole} mc msg@RcvMessage {sharedMsgId_} msgMeta
newGroupContentMessage :: GroupInfo -> GroupMember -> MsgContainer -> RcvMessage -> UTCTime -> m ()
newGroupContentMessage gInfo m@GroupMember {memberId, memberRole} mc msg@RcvMessage {sharedMsgId_} brokerTs
| isVoice content && not (groupFeatureAllowed SGFVoice gInfo) = rejected GFVoice
| not (isVoice content) && isJust fInv_ && not (groupFeatureAllowed SGFFiles gInfo) = rejected GFFiles
| otherwise = do
@ -4179,38 +4234,37 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
| moderatorRole < GRAdmin || moderatorRole < memberRole =
createItem timed_ live
| groupFeatureAllowed SGFFullDelete gInfo = do
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ msgMeta CIRcvModerated Nothing timed_ False
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs CIRcvModerated Nothing timed_ False
ci' <- withStore' $ \db -> updateGroupChatItemModerated db user gInfo ci moderator moderatedAt
toView $ CRNewChatItem user $ AChatItem SCTGroup SMDRcv (GroupChat gInfo) ci'
| otherwise = do
file_ <- processFileInvitation fInv_ content $ \db -> createRcvGroupFileTransfer db userId m
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ msgMeta (CIRcvMsgContent content) (snd <$> file_) timed_ False
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs (CIRcvMsgContent content) (snd <$> file_) timed_ False
toView =<< markGroupCIDeleted user gInfo ci createdByMsgId False (Just moderator) moderatedAt
createItem timed_ live = do
file_ <- processFileInvitation fInv_ content $ \db -> createRcvGroupFileTransfer db userId m
newChatItem (CIRcvMsgContent content) (snd <$> file_) timed_ live
when (showMessages $ memberSettings m) $ autoAcceptFile file_
newChatItem ciContent ciFile_ timed_ live = do
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ msgMeta ciContent ciFile_ timed_ live
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs ciContent ciFile_ timed_ live
ci' <- blockedMember m ci $ withStore' $ \db -> markGroupChatItemBlocked db user gInfo ci
reactions <- maybe (pure []) (\sharedMsgId -> withStore' $ \db -> getGroupCIReactions db gInfo memberId sharedMsgId) sharedMsgId_
groupMsgToView gInfo m ci' {reactions} msgMeta
groupMsgToView gInfo ci' {reactions}
groupMessageUpdate :: GroupInfo -> GroupMember -> SharedMsgId -> MsgContent -> RcvMessage -> MsgMeta -> Maybe Int -> Maybe Bool -> m ()
groupMessageUpdate gInfo@GroupInfo {groupId} m@GroupMember {groupMemberId, memberId} sharedMsgId mc msg@RcvMessage {msgId} msgMeta ttl_ live_ =
groupMessageUpdate :: GroupInfo -> GroupMember -> SharedMsgId -> MsgContent -> RcvMessage -> UTCTime -> Maybe Int -> Maybe Bool -> m ()
groupMessageUpdate gInfo@GroupInfo {groupId} m@GroupMember {groupMemberId, memberId} sharedMsgId mc msg@RcvMessage {msgId} brokerTs ttl_ live_ =
updateRcvChatItem `catchCINotFound` \_ -> do
-- This patches initial sharedMsgId into chat item when locally deleted chat item
-- received an update from the sender, so that it can be referenced later (e.g. by broadcast delete).
-- Chat item and update message which created it will have different sharedMsgId in this case...
let timed_ = rcvGroupCITimed gInfo ttl_
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg (Just sharedMsgId) msgMeta content Nothing timed_ live
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg (Just sharedMsgId) brokerTs content Nothing timed_ live
ci' <- withStore' $ \db -> do
createChatItemVersion db (chatItemId' ci) brokerTs mc
ci' <- updateGroupChatItem db user groupId ci content live Nothing
blockedMember m ci' $ markGroupChatItemBlocked db user gInfo ci'
toView $ CRChatItemUpdated user (AChatItem SCTGroup SMDRcv (GroupChat gInfo) ci')
where
MsgMeta {broker = (_, brokerTs)} = msgMeta
content = CIRcvMsgContent mc
live = fromMaybe False live_
updateRcvChatItem = do
@ -4233,8 +4287,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
else messageError "x.msg.update: group member attempted to update a message of another member"
_ -> messageError "x.msg.update: group member attempted invalid message update"
groupMessageDelete :: GroupInfo -> GroupMember -> SharedMsgId -> Maybe MemberId -> RcvMessage -> MsgMeta -> m ()
groupMessageDelete gInfo@GroupInfo {groupId, membership} m@GroupMember {memberId, memberRole = senderRole} sharedMsgId sndMemberId_ RcvMessage {msgId} MsgMeta {broker = (_, brokerTs)} = do
groupMessageDelete :: GroupInfo -> GroupMember -> SharedMsgId -> Maybe MemberId -> RcvMessage -> UTCTime -> m ()
groupMessageDelete gInfo@GroupInfo {groupId, membership} m@GroupMember {memberId, memberRole = senderRole} sharedMsgId sndMemberId_ RcvMessage {msgId} brokerTs = do
let msgMemberId = fromMaybe memberId sndMemberId_
withStore' (\db -> runExceptT $ getGroupMemberCIBySharedMsgId db user groupId msgMemberId sharedMsgId) >>= \case
Right (CChatItem _ ci@ChatItem {chatDir}) -> case chatDir of
@ -4271,20 +4325,22 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
RcvFileTransfer {fileId, xftpRcvFile} <- withStore $ \db -> createRcvFileTransfer db userId ct fInv inline fileChunkSize
let fileProtocol = if isJust xftpRcvFile then FPXFTP else FPSMP
ciFile = Just $ CIFile {fileId, fileName, fileSize, fileSource = Nothing, fileStatus = CIFSRcvInvitation, fileProtocol}
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ msgMeta (CIRcvMsgContent $ MCFile "") ciFile Nothing False
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs (CIRcvMsgContent $ MCFile "") ciFile Nothing False
toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci)
where
brokerTs = metaBrokerTs msgMeta
-- TODO remove once XFile is discontinued
processGroupFileInvitation' :: GroupInfo -> GroupMember -> FileInvitation -> RcvMessage -> MsgMeta -> m ()
processGroupFileInvitation' gInfo m fInv@FileInvitation {fileName, fileSize} msg@RcvMessage {sharedMsgId_} msgMeta = do
processGroupFileInvitation' :: GroupInfo -> GroupMember -> FileInvitation -> RcvMessage -> UTCTime -> m ()
processGroupFileInvitation' gInfo m fInv@FileInvitation {fileName, fileSize} msg@RcvMessage {sharedMsgId_} brokerTs = do
ChatConfig {fileChunkSize} <- asks config
inline <- receiveInlineMode fInv Nothing fileChunkSize
RcvFileTransfer {fileId, xftpRcvFile} <- withStore $ \db -> createRcvGroupFileTransfer db userId m fInv inline fileChunkSize
let fileProtocol = if isJust xftpRcvFile then FPXFTP else FPSMP
ciFile = Just $ CIFile {fileId, fileName, fileSize, fileSource = Nothing, fileStatus = CIFSRcvInvitation, fileProtocol}
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ msgMeta (CIRcvMsgContent $ MCFile "") ciFile Nothing False
ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg sharedMsgId_ brokerTs (CIRcvMsgContent $ MCFile "") ciFile Nothing False
ci' <- blockedMember m ci $ withStore' $ \db -> markGroupChatItemBlocked db user gInfo ci
groupMsgToView gInfo m ci' msgMeta
groupMsgToView gInfo ci'
blockedMember :: Monad m' => GroupMember -> ChatItem c d -> m' (ChatItem c d) -> m' (ChatItem c d)
blockedMember m ci blockedCI
@ -4391,9 +4447,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
_ -> pure ()
receiveFileChunk ft Nothing meta chunk
xFileCancelGroup :: GroupInfo -> GroupMember -> SharedMsgId -> MsgMeta -> m ()
xFileCancelGroup g@GroupInfo {groupId} mem@GroupMember {groupMemberId, memberId} sharedMsgId msgMeta = do
checkIntegrityCreateItem (CDGroupRcv g mem) msgMeta
xFileCancelGroup :: GroupInfo -> GroupMember -> SharedMsgId -> m ()
xFileCancelGroup GroupInfo {groupId} GroupMember {groupMemberId, memberId} sharedMsgId = do
fileId <- withStore $ \db -> getGroupFileIdBySharedMsgId db userId groupId sharedMsgId
CChatItem msgDir ChatItem {chatDir} <- withStore $ \db -> getGroupChatItemBySharedMsgId db user groupId groupMemberId sharedMsgId
case (msgDir, chatDir) of
@ -4408,9 +4463,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
else messageError "x.file.cancel: group member attempted to cancel file of another member" -- shouldn't happen now that query includes group member id
(SMDSnd, _) -> messageError "x.file.cancel: group member attempted invalid file cancel"
xFileAcptInvGroup :: GroupInfo -> GroupMember -> SharedMsgId -> Maybe ConnReqInvitation -> String -> MsgMeta -> m ()
xFileAcptInvGroup g@GroupInfo {groupId} m@GroupMember {activeConn} sharedMsgId fileConnReq_ fName msgMeta = do
checkIntegrityCreateItem (CDGroupRcv g m) msgMeta
xFileAcptInvGroup :: GroupInfo -> GroupMember -> SharedMsgId -> Maybe ConnReqInvitation -> String -> m ()
xFileAcptInvGroup GroupInfo {groupId} m@GroupMember {activeConn} sharedMsgId fileConnReq_ fName = do
fileId <- withStore $ \db -> getGroupFileIdBySharedMsgId db userId groupId sharedMsgId
(AChatItem _ _ _ ci) <- withStore $ \db -> getChatItemByFileId db user fileId
assertSMPAcceptNotProhibited ci
@ -4439,9 +4493,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
_ -> messageError "x.file.acpt.inv: member connection is not active"
else messageError "x.file.acpt.inv: fileName is different from expected"
groupMsgToView :: GroupInfo -> GroupMember -> ChatItem 'CTGroup 'MDRcv -> MsgMeta -> m ()
groupMsgToView gInfo m ci msgMeta = do
checkIntegrityCreateItem (CDGroupRcv gInfo m) msgMeta
groupMsgToView :: GroupInfo -> ChatItem 'CTGroup 'MDRcv -> m ()
groupMsgToView gInfo ci =
toView $ CRNewChatItem user (AChatItem SCTGroup SMDRcv (GroupChat gInfo) ci)
processGroupInvitation :: Contact -> GroupInvitation -> RcvMessage -> MsgMeta -> m ()
@ -4467,11 +4520,12 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
toView $ CRUserAcceptedGroupSent user gInfo {membership = membership {memberStatus = GSMemAccepted}} (Just ct)
else do
let content = CIRcvGroupInvitation (CIGroupInvitation {groupId, groupMemberId, localDisplayName, groupProfile, status = CIGISPending}) memRole
ci <- saveRcvChatItem user (CDDirectRcv ct) msg msgMeta content
ci <- saveRcvChatItem user (CDDirectRcv ct) msg brokerTs content
withStore' $ \db -> setGroupInvitationChatItemId db user groupId (chatItemId' ci)
toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci)
toView $ CRReceivedGroupInvitation {user, groupInfo = gInfo, contact = ct, fromMemberRole = fromRole, memberRole = memRole}
where
brokerTs = metaBrokerTs msgMeta
sameGroupLinkId :: Maybe GroupLinkId -> Maybe GroupLinkId -> Bool
sameGroupLinkId (Just gli) (Just gli') = gli == gli'
sameGroupLinkId _ _ = False
@ -4495,13 +4549,15 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
forM_ contactConns $ \conn -> withStore' $ \db -> updateConnectionStatus db conn ConnDeleted
activeConn' <- forM (contactConn ct') $ \conn -> pure conn {connStatus = ConnDeleted}
let ct'' = ct' {activeConn = activeConn'} :: Contact
ci <- saveRcvChatItem user (CDDirectRcv ct'') msg msgMeta (CIRcvDirectEvent RDEContactDeleted)
ci <- saveRcvChatItem user (CDDirectRcv ct'') msg brokerTs (CIRcvDirectEvent RDEContactDeleted)
toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat ct'') ci)
toView $ CRContactDeletedByContact user ct''
else do
contactConns <- withStore' $ \db -> getContactConnections db userId c
deleteAgentConnectionsAsync user $ map aConnId contactConns
withStore' $ \db -> deleteContact db user c
where
brokerTs = metaBrokerTs msgMeta
processContactProfileUpdate :: Contact -> Profile -> Bool -> m Contact
processContactProfileUpdate c@Contact {profile = p} p' createItems
@ -4532,9 +4588,8 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
| otherwise -> Nothing
in setPreference_ SCFTimedMessages ctUserTMPref' ctUserPrefs
-- TODO use for member profile update
-- xInfoMember :: GroupInfo -> GroupMember -> Profile -> m ()
-- xInfoMember gInfo m p' = void $ processMemberProfileUpdate gInfo m p'
xInfoMember :: GroupInfo -> GroupMember -> Profile -> m ()
xInfoMember gInfo m p' = void $ processMemberProfileUpdate gInfo m p'
xGrpLinkMem :: GroupInfo -> GroupMember -> Connection -> Profile -> m ()
xGrpLinkMem gInfo@GroupInfo {membership} m@GroupMember {groupMemberId, memberCategory} Connection {viaGroupLink} p' = do
@ -4666,9 +4721,10 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
toView $ CRNewChatItem user $ AChatItem SCTDirect SMDRcv (DirectChat ct) ci
else featureRejected CFCalls
where
saveCallItem status = saveRcvChatItem user (CDDirectRcv ct) msg msgMeta (CIRcvCall status 0)
brokerTs = metaBrokerTs msgMeta
saveCallItem status = saveRcvChatItem user (CDDirectRcv ct) msg brokerTs (CIRcvCall status 0)
featureRejected f = do
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ msgMeta (CIRcvChatFeatureRejected f) Nothing Nothing False
ci <- saveRcvChatItem' user (CDDirectRcv ct) msg sharedMsgId_ brokerTs (CIRcvChatFeatureRejected f) Nothing Nothing False
toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat ct) ci)
-- to party initiating call
@ -4827,21 +4883,21 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
-- TODO show/log error, other events in SMP confirmation
_ -> pure conn'
xGrpMemNew :: GroupInfo -> GroupMember -> MemberInfo -> RcvMessage -> MsgMeta -> m ()
xGrpMemNew gInfo m memInfo@(MemberInfo memId memRole _ memberProfile) msg msgMeta = do
xGrpMemNew :: GroupInfo -> GroupMember -> MemberInfo -> RcvMessage -> UTCTime -> m ()
xGrpMemNew gInfo m memInfo@(MemberInfo memId memRole _ memberProfile) msg brokerTs = do
checkHostRole m memRole
members <- withStore' $ \db -> getGroupMembers db user gInfo
unless (sameMemberId memId $ membership gInfo) $
if isMember memId gInfo members
then messageError "x.grp.mem.new error: member already exists"
else do
newMember@GroupMember {groupMemberId} <- withStore $ \db -> createNewGroupMember db user gInfo memInfo GCPostMember GSMemAnnounced
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg msgMeta (CIRcvGroupEvent $ RGEMemberAdded groupMemberId memberProfile)
groupMsgToView gInfo m ci msgMeta
newMember@GroupMember {groupMemberId} <- withStore $ \db -> createNewGroupMember db user gInfo m memInfo GCPostMember GSMemAnnounced
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent $ RGEMemberAdded groupMemberId memberProfile)
groupMsgToView gInfo ci
toView $ CRJoinedGroupMemberConnecting user gInfo m newMember
xGrpMemIntro :: GroupInfo -> GroupMember -> MemberInfo -> m ()
xGrpMemIntro gInfo@GroupInfo {chatSettings} m@GroupMember {memberRole, localDisplayName = c} memInfo@(MemberInfo memId _ memberChatVRange _) = do
xGrpMemIntro gInfo@GroupInfo {chatSettings} m@GroupMember {memberRole, localDisplayName = c} memInfo@(MemberInfo memId _ memChatVRange _) = do
case memberCategory m of
GCHostMember -> do
members <- withStore' $ \db -> getGroupMembers db user gInfo
@ -4852,7 +4908,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
subMode <- chatReadVar subscriptionMode
-- [async agent commands] commands should be asynchronous, continuation is to send XGrpMemInv - have to remember one has completed and process on second
groupConnIds <- createConn subMode
directConnIds <- case memberChatVRange of
directConnIds <- case memChatVRange of
Nothing -> Just <$> createConn subMode
Just mcvr
| isCompatibleRange (fromChatVRange mcvr) groupNoDirectVRange -> pure Nothing
@ -4884,7 +4940,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
_ -> messageError "x.grp.mem.inv can be only sent by invitee member"
xGrpMemFwd :: GroupInfo -> GroupMember -> MemberInfo -> IntroInvitation -> m ()
xGrpMemFwd gInfo@GroupInfo {membership, chatSettings} m memInfo@(MemberInfo memId memRole memberChatVRange _) introInv@IntroInvitation {groupConnReq, directConnReq} = do
xGrpMemFwd gInfo@GroupInfo {membership, chatSettings} m memInfo@(MemberInfo memId memRole memChatVRange _) introInv@IntroInvitation {groupConnReq, directConnReq} = do
checkHostRole m memRole
members <- withStore' $ \db -> getGroupMembers db user gInfo
toMember <- case find (sameMemberId memId) members of
@ -4892,7 +4948,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
-- the situation when member does not exist is an error
-- member receiving x.grp.mem.fwd should have also received x.grp.mem.new prior to that.
-- For now, this branch compensates for the lack of delayed message delivery.
Nothing -> withStore $ \db -> createNewGroupMember db user gInfo memInfo GCPostMember GSMemAnnounced
Nothing -> withStore $ \db -> createNewGroupMember db user gInfo m memInfo GCPostMember GSMemAnnounced
Just m' -> pure m'
withStore' $ \db -> saveMemberInvitation db toMember introInv
subMode <- chatReadVar subscriptionMode
@ -4902,11 +4958,11 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
groupConnIds <- joinAgentConnectionAsync user (chatHasNtfs chatSettings) groupConnReq dm subMode
directConnIds <- forM directConnReq $ \dcr -> joinAgentConnectionAsync user True dcr dm subMode
let customUserProfileId = localProfileId <$> incognitoMembershipProfile gInfo
mcvr = maybe chatInitialVRange fromChatVRange memberChatVRange
mcvr = maybe chatInitialVRange fromChatVRange memChatVRange
withStore' $ \db -> createIntroToMemberContact db user m toMember mcvr groupConnIds directConnIds customUserProfileId subMode
xGrpMemRole :: GroupInfo -> GroupMember -> MemberId -> GroupMemberRole -> RcvMessage -> MsgMeta -> m ()
xGrpMemRole gInfo@GroupInfo {membership} m@GroupMember {memberRole = senderRole} memId memRole msg msgMeta
xGrpMemRole :: GroupInfo -> GroupMember -> MemberId -> GroupMemberRole -> RcvMessage -> UTCTime -> m ()
xGrpMemRole gInfo@GroupInfo {membership} m@GroupMember {memberRole = senderRole} memId memRole msg brokerTs
| memberId (membership :: GroupMember) == memId =
let gInfo' = gInfo {membership = membership {memberRole = memRole}}
in changeMemberRole gInfo' membership $ RGEUserRole memRole
@ -4920,16 +4976,54 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
| senderRole < GRAdmin || senderRole < fromRole = messageError "x.grp.mem.role with insufficient member permissions"
| otherwise = do
withStore' $ \db -> updateGroupMemberRole db user member memRole
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg msgMeta (CIRcvGroupEvent gEvent)
groupMsgToView gInfo m ci msgMeta
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent gEvent)
groupMsgToView gInfo ci
toView CRMemberRole {user, groupInfo = gInfo', byMember = m, member = member {memberRole = memRole}, fromRole, toRole = memRole}
checkHostRole :: GroupMember -> GroupMemberRole -> m ()
checkHostRole GroupMember {memberRole, localDisplayName} memRole =
when (memberRole < GRAdmin || memberRole < memRole) $ throwChatError (CEGroupContactRole localDisplayName)
xGrpMemDel :: GroupInfo -> GroupMember -> MemberId -> RcvMessage -> MsgMeta -> m ()
xGrpMemDel gInfo@GroupInfo {membership} m@GroupMember {memberRole = senderRole} memId msg msgMeta = do
xGrpMemCon :: GroupInfo -> GroupMember -> MemberId -> m ()
xGrpMemCon gInfo sendingMember memId = do
refMember <- withStore $ \db -> getGroupMemberByMemberId db user gInfo memId
case (memberCategory sendingMember, memberCategory refMember) of
(GCInviteeMember, GCInviteeMember) ->
withStore' (\db -> runExceptT $ getIntroduction db refMember sendingMember) >>= \case
Right intro -> inviteeXGrpMemCon intro
Left _ -> withStore' (\db -> runExceptT $ getIntroduction db sendingMember refMember) >>= \case
Right intro -> forwardMemberXGrpMemCon intro
Left _ -> messageWarning "x.grp.mem.con: no introduction"
(GCInviteeMember, _) ->
withStore' (\db -> runExceptT $ getIntroduction db refMember sendingMember) >>= \case
Right intro -> inviteeXGrpMemCon intro
Left _ -> messageWarning "x.grp.mem.con: no introduction"
(_, GCInviteeMember) ->
withStore' (\db -> runExceptT $ getIntroduction db sendingMember refMember) >>= \case
Right intro -> forwardMemberXGrpMemCon intro
Left _ -> messageWarning "x.grp.mem.con: no introductiosupportn"
-- Note: we can allow XGrpMemCon to all member categories if we decide to support broader group forwarding,
-- deduplication (see saveGroupRcvMsg, saveGroupFwdRcvMsg) already supports sending XGrpMemCon
-- to any forwarding member, not only host/inviting member;
-- database would track all members connections then
-- (currently it's done via group_member_intros for introduced connections only)
_ ->
messageWarning "x.grp.mem.con: neither member is invitee"
where
inviteeXGrpMemCon :: GroupMemberIntro -> m ()
inviteeXGrpMemCon GroupMemberIntro {introId, introStatus}
| introStatus == GMIntroReConnected = updateStatus introId GMIntroConnected
| introStatus `elem` [GMIntroToConnected, GMIntroConnected] = pure ()
| otherwise = updateStatus introId GMIntroToConnected
forwardMemberXGrpMemCon :: GroupMemberIntro -> m ()
forwardMemberXGrpMemCon GroupMemberIntro {introId, introStatus}
| introStatus == GMIntroToConnected = updateStatus introId GMIntroConnected
| introStatus `elem` [GMIntroReConnected, GMIntroConnected] = pure ()
| otherwise = updateStatus introId GMIntroReConnected
updateStatus introId status = withStore' $ \db -> updateIntroStatus db introId status
xGrpMemDel :: GroupInfo -> GroupMember -> MemberId -> RcvMessage -> UTCTime -> m ()
xGrpMemDel gInfo@GroupInfo {membership} m@GroupMember {memberRole = senderRole} memId msg brokerTs = do
members <- withStore' $ \db -> getGroupMembers db user gInfo
if memberId (membership :: GroupMember) == memId
then checkRole membership $ do
@ -4955,23 +5049,20 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
messageError "x.grp.mem.del with insufficient member permissions"
| otherwise = a
deleteMemberItem gEvent = do
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg msgMeta (CIRcvGroupEvent gEvent)
groupMsgToView gInfo m ci msgMeta
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent gEvent)
groupMsgToView gInfo ci
sameMemberId :: MemberId -> GroupMember -> Bool
sameMemberId memId GroupMember {memberId} = memId == memberId
xGrpLeave :: GroupInfo -> GroupMember -> RcvMessage -> MsgMeta -> m ()
xGrpLeave gInfo m msg msgMeta = do
xGrpLeave :: GroupInfo -> GroupMember -> RcvMessage -> UTCTime -> m ()
xGrpLeave gInfo m msg brokerTs = do
deleteMemberConnection user m
-- member record is not deleted to allow creation of "member left" chat item
withStore' $ \db -> updateGroupMemberStatus db userId m GSMemLeft
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg msgMeta (CIRcvGroupEvent RGEMemberLeft)
groupMsgToView gInfo m ci msgMeta
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent RGEMemberLeft)
groupMsgToView gInfo ci
toView $ CRLeftMember user gInfo m {memberStatus = GSMemLeft}
xGrpDel :: GroupInfo -> GroupMember -> RcvMessage -> MsgMeta -> m ()
xGrpDel gInfo@GroupInfo {membership} m@GroupMember {memberRole} msg msgMeta = do
xGrpDel :: GroupInfo -> GroupMember -> RcvMessage -> UTCTime -> m ()
xGrpDel gInfo@GroupInfo {membership} m@GroupMember {memberRole} msg brokerTs = do
when (memberRole /= GROwner) $ throwChatError $ CEGroupUserRole gInfo GROwner
ms <- withStore' $ \db -> do
members <- getGroupMembers db user gInfo
@ -4979,24 +5070,24 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
pure members
-- member records are not deleted to keep history
deleteMembersConnections user ms
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg msgMeta (CIRcvGroupEvent RGEGroupDeleted)
groupMsgToView gInfo m ci msgMeta
ci <- saveRcvChatItem user (CDGroupRcv gInfo m) msg brokerTs (CIRcvGroupEvent RGEGroupDeleted)
groupMsgToView gInfo ci
toView $ CRGroupDeleted user gInfo {membership = membership {memberStatus = GSMemGroupDeleted}} m
xGrpInfo :: GroupInfo -> GroupMember -> GroupProfile -> RcvMessage -> MsgMeta -> m ()
xGrpInfo g@GroupInfo {groupProfile = p} m@GroupMember {memberRole} p' msg msgMeta
xGrpInfo :: GroupInfo -> GroupMember -> GroupProfile -> RcvMessage -> UTCTime -> m ()
xGrpInfo g@GroupInfo {groupProfile = p} m@GroupMember {memberRole} p' msg brokerTs
| memberRole < GROwner = messageError "x.grp.info with insufficient member permissions"
| otherwise = unless (p == p') $ do
g' <- withStore $ \db -> updateGroupProfile db user g p'
toView $ CRGroupUpdated user g g' (Just m)
let cd = CDGroupRcv g' m
unless (sameGroupProfileInfo p p') $ do
ci <- saveRcvChatItem user cd msg msgMeta (CIRcvGroupEvent $ RGEGroupUpdated p')
groupMsgToView g' m ci msgMeta
ci <- saveRcvChatItem user cd msg brokerTs (CIRcvGroupEvent $ RGEGroupUpdated p')
groupMsgToView g' ci
createGroupFeatureChangedItems user cd CIRcvGroupFeature g g'
xGrpDirectInv :: GroupInfo -> GroupMember -> Connection -> ConnReqInvitation -> Maybe MsgContent -> RcvMessage -> MsgMeta -> m ()
xGrpDirectInv g m mConn connReq mContent_ msg msgMeta = do
xGrpDirectInv :: GroupInfo -> GroupMember -> Connection -> ConnReqInvitation -> Maybe MsgContent -> RcvMessage -> UTCTime -> m ()
xGrpDirectInv g m mConn connReq mContent_ msg brokerTs = do
unless (groupFeatureAllowed SGFDirectMessages g) $ messageError "x.grp.direct.inv: direct messages not allowed"
let GroupMember {memberContactId} = m
subMode <- chatReadVar subscriptionMode
@ -5032,11 +5123,10 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
dm <- directMessage $ XInfo p
joinAgentConnectionAsync user True connReq dm subMode
createItems mCt' m' = do
checkIntegrityCreateItem (CDGroupRcv g m') msgMeta
createInternalChatItem user (CDGroupRcv g m') (CIRcvGroupEvent RGEMemberCreatedContact) Nothing
toView $ CRNewMemberContactReceivedInv user mCt' g m'
forM_ mContent_ $ \mc -> do
ci <- saveRcvChatItem user (CDDirectRcv mCt') msg msgMeta (CIRcvMsgContent mc)
ci <- saveRcvChatItem user (CDDirectRcv mCt') msg brokerTs (CIRcvMsgContent mc)
toView $ CRNewChatItem user (AChatItem SCTDirect SMDRcv (DirectChat mCt') ci)
securityCodeChanged :: Contact -> m ()
@ -5044,6 +5134,33 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
toView $ CRContactVerificationReset user ct
createInternalChatItem user (CDDirectRcv ct) (CIRcvConnEvent RCEVerificationCodeReset) Nothing
xGrpMsgForward :: GroupInfo -> GroupMember -> MemberId -> ChatMessage 'Json -> UTCTime -> m ()
xGrpMsgForward gInfo@GroupInfo {groupId} m memberId msg msgTs = do
when (m.memberRole < GRAdmin) $ throwChatError (CEGroupContactRole m.localDisplayName)
author <- withStore $ \db -> getGroupMemberByMemberId db user gInfo memberId
processForwardedMsg author msg
where
-- Note: forwarded group events (see forwardedGroupMsg) should include msgId to be deduplicated
processForwardedMsg :: GroupMember -> ChatMessage 'Json -> m ()
processForwardedMsg author chatMsg = do
let body = LB.toStrict $ J.encode msg
rcvMsg@RcvMessage {chatMsgEvent = ACME _ event} <- saveGroupFwdRcvMsg user groupId m author body chatMsg
case event of
XMsgNew mc -> memberCanSend author $ newGroupContentMessage gInfo author mc rcvMsg msgTs
XMsgFileDescr sharedMsgId fileDescr -> memberCanSend author $ groupMessageFileDescription gInfo author sharedMsgId fileDescr
XMsgUpdate sharedMsgId mContent ttl live -> memberCanSend author $ groupMessageUpdate gInfo author sharedMsgId mContent rcvMsg msgTs ttl live
XMsgDel sharedMsgId memId -> groupMessageDelete gInfo author sharedMsgId memId rcvMsg msgTs
XMsgReact sharedMsgId (Just memId) reaction add -> groupMsgReaction gInfo author sharedMsgId memId reaction add rcvMsg msgTs
XFileCancel sharedMsgId -> xFileCancelGroup gInfo author sharedMsgId
XInfo p -> xInfoMember gInfo author p
XGrpMemNew memInfo -> xGrpMemNew gInfo author memInfo rcvMsg msgTs
XGrpMemRole memId memRole -> xGrpMemRole gInfo author memId memRole rcvMsg msgTs
XGrpMemDel memId -> xGrpMemDel gInfo author memId rcvMsg msgTs
XGrpLeave -> xGrpLeave gInfo author rcvMsg msgTs
XGrpDel -> xGrpDel gInfo author rcvMsg msgTs
XGrpInfo p' -> xGrpInfo gInfo author p' rcvMsg msgTs
_ -> messageError $ "x.grp.msg.forward: unsupported forwarded event " <> T.pack (show $ toCMEventTag event)
directMsgReceived :: Contact -> Connection -> MsgMeta -> NonEmpty MsgReceipt -> m ()
directMsgReceived ct conn@Connection {connId} msgMeta msgRcpts = do
checkIntegrityCreateItem (CDDirectRcv ct) msgMeta
@ -5092,6 +5209,12 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
toView $ CRChatItemStatusUpdated user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) chatItem)
_ -> pure ()
metaBrokerTs :: MsgMeta -> UTCTime
metaBrokerTs MsgMeta {broker = (_, brokerTs)} = brokerTs
sameMemberId :: MemberId -> GroupMember -> Bool
sameMemberId memId GroupMember {memberId} = memId == memberId
updatePeerChatVRange :: ChatMonad m => Connection -> VersionRange -> m Connection
updatePeerChatVRange conn@Connection {connId, peerChatVRange} msgChatVRange = do
let jMsgChatVRange = JVersionRange msgChatVRange
@ -5101,6 +5224,18 @@ updatePeerChatVRange conn@Connection {connId, peerChatVRange} msgChatVRange = do
pure conn {peerChatVRange = jMsgChatVRange}
else pure conn
updateMemberChatVRange :: ChatMonad m => GroupMember -> Connection -> VersionRange -> m (GroupMember, Connection)
updateMemberChatVRange mem@GroupMember {groupMemberId} conn@Connection {connId, peerChatVRange} msgChatVRange = do
let jMsgChatVRange = JVersionRange msgChatVRange
if jMsgChatVRange /= peerChatVRange
then do
withStore' $ \db -> do
setPeerChatVRange db connId msgChatVRange
setMemberChatVRange db groupMemberId msgChatVRange
let conn' = conn {peerChatVRange = jMsgChatVRange}
pure (mem {memberChatVRange = jMsgChatVRange, activeConn = Just conn'}, conn')
else pure (mem, conn)
parseFileDescription :: (ChatMonad m, FilePartyI p) => Text -> m (ValidFileDescription p)
parseFileDescription =
liftEither . first (ChatError . CEInvalidFileDescription) . (strDecode . encodeUtf8)
@ -5349,18 +5484,36 @@ sendGroupMessage' user members chatMsgEvent groupId introId_ postDeliver = do
where
messageMember :: GroupMember -> SndMessage -> m (Maybe GroupMember)
messageMember m@GroupMember {groupMemberId} SndMessage {msgId, msgBody} = case memberConn m of
Nothing -> do
withStore' $ \db -> createPendingGroupMessage db groupMemberId msgId introId_
pure $ Just m
Nothing -> pendingOrForwarded
Just conn@Connection {connStatus}
| connDisabled conn || connStatus == ConnDeleted -> pure Nothing
| connStatus == ConnSndReady || connStatus == ConnReady -> do
let tag = toCMEventTag chatMsgEvent
deliverMessage conn tag msgBody msgId >> postDeliver
pure $ Just m
| otherwise -> do
withStore' $ \db -> createPendingGroupMessage db groupMemberId msgId introId_
pure $ Just m
| otherwise -> pendingOrForwarded
where
pendingOrForwarded
| forwardSupported && isForwardedGroupMsg chatMsgEvent = pure Nothing
| isXGrpMsgForward chatMsgEvent = pure Nothing
| otherwise = do
withStore' $ \db -> createPendingGroupMessage db groupMemberId msgId introId_
pure $ Just m
forwardSupported = do
let mcvr = memberChatVRange' m
isCompatibleRange mcvr groupForwardVRange && invitingMemberSupportsForward
invitingMemberSupportsForward = case m.invitedByGroupMemberId of
Just invMemberId ->
-- can be optimized for large groups by replacing [GroupMember] with Map GroupMemberId GroupMember
case find (\m' -> groupMemberId' m' == invMemberId) members of
Just invitingMember -> do
let mcvr = memberChatVRange' invitingMember
isCompatibleRange mcvr groupForwardVRange
Nothing -> False
Nothing -> False
isXGrpMsgForward ev = case ev of
XGrpMsgForward {} -> True
_ -> False
sendPendingGroupMessages :: ChatMonad m => User -> GroupMember -> Connection -> m ()
sendPendingGroupMessages user GroupMember {groupMemberId, localDisplayName} conn = do
@ -5378,18 +5531,49 @@ sendPendingGroupMessages user GroupMember {groupMemberId, localDisplayName} conn
_ -> throwChatError $ CEGroupMemberIntroNotFound localDisplayName
_ -> pure ()
saveRcvMSG :: ChatMonad m => Connection -> ConnOrGroupId -> MsgMeta -> MsgBody -> CommandId -> m (Connection, RcvMessage)
saveRcvMSG conn@Connection {connId} connOrGroupId agentMsgMeta msgBody agentAckCmdId = do
saveDirectRcvMSG :: ChatMonad m => Connection -> MsgMeta -> CommandId -> MsgBody -> m (Connection, RcvMessage)
saveDirectRcvMSG conn@Connection {connId} agentMsgMeta agentAckCmdId msgBody = do
ACMsg _ ChatMessage {chatVRange, msgId = sharedMsgId_, chatMsgEvent} <- parseAChatMessage conn agentMsgMeta msgBody
conn' <- updatePeerChatVRange conn chatVRange
let agentMsgId = fst $ recipient agentMsgMeta
newMsg = NewMessage {chatMsgEvent, msgBody}
rcvMsgDelivery = RcvMsgDelivery {connId, agentMsgId, agentMsgMeta, agentAckCmdId}
msg <- withStoreCtx'
(Just $ "createNewMessageAndRcvMsgDelivery, rcvMsgDelivery: " <> show rcvMsgDelivery <> ", sharedMsgId_: " <> show sharedMsgId_ <> ", msgDeliveryStatus: MDSRcvAgent")
$ \db -> createNewMessageAndRcvMsgDelivery db connOrGroupId newMsg sharedMsgId_ rcvMsgDelivery
msg <- withStore $ \db -> createNewMessageAndRcvMsgDelivery db (ConnectionId connId) newMsg sharedMsgId_ rcvMsgDelivery Nothing
pure (conn', msg)
saveGroupRcvMsg :: (MsgEncodingI e, ChatMonad m) => User -> GroupId -> GroupMember -> Connection -> MsgMeta -> CommandId -> MsgBody -> ChatMessage e -> m (GroupMember, Connection, RcvMessage)
saveGroupRcvMsg user groupId authorMember conn@Connection {connId} agentMsgMeta agentAckCmdId msgBody ChatMessage {chatVRange, msgId = sharedMsgId_, chatMsgEvent} = do
(am', conn') <- updateMemberChatVRange authorMember conn chatVRange
let agentMsgId = fst $ recipient agentMsgMeta
newMsg = NewMessage {chatMsgEvent, msgBody}
rcvMsgDelivery = RcvMsgDelivery {connId, agentMsgId, agentMsgMeta, agentAckCmdId}
amId = Just am'.groupMemberId
msg <- withStore (\db -> createNewMessageAndRcvMsgDelivery db (GroupId groupId) newMsg sharedMsgId_ rcvMsgDelivery amId)
`catchChatError` \e -> case e of
ChatErrorStore (SEDuplicateGroupMessage _ _ _ (Just forwardedByGroupMemberId)) -> do
fm <- withStore $ \db -> getGroupMember db user groupId forwardedByGroupMemberId
forM_ (memberConn fm) $ \fmConn ->
void $ sendDirectMessage fmConn (XGrpMemCon am'.memberId) (GroupId groupId)
throwError e
_ -> throwError e
pure (am', conn', msg)
saveGroupFwdRcvMsg :: (MsgEncodingI e, ChatMonad m) => User -> GroupId -> GroupMember -> GroupMember -> MsgBody -> ChatMessage e -> m RcvMessage
saveGroupFwdRcvMsg user groupId forwardingMember refAuthorMember msgBody ChatMessage {msgId = sharedMsgId_, chatMsgEvent} = do
let newMsg = NewMessage {chatMsgEvent, msgBody}
fwdMemberId = Just $ groupMemberId' forwardingMember
refAuthorId = Just $ groupMemberId' refAuthorMember
withStore (\db -> createNewRcvMessage db (GroupId groupId) newMsg sharedMsgId_ refAuthorId fwdMemberId)
`catchChatError` \e -> case e of
ChatErrorStore (SEDuplicateGroupMessage _ _ (Just authorGroupMemberId) Nothing) -> do
am <- withStore $ \db -> getGroupMember db user groupId authorGroupMemberId
if sameMemberId refAuthorMember.memberId am
then forM_ (memberConn forwardingMember) $ \fmConn ->
void $ sendDirectMessage fmConn (XGrpMemCon am.memberId) (GroupId groupId)
else toView $ CRMessageError user "error" "saveGroupFwdRcvMsg: referenced author member id doesn't match message member id"
throwError e
_ -> throwError e
saveSndChatItem :: ChatMonad m => User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> m (ChatItem c 'MDSnd)
saveSndChatItem user cd msg content = saveSndChatItem' user cd msg content Nothing Nothing Nothing False
@ -5401,27 +5585,27 @@ saveSndChatItem' user cd msg@SndMessage {sharedMsgId} content ciFile quotedItem
ciId <- createNewSndChatItem db user cd msg content quotedItem itemTimed live createdAt
forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt
pure ciId
liftIO $ mkChatItem cd ciId content ciFile quotedItem (Just sharedMsgId) itemTimed live createdAt createdAt
liftIO $ mkChatItem cd ciId content ciFile quotedItem (Just sharedMsgId) itemTimed live createdAt Nothing createdAt
saveRcvChatItem :: ChatMonad m => User -> ChatDirection c 'MDRcv -> RcvMessage -> MsgMeta -> CIContent 'MDRcv -> m (ChatItem c 'MDRcv)
saveRcvChatItem user cd msg@RcvMessage {sharedMsgId_} msgMeta content =
saveRcvChatItem' user cd msg sharedMsgId_ msgMeta content Nothing Nothing False
saveRcvChatItem :: ChatMonad m => User -> ChatDirection c 'MDRcv -> RcvMessage -> UTCTime -> CIContent 'MDRcv -> m (ChatItem c 'MDRcv)
saveRcvChatItem user cd msg@RcvMessage {sharedMsgId_} brokerTs content =
saveRcvChatItem' user cd msg sharedMsgId_ brokerTs content Nothing Nothing False
saveRcvChatItem' :: ChatMonad m => User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> MsgMeta -> CIContent 'MDRcv -> Maybe (CIFile 'MDRcv) -> Maybe CITimed -> Bool -> m (ChatItem c 'MDRcv)
saveRcvChatItem' user cd msg sharedMsgId_ MsgMeta {broker = (_, brokerTs)} content ciFile itemTimed live = do
saveRcvChatItem' :: ChatMonad m => User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> UTCTime -> CIContent 'MDRcv -> Maybe (CIFile 'MDRcv) -> Maybe CITimed -> Bool -> m (ChatItem c 'MDRcv)
saveRcvChatItem' user cd msg sharedMsgId_ brokerTs content ciFile itemTimed live = do
createdAt <- liftIO getCurrentTime
(ciId, quotedItem) <- withStore' $ \db -> do
when (ciRequiresAttention content) $ updateChatTs db user cd createdAt
(ciId, quotedItem) <- createNewRcvChatItem db user cd msg sharedMsgId_ content itemTimed live brokerTs createdAt
forM_ ciFile $ \CIFile {fileId} -> updateFileTransferChatItemId db fileId ciId createdAt
pure (ciId, quotedItem)
liftIO $ mkChatItem cd ciId content ciFile quotedItem sharedMsgId_ itemTimed live brokerTs createdAt
liftIO $ mkChatItem cd ciId content ciFile quotedItem sharedMsgId_ itemTimed live brokerTs msg.forwardedByGroupMemberId createdAt
mkChatItem :: forall c d. MsgDirectionI d => ChatDirection c d -> ChatItemId -> CIContent d -> Maybe (CIFile d) -> Maybe (CIQuote c) -> Maybe SharedMsgId -> Maybe CITimed -> Bool -> ChatItemTs -> UTCTime -> IO (ChatItem c d)
mkChatItem cd ciId content file quotedItem sharedMsgId itemTimed live itemTs currentTs = do
mkChatItem :: forall c d. MsgDirectionI d => ChatDirection c d -> ChatItemId -> CIContent d -> Maybe (CIFile d) -> Maybe (CIQuote c) -> Maybe SharedMsgId -> Maybe CITimed -> Bool -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> IO (ChatItem c d)
mkChatItem cd ciId content file quotedItem sharedMsgId itemTimed live itemTs forwardedByGroupMemberId currentTs = do
let itemText = ciContentToText content
itemStatus = ciCreateStatus content
meta = mkCIMeta ciId content itemText itemStatus sharedMsgId Nothing False itemTimed (justTrue live) currentTs itemTs currentTs currentTs
meta = mkCIMeta ciId content itemText itemStatus sharedMsgId Nothing False itemTimed (justTrue live) currentTs itemTs forwardedByGroupMemberId currentTs currentTs
pure ChatItem {chatDir = toCIDirection cd, meta, content, formattedText = parseMaybeMarkdownList itemText, quotedItem, reactions = [], file}
deleteDirectCI :: (ChatMonad m, MsgDirectionI d) => User -> Contact -> ChatItem 'CTDirect d -> Bool -> Bool -> m ChatResponse
@ -5584,7 +5768,7 @@ createInternalChatItem user cd content itemTs_ = do
ciId <- withStore' $ \db -> do
when (ciRequiresAttention content) $ updateChatTs db user cd createdAt
createNewChatItemNoMsg db user cd content itemTs createdAt
ci <- liftIO $ mkChatItem cd ciId content Nothing Nothing Nothing Nothing False itemTs createdAt
ci <- liftIO $ mkChatItem cd ciId content Nothing Nothing Nothing Nothing False itemTs Nothing createdAt
toView $ CRNewChatItem user (AChatItem (chatTypeI @c) (msgDirection @d) (toChatInfo cd) ci)
getCreateActiveUser :: SQLiteStore -> Bool -> IO User

View File

@ -126,7 +126,8 @@ data ChatConfig = ChatConfig
cleanupManagerInterval :: NominalDiffTime,
cleanupManagerStepDelay :: Int64,
ciExpirationInterval :: Int64, -- microseconds
coreApi :: Bool
coreApi :: Bool,
highlyAvailable :: Bool
}
data DefaultAgentServers = DefaultAgentServers

View File

@ -159,7 +159,7 @@ isMention ChatItem {chatDir, quotedItem} = case chatDir of
CIQDirectSnd -> True
CIQGroupSnd -> True
_ -> False
data CIDirection (c :: ChatType) (d :: MsgDirection) where
CIDirectSnd :: CIDirection 'CTDirect 'MDSnd
CIDirectRcv :: CIDirection 'CTDirect 'MDRcv
@ -338,17 +338,18 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta
itemTimed :: Maybe CITimed,
itemLive :: Maybe Bool,
editable :: Bool,
forwardedByGroupMemberId :: Maybe GroupMemberId,
createdAt :: UTCTime,
updatedAt :: UTCTime
}
deriving (Show, Generic)
mkCIMeta :: ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe SharedMsgId -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> UTCTime -> UTCTime -> CIMeta c d
mkCIMeta itemId itemContent itemText itemStatus itemSharedMsgId itemDeleted itemEdited itemTimed itemLive currentTs itemTs createdAt updatedAt =
mkCIMeta :: ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe SharedMsgId -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> UTCTime -> UTCTime -> CIMeta c d
mkCIMeta itemId itemContent itemText itemStatus itemSharedMsgId itemDeleted itemEdited itemTimed itemLive currentTs itemTs forwardedByGroupMemberId createdAt updatedAt =
let editable = case itemContent of
CISndMsgContent _ -> diffUTCTime currentTs itemTs < nominalDay && isNothing itemDeleted
_ -> False
in CIMeta {itemId, itemTs, itemText, itemStatus, itemSharedMsgId, itemDeleted, itemEdited, itemTimed, itemLive, editable, createdAt, updatedAt}
in CIMeta {itemId, itemTs, itemText, itemStatus, itemSharedMsgId, itemDeleted, itemEdited, itemTimed, itemLive, editable, forwardedByGroupMemberId, createdAt, updatedAt}
instance ToJSON (CIMeta c d) where toEncoding = J.genericToEncoding J.defaultOptions
@ -811,7 +812,9 @@ data RcvMessage = RcvMessage
{ msgId :: MessageId,
chatMsgEvent :: AChatMsgEvent,
sharedMsgId_ :: Maybe SharedMsgId,
msgBody :: MsgBody
msgBody :: MsgBody,
authorGroupMemberId :: Maybe GroupMemberId,
forwardedByGroupMemberId :: Maybe GroupMemberId
}
data PendingGroupMessage = PendingGroupMessage

View File

@ -0,0 +1,53 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Migrations.M20231113_group_forward where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231113_group_forward :: Query
m20231113_group_forward =
[sql|
ALTER TABLE group_member_intros ADD COLUMN intro_chat_protocol_version INTEGER NOT NULL DEFAULT 3;
CREATE INDEX idx_group_member_intros_re_group_member_id ON group_member_intros(re_group_member_id);
ALTER TABLE group_members ADD COLUMN invited_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
ALTER TABLE group_members ADD COLUMN peer_chat_min_version INTEGER NOT NULL DEFAULT 1;
ALTER TABLE group_members ADD COLUMN peer_chat_max_version INTEGER NOT NULL DEFAULT 1;
CREATE INDEX idx_group_members_invited_by_group_member_id ON group_members(invited_by_group_member_id);
UPDATE group_members
SET (peer_chat_min_version, peer_chat_max_version) = (c.peer_chat_min_version, c.peer_chat_max_version)
FROM connections c
WHERE c.group_member_id = group_members.group_member_id;
ALTER TABLE messages ADD COLUMN author_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
ALTER TABLE messages ADD COLUMN forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
CREATE INDEX idx_messages_author_group_member_id ON messages(author_group_member_id);
CREATE INDEX idx_messages_forwarded_by_group_member_id ON messages(forwarded_by_group_member_id);
CREATE INDEX idx_messages_group_id_shared_msg_id ON messages(group_id, shared_msg_id);
ALTER TABLE chat_items ADD COLUMN forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
CREATE INDEX idx_chat_items_forwarded_by_group_member_id ON chat_items(forwarded_by_group_member_id);
|]
down_m20231113_group_forward :: Query
down_m20231113_group_forward =
[sql|
DROP INDEX idx_chat_items_forwarded_by_group_member_id;
ALTER TABLE chat_items DROP COLUMN forwarded_by_group_member_id;
DROP INDEX idx_messages_group_id_shared_msg_id;
DROP INDEX idx_messages_forwarded_by_group_member_id;
DROP INDEX idx_messages_author_group_member_id;
ALTER TABLE messages DROP COLUMN forwarded_by_group_member_id;
ALTER TABLE messages DROP COLUMN author_group_member_id;
DROP INDEX idx_group_members_invited_by_group_member_id;
ALTER TABLE group_members DROP COLUMN peer_chat_max_version;
ALTER TABLE group_members DROP COLUMN peer_chat_min_version;
ALTER TABLE group_members DROP COLUMN invited_by_group_member_id;
DROP INDEX idx_group_member_intros_re_group_member_id;
ALTER TABLE group_member_intros DROP COLUMN intro_chat_protocol_version;
|]

View File

@ -147,6 +147,9 @@ CREATE TABLE group_members(
member_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL,
show_messages INTEGER NOT NULL DEFAULT 1,
xgrplinkmem_received INTEGER NOT NULL DEFAULT 0,
invited_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL,
peer_chat_min_version INTEGER NOT NULL DEFAULT 1,
peer_chat_max_version INTEGER NOT NULL DEFAULT 1,
FOREIGN KEY(user_id, local_display_name)
REFERENCES display_names(user_id, local_display_name)
ON DELETE CASCADE
@ -161,7 +164,8 @@ CREATE TABLE group_member_intros(
direct_queue_info BLOB,
intro_status TEXT NOT NULL,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL), -- see GroupMemberIntroStatus
updated_at TEXT CHECK(updated_at NOT NULL),
intro_chat_protocol_version INTEGER NOT NULL DEFAULT 3, -- see GroupMemberIntroStatus
UNIQUE(re_group_member_id, to_group_member_id)
);
CREATE TABLE files(
@ -322,7 +326,9 @@ CREATE TABLE messages(
connection_id INTEGER DEFAULT NULL REFERENCES connections ON DELETE CASCADE,
group_id INTEGER DEFAULT NULL REFERENCES groups ON DELETE CASCADE,
shared_msg_id BLOB,
shared_msg_id_user INTEGER
shared_msg_id_user INTEGER,
author_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL,
forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL
);
CREATE TABLE msg_deliveries(
msg_delivery_id INTEGER PRIMARY KEY,
@ -372,7 +378,8 @@ CREATE TABLE chat_items(
timed_delete_at TEXT,
item_live INTEGER,
item_deleted_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL,
item_deleted_ts TEXT
item_deleted_ts TEXT,
forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL
);
CREATE TABLE chat_item_messages(
chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE,
@ -752,3 +759,22 @@ CREATE INDEX idx_contact_profiles_contact_link ON contact_profiles(
user_id,
contact_link
);
CREATE INDEX idx_group_member_intros_re_group_member_id ON group_member_intros(
re_group_member_id
);
CREATE INDEX idx_group_members_invited_by_group_member_id ON group_members(
invited_by_group_member_id
);
CREATE INDEX idx_messages_author_group_member_id ON messages(
author_group_member_id
);
CREATE INDEX idx_messages_forwarded_by_group_member_id ON messages(
forwarded_by_group_member_id
);
CREATE INDEX idx_messages_group_id_shared_msg_id ON messages(
group_id,
shared_msg_id
);
CREATE INDEX idx_chat_items_forwarded_by_group_member_id ON chat_items(
forwarded_by_group_member_id
);

View File

@ -152,7 +152,8 @@ mobileChatOpts dbFilePrefix dbKey =
logServerHosts = True,
logAgent = Nothing,
logFile = Nothing,
tbqSize = 1024
tbqSize = 1024,
highlyAvailable = False
},
chatCmd = "",
chatCmdDelay = 3,

View File

@ -54,7 +54,8 @@ data CoreChatOpts = CoreChatOpts
logServerHosts :: Bool,
logAgent :: Maybe LogLevel,
logFile :: Maybe FilePath,
tbqSize :: Natural
tbqSize :: Natural,
highlyAvailable :: Bool
}
agentLogLevel :: ChatLogLevel -> LogLevel
@ -172,6 +173,11 @@ coreChatOptsP appDir defaultDbFileName = do
<> value 1024
<> showDefault
)
highlyAvailable <-
switch
( long "ha"
<> help "Run as a highly available client (this may increase traffic in groups)"
)
pure
CoreChatOpts
{ dbFilePrefix,
@ -184,7 +190,8 @@ coreChatOptsP appDir defaultDbFileName = do
logServerHosts = logServerHosts || logLevel <= CLLInfo,
logAgent = if logAgent || logLevel == CLLDebug then Just $ agentLogLevel logLevel else Nothing,
logFile,
tbqSize
tbqSize,
highlyAvailable
}
where
useTcpTimeout p t = 1000000 * if t > 0 then t else maybe 5 (const 10) p

View File

@ -2,6 +2,7 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
@ -17,7 +18,7 @@ module Simplex.Chat.Protocol where
import Control.Applicative ((<|>))
import Control.Monad ((<=<))
import Data.Aeson (FromJSON, ToJSON, (.:), (.:?), (.=))
import Data.Aeson (FromJSON (..), ToJSON (..), (.:), (.:?), (.=))
import qualified Data.Aeson as J
import qualified Data.Aeson.Encoding as JE
import qualified Data.Aeson.KeyMap as JM
@ -49,7 +50,7 @@ import Simplex.Messaging.Util (eitherToMaybe, safeDecodeUtf8, (<$?>))
import Simplex.Messaging.Version hiding (version)
currentChatVersion :: Version
currentChatVersion = 3
currentChatVersion = 4
supportedChatVRange :: VersionRange
supportedChatVRange = mkVersionRange 1 currentChatVersion
@ -66,6 +67,10 @@ xGrpDirectInvVRange = mkVersionRange 2 currentChatVersion
groupLinkNoContactVRange :: VersionRange
groupLinkNoContactVRange = mkVersionRange 3 currentChatVersion
-- version range that supports group forwarding
groupForwardVRange :: VersionRange
groupForwardVRange = mkVersionRange 4 currentChatVersion
data ConnectionEntity
= RcvDirectMsgConnection {entityConnection :: Connection, contact :: Maybe Contact}
| RcvGroupMsgConnection {entityConnection :: Connection, groupInfo :: GroupInfo, groupMember :: GroupMember}
@ -126,7 +131,7 @@ data AppMessageJson = AppMessageJson
event :: Text,
params :: J.Object
}
deriving (Generic, FromJSON)
deriving (Eq, Show, Generic, FromJSON)
data AppMessageBinary = AppMessageBinary
{ msgId :: Maybe SharedMsgId,
@ -206,7 +211,6 @@ instance StrEncoding AChatMessage where
data ChatMsgEvent (e :: MsgEncoding) where
XMsgNew :: MsgContainer -> ChatMsgEvent 'Json
XMsgFileDescr :: {msgId :: SharedMsgId, fileDescr :: FileDescr} -> ChatMsgEvent 'Json
XMsgFileCancel :: SharedMsgId -> ChatMsgEvent 'Json
XMsgUpdate :: {msgId :: SharedMsgId, content :: MsgContent, ttl :: Maybe Int, live :: Maybe Bool} -> ChatMsgEvent 'Json
XMsgDel :: SharedMsgId -> Maybe MemberId -> ChatMsgEvent 'Json
XMsgDeleted :: ChatMsgEvent 'Json
@ -228,13 +232,14 @@ data ChatMsgEvent (e :: MsgEncoding) where
XGrpMemFwd :: MemberInfo -> IntroInvitation -> ChatMsgEvent 'Json
XGrpMemInfo :: MemberId -> Profile -> ChatMsgEvent 'Json
XGrpMemRole :: MemberId -> GroupMemberRole -> ChatMsgEvent 'Json
XGrpMemCon :: MemberId -> ChatMsgEvent 'Json -- TODO not implemented
XGrpMemCon :: MemberId -> ChatMsgEvent 'Json
XGrpMemConAll :: MemberId -> ChatMsgEvent 'Json -- TODO not implemented
XGrpMemDel :: MemberId -> ChatMsgEvent 'Json
XGrpLeave :: ChatMsgEvent 'Json
XGrpDel :: ChatMsgEvent 'Json
XGrpInfo :: GroupProfile -> ChatMsgEvent 'Json
XGrpDirectInv :: ConnReqInvitation -> Maybe MsgContent -> ChatMsgEvent 'Json
XGrpMsgForward :: MemberId -> ChatMessage 'Json -> UTCTime -> ChatMsgEvent 'Json
XInfoProbe :: Probe -> ChatMsgEvent 'Json
XInfoProbeCheck :: ProbeHash -> ChatMsgEvent 'Json
XInfoProbeOk :: Probe -> ChatMsgEvent 'Json
@ -255,6 +260,30 @@ data AChatMsgEvent = forall e. MsgEncodingI e => ACME (SMsgEncoding e) (ChatMsgE
deriving instance Show AChatMsgEvent
isForwardedGroupMsg :: ChatMsgEvent e -> Bool
isForwardedGroupMsg ev = case ev of
XMsgNew mc -> case mcExtMsgContent mc of
ExtMsgContent {file = Just FileInvitation {fileInline = Just _}} -> False
_ -> True
XMsgFileDescr _ _ -> True
XMsgUpdate {} -> True
XMsgDel _ _ -> True
XMsgReact {} -> True
XFileCancel _ -> True
XInfo _ -> True
XGrpMemNew _ -> True
XGrpMemRole {} -> True
XGrpMemDel _ -> True -- TODO there should be a special logic when deleting host member (e.g., host forwards it before deleting connections)
XGrpLeave -> True
XGrpDel -> True -- TODO there should be a special logic - host should forward before deleting connections
XGrpInfo _ -> True
_ -> False
forwardedGroupMsg :: forall e. MsgEncodingI e => ChatMessage e -> Maybe (ChatMessage 'Json)
forwardedGroupMsg msg@ChatMessage {chatMsgEvent} = case encoding @e of
SJson | isForwardedGroupMsg chatMsgEvent -> Just msg
_ -> Nothing
data MsgReaction = MREmoji {emoji :: MREmojiChar} | MRUnknown {tag :: Text, json :: J.Object}
deriving (Eq, Show)
@ -549,7 +578,6 @@ instance FromField MsgContent where
data CMEventTag (e :: MsgEncoding) where
XMsgNew_ :: CMEventTag 'Json
XMsgFileDescr_ :: CMEventTag 'Json
XMsgFileCancel_ :: CMEventTag 'Json
XMsgUpdate_ :: CMEventTag 'Json
XMsgDel_ :: CMEventTag 'Json
XMsgDeleted_ :: CMEventTag 'Json
@ -578,6 +606,7 @@ data CMEventTag (e :: MsgEncoding) where
XGrpDel_ :: CMEventTag 'Json
XGrpInfo_ :: CMEventTag 'Json
XGrpDirectInv_ :: CMEventTag 'Json
XGrpMsgForward_ :: CMEventTag 'Json
XInfoProbe_ :: CMEventTag 'Json
XInfoProbeCheck_ :: CMEventTag 'Json
XInfoProbeOk_ :: CMEventTag 'Json
@ -598,7 +627,6 @@ instance MsgEncodingI e => StrEncoding (CMEventTag e) where
strEncode = \case
XMsgNew_ -> "x.msg.new"
XMsgFileDescr_ -> "x.msg.file.descr"
XMsgFileCancel_ -> "x.msg.file.cancel"
XMsgUpdate_ -> "x.msg.update"
XMsgDel_ -> "x.msg.del"
XMsgDeleted_ -> "x.msg.deleted"
@ -627,6 +655,7 @@ instance MsgEncodingI e => StrEncoding (CMEventTag e) where
XGrpDel_ -> "x.grp.del"
XGrpInfo_ -> "x.grp.info"
XGrpDirectInv_ -> "x.grp.direct.inv"
XGrpMsgForward_ -> "x.grp.msg.forward"
XInfoProbe_ -> "x.info.probe"
XInfoProbeCheck_ -> "x.info.probe.check"
XInfoProbeOk_ -> "x.info.probe.ok"
@ -648,7 +677,6 @@ instance StrEncoding ACMEventTag where
('x', t) -> pure . ACMEventTag SJson $ case t of
"x.msg.new" -> XMsgNew_
"x.msg.file.descr" -> XMsgFileDescr_
"x.msg.file.cancel" -> XMsgFileCancel_
"x.msg.update" -> XMsgUpdate_
"x.msg.del" -> XMsgDel_
"x.msg.deleted" -> XMsgDeleted_
@ -677,6 +705,7 @@ instance StrEncoding ACMEventTag where
"x.grp.del" -> XGrpDel_
"x.grp.info" -> XGrpInfo_
"x.grp.direct.inv" -> XGrpDirectInv_
"x.grp.msg.forward" -> XGrpMsgForward_
"x.info.probe" -> XInfoProbe_
"x.info.probe.check" -> XInfoProbeCheck_
"x.info.probe.ok" -> XInfoProbeOk_
@ -694,7 +723,6 @@ toCMEventTag :: ChatMsgEvent e -> CMEventTag e
toCMEventTag msg = case msg of
XMsgNew _ -> XMsgNew_
XMsgFileDescr _ _ -> XMsgFileDescr_
XMsgFileCancel _ -> XMsgFileCancel_
XMsgUpdate {} -> XMsgUpdate_
XMsgDel {} -> XMsgDel_
XMsgDeleted -> XMsgDeleted_
@ -723,6 +751,7 @@ toCMEventTag msg = case msg of
XGrpDel -> XGrpDel_
XGrpInfo _ -> XGrpInfo_
XGrpDirectInv _ _ -> XGrpDirectInv_
XGrpMsgForward {} -> XGrpMsgForward_
XInfoProbe _ -> XInfoProbe_
XInfoProbeCheck _ -> XInfoProbeCheck_
XInfoProbeOk _ -> XInfoProbeOk_
@ -793,7 +822,6 @@ appJsonToCM AppMessageJson {v, msgId, event, params} = do
msg = \case
XMsgNew_ -> XMsgNew <$> JT.parseEither parseMsgContainer params
XMsgFileDescr_ -> XMsgFileDescr <$> p "msgId" <*> p "fileDescr"
XMsgFileCancel_ -> XMsgFileCancel <$> p "msgId"
XMsgUpdate_ -> XMsgUpdate <$> p "msgId" <*> p "content" <*> opt "ttl" <*> opt "live"
XMsgDel_ -> XMsgDel <$> p "msgId" <*> opt "memberId"
XMsgDeleted_ -> pure XMsgDeleted
@ -822,6 +850,7 @@ appJsonToCM AppMessageJson {v, msgId, event, params} = do
XGrpDel_ -> pure XGrpDel
XGrpInfo_ -> XGrpInfo <$> p "groupProfile"
XGrpDirectInv_ -> XGrpDirectInv <$> p "connReq" <*> opt "content"
XGrpMsgForward_ -> XGrpMsgForward <$> p "memberId" <*> p "msg" <*> p "msgTs"
XInfoProbe_ -> XInfoProbe <$> p "probe"
XInfoProbeCheck_ -> XInfoProbeCheck <$> p "probeHash"
XInfoProbeOk_ -> XInfoProbeOk <$> p "probe"
@ -853,7 +882,6 @@ chatToAppMessage ChatMessage {chatVRange, msgId, chatMsgEvent} = case encoding @
params = \case
XMsgNew container -> msgContainerJSON container
XMsgFileDescr msgId' fileDescr -> o ["msgId" .= msgId', "fileDescr" .= fileDescr]
XMsgFileCancel msgId' -> o ["msgId" .= msgId']
XMsgUpdate msgId' content ttl live -> o $ ("ttl" .=? ttl) $ ("live" .=? live) ["msgId" .= msgId', "content" .= content]
XMsgDel msgId' memberId -> o $ ("memberId" .=? memberId) ["msgId" .= msgId']
XMsgDeleted -> JM.empty
@ -882,6 +910,7 @@ chatToAppMessage ChatMessage {chatVRange, msgId, chatMsgEvent} = case encoding @
XGrpDel -> JM.empty
XGrpInfo p -> o ["groupProfile" .= p]
XGrpDirectInv connReq content -> o $ ("content" .=? content) ["connReq" .= connReq]
XGrpMsgForward memberId msg msgTs -> o ["memberId" .= memberId, "msg" .= msg, "msgTs" .= msgTs]
XInfoProbe probe -> o ["probe" .= probe]
XInfoProbeCheck probeHash -> o ["probeHash" .= probeHash]
XInfoProbeOk probe -> o ["probe" .= probe]
@ -892,3 +921,9 @@ chatToAppMessage ChatMessage {chatVRange, msgId, chatMsgEvent} = case encoding @
XCallEnd callId -> o ["callId" .= callId]
XOk -> JM.empty
XUnknown _ ps -> ps
instance ToJSON (ChatMessage 'Json) where
toJSON = (\(AMJson msg) -> toJSON msg) . chatToAppMessage
instance FromJSON (ChatMessage 'Json) where
parseJSON v = appJsonToCM <$?> parseJSON v

View File

@ -95,13 +95,13 @@ getConnectionEntity db user@User {userId, userContactId} agentConnId = do
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
-- GroupInfo {membership}
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
-- GroupInfo {membership = GroupMember {memberProfile}}
pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- from GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
JOIN groups g ON g.group_id = m.group_id

View File

@ -42,6 +42,7 @@ module Simplex.Chat.Store.Groups
getGroupInfoByName,
getGroupMember,
getGroupMemberById,
getGroupMemberByMemberId,
getGroupMembers,
getGroupMembersForExpiration,
getGroupCurrentMembersCount,
@ -74,6 +75,9 @@ module Simplex.Chat.Store.Groups
createIntroductions,
updateIntroStatus,
saveIntroInvitation,
getIntroduction,
getForwardIntroducedMembers,
getForwardInvitedMembers,
createIntroReMember,
createIntroToMemberContact,
saveMemberInvitation,
@ -120,6 +124,7 @@ import Data.Time.Clock (UTCTime (..), getCurrentTime)
import Database.SQLite.Simple (NamedParam (..), Only (..), Query (..), (:.) (..))
import Database.SQLite.Simple.QQ (sql)
import Simplex.Chat.Messages
import Simplex.Chat.Protocol (currentChatVersion, groupForwardVRange, supportedChatVRange)
import Simplex.Chat.Store.Direct
import Simplex.Chat.Store.Shared
import Simplex.Chat.Types
@ -135,9 +140,9 @@ import UnliftIO.STM
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Maybe ImageData, Maybe ProfileId, Maybe MsgFilter, Maybe Bool, Bool, Maybe GroupPreferences) :. (UTCTime, UTCTime, Maybe UTCTime) :. GroupMemberRow
type GroupMemberRow = ((Int64, Int64, MemberId, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, Bool) :. (Maybe Int64, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences))
type GroupMemberRow = ((Int64, Int64, MemberId, Version, Version, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, Bool) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId, ProfileId, ContactName, Text, Maybe ImageData, Maybe ConnReqContact, LocalAlias, Maybe Preferences))
type MaybeGroupMemberRow = ((Maybe Int64, Maybe Int64, Maybe MemberId, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus, Maybe Bool) :. (Maybe Int64, Maybe ContactName, Maybe ContactId, Maybe ProfileId, Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe ImageData, Maybe ConnReqContact, Maybe LocalAlias, Maybe Preferences))
type MaybeGroupMemberRow = ((Maybe Int64, Maybe Int64, Maybe MemberId, Maybe Version, Maybe Version, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus, Maybe Bool) :. (Maybe Int64, Maybe GroupMemberId, Maybe ContactName, Maybe ContactId, Maybe ProfileId, Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe ImageData, Maybe ConnReqContact, Maybe LocalAlias, Maybe Preferences))
toGroupInfo :: Int64 -> GroupInfoRow -> GroupInfo
toGroupInfo userContactId ((groupId, localDisplayName, displayName, fullName, description, image, hostConnCustomUserProfileId, enableNtfs_, sendRcpts, favorite, groupPreferences) :. (createdAt, updatedAt, chatTs) :. userMemberRow) =
@ -148,16 +153,17 @@ toGroupInfo userContactId ((groupId, localDisplayName, displayName, fullName, de
in GroupInfo {groupId, localDisplayName, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId, chatSettings, createdAt, updatedAt, chatTs}
toGroupMember :: Int64 -> GroupMemberRow -> GroupMember
toGroupMember userContactId ((groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus, showMessages) :. (invitedById, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) =
toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, preferences)) =
let memberProfile = LocalProfile {profileId, displayName, fullName, image, contactLink, preferences, localAlias}
memberSettings = GroupMemberSettings {showMessages}
invitedBy = toInvitedBy userContactId invitedById
activeConn = Nothing
memberChatVRange = JVersionRange $ fromMaybe (versionToRange maxVer) $ safeVersionRange minVer maxVer
in GroupMember {..}
toMaybeGroupMember :: Int64 -> MaybeGroupMemberRow -> Maybe GroupMember
toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages) :. (invitedById, Just localDisplayName, memberContactId, Just memberContactProfileId, Just profileId, Just displayName, Just fullName, image, contactLink, Just localAlias, contactPreferences)) =
Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus, showMessages) :. (invitedById, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, contactPreferences))
toMaybeGroupMember userContactId ((Just groupMemberId, Just groupId, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages) :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId, Just profileId, Just displayName, Just fullName, image, contactLink, Just localAlias, contactPreferences)) =
Just $ toGroupMember userContactId ((groupMemberId, groupId, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages) :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId, profileId, displayName, fullName, image, contactLink, localAlias, contactPreferences))
toMaybeGroupMember _ _ = Nothing
createGroupLink :: DB.Connection -> User -> GroupInfo -> ConnId -> ConnReqContact -> GroupLinkId -> GroupMemberRole -> SubscriptionMode -> ExceptT StoreError IO ()
@ -252,13 +258,13 @@ getGroupAndMember db User {userId, userContactId} groupMemberId =
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
-- GroupInfo {membership}
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
-- GroupInfo {membership = GroupMember {memberProfile}}
pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- from GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter,
c.peer_chat_min_version, c.peer_chat_max_version
@ -303,14 +309,14 @@ createNewGroup db gVar user@User {userId} groupProfile incognitoProfile = Except
(ldn, userId, profileId, True, currentTs, currentTs, currentTs)
insertedRowId db
memberId <- liftIO $ encodedRandomBytes gVar 12
membership <- createContactMemberInv_ db user groupId user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser customUserProfileId currentTs
membership <- createContactMemberInv_ db user groupId Nothing user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser customUserProfileId currentTs supportedChatVRange
let chatSettings = ChatSettings {enableNtfs = MFAll, sendRcpts = Nothing, favorite = False}
pure GroupInfo {groupId, localDisplayName = ldn, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId = Nothing, chatSettings, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs}
-- | creates a new group record for the group the current user was invited to, or returns an existing one
createGroupInvitation :: DB.Connection -> User -> Contact -> GroupInvitation -> Maybe ProfileId -> ExceptT StoreError IO (GroupInfo, GroupMemberId)
createGroupInvitation _ _ Contact {localDisplayName, activeConn = Nothing} _ _ = throwError $ SEContactNotReady localDisplayName
createGroupInvitation db user@User {userId} contact@Contact {contactId, activeConn = Just Connection {customUserProfileId}} GroupInvitation {fromMember, invitedMember, connRequest, groupProfile} incognitoProfileId = do
createGroupInvitation db user@User {userId} contact@Contact {contactId, activeConn = Just hostConn@Connection {customUserProfileId}} GroupInvitation {fromMember, invitedMember, connRequest, groupProfile} incognitoProfileId = do
liftIO getInvitationGroupId_ >>= \case
Nothing -> createGroupInvitation_
Just gId -> do
@ -348,8 +354,9 @@ createGroupInvitation db user@User {userId} contact@Contact {contactId, activeCo
"INSERT INTO groups (group_profile_id, local_display_name, inv_queue_info, host_conn_custom_user_profile_id, user_id, enable_ntfs, created_at, updated_at, chat_ts) VALUES (?,?,?,?,?,?,?,?,?)"
(profileId, localDisplayName, connRequest, customUserProfileId, userId, True, currentTs, currentTs, currentTs)
insertedRowId db
GroupMember {groupMemberId} <- createContactMemberInv_ db user groupId contact fromMember GCHostMember GSMemInvited IBUnknown Nothing currentTs
membership <- createContactMemberInv_ db user groupId user invitedMember GCUserMember GSMemInvited (IBContact contactId) incognitoProfileId currentTs
let JVersionRange hostVRange = hostConn.peerChatVRange
GroupMember {groupMemberId} <- createContactMemberInv_ db user groupId Nothing contact fromMember GCHostMember GSMemInvited IBUnknown Nothing currentTs hostVRange
membership <- createContactMemberInv_ db user groupId (Just groupMemberId) user invitedMember GCUserMember GSMemInvited (IBContact contactId) incognitoProfileId currentTs supportedChatVRange
let chatSettings = ChatSettings {enableNtfs = MFAll, sendRcpts = Nothing, favorite = False}
pure (GroupInfo {groupId, localDisplayName, groupProfile, fullGroupPreferences, membership, hostConnCustomUserProfileId = customUserProfileId, chatSettings, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs}, groupMemberId)
@ -358,8 +365,8 @@ getHostMemberId_ db User {userId} groupId =
ExceptT . firstRow fromOnly (SEHostMemberIdNotFound groupId) $
DB.query db "SELECT group_member_id FROM group_members WHERE user_id = ? AND group_id = ? AND member_category = ?" (userId, groupId, GCHostMember)
createContactMemberInv_ :: IsContact a => DB.Connection -> User -> GroupId -> a -> MemberIdRole -> GroupMemberCategory -> GroupMemberStatus -> InvitedBy -> Maybe ProfileId -> UTCTime -> ExceptT StoreError IO GroupMember
createContactMemberInv_ db User {userId, userContactId} groupId userOrContact MemberIdRole {memberId, memberRole} memberCategory memberStatus invitedBy incognitoProfileId createdAt = do
createContactMemberInv_ :: IsContact a => DB.Connection -> User -> GroupId -> Maybe GroupMemberId -> a -> MemberIdRole -> GroupMemberCategory -> GroupMemberStatus -> InvitedBy -> Maybe ProfileId -> UTCTime -> VersionRange -> ExceptT StoreError IO GroupMember
createContactMemberInv_ db User {userId, userContactId} groupId invitedByGroupMemberId userOrContact MemberIdRole {memberId, memberRole} memberCategory memberStatus invitedBy incognitoProfileId createdAt memberChatVRange@(VersionRange minV maxV) = do
incognitoProfile <- forM incognitoProfileId $ \profileId -> getProfileById db userId profileId
(localDisplayName, memberProfile) <- case (incognitoProfile, incognitoProfileId) of
(Just profile@LocalProfile {displayName}, Just profileId) ->
@ -376,11 +383,13 @@ createContactMemberInv_ db User {userId, userContactId} groupId userOrContact Me
memberStatus,
memberSettings = defaultMemberSettings,
invitedBy,
invitedByGroupMemberId,
localDisplayName,
memberProfile,
memberContactId = Just $ contactId' userOrContact,
memberContactProfileId = localProfileId (profile' userOrContact),
activeConn = Nothing
activeConn = Nothing,
memberChatVRange = JVersionRange memberChatVRange
}
where
insertMember_ :: IO ContactName
@ -390,12 +399,14 @@ createContactMemberInv_ db User {userId, userContactId} groupId userOrContact Me
db
[sql|
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, memberCategory, memberStatus, fromInvitedBy userContactId invitedBy)
( (groupId, memberId, memberRole, memberCategory, memberStatus, fromInvitedBy userContactId invitedBy, invitedByGroupMemberId)
:. (userId, localDisplayName' userOrContact, contactId' userOrContact, localProfileId $ profile' userOrContact, createdAt, createdAt)
:. (minV, maxV)
)
pure localDisplayName
insertMemberIncognitoProfile_ :: ContactName -> ProfileId -> ExceptT StoreError IO ContactName
@ -405,12 +416,14 @@ createContactMemberInv_ db User {userId, userContactId} groupId userOrContact Me
db
[sql|
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by,
user_id, local_display_name, contact_id, contact_profile_id, member_profile_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, member_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, memberCategory, memberStatus, fromInvitedBy userContactId invitedBy)
( (groupId, memberId, memberRole, memberCategory, memberStatus, fromInvitedBy userContactId invitedBy, invitedByGroupMemberId)
:. (userId, incognitoLdn, contactId' userOrContact, localProfileId $ profile' userOrContact, customUserProfileId, createdAt, createdAt)
:. (minV, maxV)
)
pure $ Right incognitoLdn
@ -425,7 +438,7 @@ createGroupInvitedViaLink
hostMemberId <- insertHost_ currentTs groupId
liftIO $ DB.execute db "UPDATE connections SET conn_type = ?, group_member_id = ?, updated_at = ? WHERE connection_id = ?" (ConnMember, hostMemberId, currentTs, connId)
-- using IBUnknown since host is created without contact
void $ createContactMemberInv_ db user groupId user invitedMember GCUserMember GSMemAccepted IBUnknown customUserProfileId currentTs
void $ createContactMemberInv_ db user groupId (Just hostMemberId) user invitedMember GCUserMember GSMemAccepted IBUnknown customUserProfileId currentTs supportedChatVRange
liftIO $ setViaGroupLinkHash db groupId connId
(,) <$> getGroupInfo db user groupId <*> getGroupMemberById db user hostMemberId
where
@ -547,8 +560,8 @@ getUserGroupDetails db User {userId, userContactId} _contactId_ search_ =
db
[sql|
SELECT g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
mu.group_member_id, g.group_id, mu.member_id, mu.member_role, mu.member_category, mu.member_status, mu.show_messages,
mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
mu.group_member_id, g.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages,
mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
FROM groups g
JOIN group_profiles gp USING (group_profile_id)
JOIN group_members mu USING (group_id)
@ -612,8 +625,8 @@ groupMemberQuery :: Query
groupMemberQuery =
[sql|
SELECT
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter,
c.peer_chat_min_version, c.peer_chat_max_version
@ -642,6 +655,14 @@ getGroupMemberById db user@User {userId} groupMemberId =
(groupMemberQuery <> " WHERE m.group_member_id = ? AND m.user_id = ?")
(userId, groupMemberId, userId)
getGroupMemberByMemberId :: DB.Connection -> User -> GroupInfo -> MemberId -> ExceptT StoreError IO GroupMember
getGroupMemberByMemberId db user@User {userId} GroupInfo {groupId} memberId =
ExceptT . firstRow (toContactMember user) (SEGroupMemberNotFoundByMemberId memberId) $
DB.query
db
(groupMemberQuery <> " WHERE m.group_id = ? AND m.member_id = ?")
(userId, groupId, memberId)
getGroupMembers :: DB.Connection -> User -> GroupInfo -> IO [GroupMember]
getGroupMembers db user@User {userId, userContactId} GroupInfo {groupId} = do
map (toContactMember user)
@ -700,15 +721,17 @@ getGroupInvitation db user groupId =
firstRow fromOnly (SEGroupNotFound groupId) $
DB.query db "SELECT g.inv_queue_info FROM groups g WHERE g.group_id = ? AND g.user_id = ?" (groupId, userId)
createNewContactMember :: DB.Connection -> TVar ChaChaDRG -> User -> GroupId -> Contact -> GroupMemberRole -> ConnId -> ConnReqInvitation -> SubscriptionMode -> ExceptT StoreError IO GroupMember
createNewContactMember :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> Contact -> GroupMemberRole -> ConnId -> ConnReqInvitation -> SubscriptionMode -> ExceptT StoreError IO GroupMember
createNewContactMember _ _ _ _ Contact {localDisplayName, activeConn = Nothing} _ _ _ _ = throwError $ SEContactNotReady localDisplayName
createNewContactMember db gVar User {userId, userContactId} groupId Contact {contactId, localDisplayName, profile, activeConn = Just Connection {peerChatVRange}} memberRole agentConnId connRequest subMode =
createNewContactMember db gVar User {userId, userContactId} GroupInfo {groupId, membership} Contact {contactId, localDisplayName, profile, activeConn = Just Connection {peerChatVRange}} memberRole agentConnId connRequest subMode =
createWithRandomId gVar $ \memId -> do
createdAt <- liftIO getCurrentTime
member@GroupMember {groupMemberId} <- createMember_ (MemberId memId) createdAt
void $ createMemberConnection_ db userId groupMemberId agentConnId (fromJVersionRange peerChatVRange) Nothing 0 createdAt subMode
pure member
where
JVersionRange (VersionRange minV maxV) = peerChatVRange
invitedByGroupMemberId = groupMemberId' membership
createMember_ memberId createdAt = do
insertMember_
groupMemberId <- liftIO $ insertedRowId db
@ -722,11 +745,13 @@ createNewContactMember db gVar User {userId, userContactId} groupId Contact {con
memberStatus = GSMemInvited,
memberSettings = defaultMemberSettings,
invitedBy = IBUser,
invitedByGroupMemberId = Just invitedByGroupMemberId,
localDisplayName,
memberProfile = profile,
memberContactId = Just contactId,
memberContactProfileId = localProfileId profile,
activeConn = Nothing
activeConn = Nothing,
memberChatVRange = peerChatVRange
}
where
insertMember_ =
@ -734,16 +759,18 @@ createNewContactMember db gVar User {userId, userContactId} groupId Contact {con
db
[sql|
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by,
user_id, local_display_name, contact_id, contact_profile_id, sent_inv_queue_info, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, sent_inv_queue_info, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, GCInviteeMember, GSMemInvited, fromInvitedBy userContactId IBUser)
( (groupId, memberId, memberRole, GCInviteeMember, GSMemInvited, fromInvitedBy userContactId IBUser, invitedByGroupMemberId)
:. (userId, localDisplayName, contactId, localProfileId profile, connRequest, createdAt, createdAt)
:. (minV, maxV)
)
createNewContactMemberAsync :: DB.Connection -> TVar ChaChaDRG -> User -> GroupId -> Contact -> GroupMemberRole -> (CommandId, ConnId) -> VersionRange -> SubscriptionMode -> ExceptT StoreError IO ()
createNewContactMemberAsync db gVar user@User {userId, userContactId} groupId Contact {contactId, localDisplayName, profile} memberRole (cmdId, agentConnId) peerChatVRange subMode =
createNewContactMemberAsync :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> Contact -> GroupMemberRole -> (CommandId, ConnId) -> VersionRange -> SubscriptionMode -> ExceptT StoreError IO ()
createNewContactMemberAsync db gVar user@User {userId, userContactId} GroupInfo {groupId, membership} Contact {contactId, localDisplayName, profile} memberRole (cmdId, agentConnId) peerChatVRange subMode =
createWithRandomId gVar $ \memId -> do
createdAt <- liftIO getCurrentTime
insertMember_ (MemberId memId) createdAt
@ -751,17 +778,20 @@ createNewContactMemberAsync db gVar user@User {userId, userContactId} groupId Co
Connection {connId} <- createMemberConnection_ db userId groupMemberId agentConnId peerChatVRange Nothing 0 createdAt subMode
setCommandConnId db user cmdId connId
where
VersionRange minV maxV = peerChatVRange
insertMember_ memberId createdAt =
DB.execute
db
[sql|
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, GCInviteeMember, GSMemInvited, fromInvitedBy userContactId IBUser)
( (groupId, memberId, memberRole, GCInviteeMember, GSMemInvited, fromInvitedBy userContactId IBUser, groupMemberId' membership)
:. (userId, localDisplayName, contactId, localProfileId profile, createdAt, createdAt)
:. (minV, maxV)
)
createAcceptedMember :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> UserContactRequest -> GroupMemberRole -> ExceptT StoreError IO (GroupMemberId, MemberId)
@ -769,8 +799,8 @@ createAcceptedMember
db
gVar
User {userId, userContactId}
GroupInfo {groupId}
UserContactRequest {localDisplayName, profileId}
GroupInfo {groupId, membership}
UserContactRequest {cReqChatVRange, localDisplayName, profileId}
memberRole = do
liftIO $
DB.execute db "DELETE FROM contact_requests WHERE user_id = ? AND local_display_name = ?" (userId, localDisplayName)
@ -780,17 +810,20 @@ createAcceptedMember
groupMemberId <- liftIO $ insertedRowId db
pure (groupMemberId, MemberId memId)
where
JVersionRange (VersionRange minV maxV) = cReqChatVRange
insertMember_ memberId createdAt =
DB.execute
db
[sql|
INSERT INTO group_members
( group_id, member_id, member_role, member_category, member_status, invited_by,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
( group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
( (groupId, memberId, memberRole, GCInviteeMember, GSMemAccepted, fromInvitedBy userContactId IBUser)
( (groupId, memberId, memberRole, GCInviteeMember, GSMemAccepted, fromInvitedBy userContactId IBUser, groupMemberId' membership)
:. (userId, localDisplayName, Nothing :: (Maybe Int64), profileId, createdAt, createdAt)
:. (minV, maxV)
)
createAcceptedMemberConnection :: DB.Connection -> User -> (CommandId, ConnId) -> UserContactRequest -> GroupMemberId -> SubscriptionMode -> IO ()
@ -859,8 +892,8 @@ updateGroupMemberStatusById db userId groupMemberId memStatus = do
(memStatus, currentTs, userId, groupMemberId)
-- | add new member with profile
createNewGroupMember :: DB.Connection -> User -> GroupInfo -> MemberInfo -> GroupMemberCategory -> GroupMemberStatus -> ExceptT StoreError IO GroupMember
createNewGroupMember db user gInfo memInfo@MemberInfo {profile} memCategory memStatus = do
createNewGroupMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> MemberInfo -> GroupMemberCategory -> GroupMemberStatus -> ExceptT StoreError IO GroupMember
createNewGroupMember db user gInfo invitingMember memInfo@MemberInfo {profile} memCategory memStatus = do
currentTs <- liftIO getCurrentTime
(localDisplayName, memProfileId) <- createNewMemberProfile_ db user profile currentTs
let newMember =
@ -869,6 +902,7 @@ createNewGroupMember db user gInfo memInfo@MemberInfo {profile} memCategory memS
memCategory,
memStatus,
memInvitedBy = IBUnknown,
memInvitedByGroupMemberId = Just $ groupMemberId' invitingMember,
localDisplayName,
memContactId = Nothing,
memProfileId
@ -891,10 +925,11 @@ createNewMember_
User {userId, userContactId}
GroupInfo {groupId}
NewGroupMember
{ memInfo = MemberInfo memberId memberRole _ memberProfile,
{ memInfo = MemberInfo memberId memberRole memChatVRange memberProfile,
memCategory = memberCategory,
memStatus = memberStatus,
memInvitedBy = invitedBy,
memInvitedByGroupMemberId,
localDisplayName,
memContactId = memberContactId,
memProfileId = memberContactProfileId
@ -902,18 +937,38 @@ createNewMember_
createdAt = do
let invitedById = fromInvitedBy userContactId invitedBy
activeConn = Nothing
mcvr@(VersionRange minV maxV) = maybe chatInitialVRange fromChatVRange memChatVRange
DB.execute
db
[sql|
INSERT INTO group_members
(group_id, member_id, member_role, member_category, member_status,
invited_by, user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
(group_id, member_id, member_role, member_category, member_status, invited_by, invited_by_group_member_id,
user_id, local_display_name, contact_id, contact_profile_id, created_at, updated_at,
peer_chat_min_version, peer_chat_max_version)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
(groupId, memberId, memberRole, memberCategory, memberStatus, invitedById, userId, localDisplayName, memberContactId, memberContactProfileId, createdAt, createdAt)
( (groupId, memberId, memberRole, memberCategory, memberStatus, invitedById, memInvitedByGroupMemberId)
:. (userId, localDisplayName, memberContactId, memberContactProfileId, createdAt, createdAt)
:. (minV, maxV)
)
groupMemberId <- insertedRowId db
let memberSettings = defaultMemberSettings
pure GroupMember {groupMemberId, groupId, memberId, memberRole, memberCategory, memberStatus, memberSettings, invitedBy, localDisplayName, memberProfile = toLocalProfile memberContactProfileId memberProfile "", memberContactId, memberContactProfileId, activeConn}
pure GroupMember {
groupMemberId,
groupId,
memberId,
memberRole,
memberCategory,
memberStatus,
memberSettings = defaultMemberSettings,
invitedBy,
invitedByGroupMemberId = memInvitedByGroupMemberId,
localDisplayName,
memberProfile = toLocalProfile memberContactProfileId memberProfile "",
memberContactId,
memberContactProfileId,
activeConn,
memberChatVRange = JVersionRange mcvr
}
checkGroupMemberHasItems :: DB.Connection -> User -> GroupMember -> IO (Maybe ChatItemId)
checkGroupMemberHasItems db User {userId} GroupMember {groupMemberId, groupId} =
@ -960,10 +1015,10 @@ createIntroductions db members toMember = do
db
[sql|
INSERT INTO group_member_intros
(re_group_member_id, to_group_member_id, intro_status, created_at, updated_at)
VALUES (?,?,?,?,?)
(re_group_member_id, to_group_member_id, intro_status, intro_chat_protocol_version, created_at, updated_at)
VALUES (?,?,?,?,?,?)
|]
(groupMemberId' reMember, groupMemberId' toMember, GMIntroPending, ts, ts)
(groupMemberId' reMember, groupMemberId' toMember, GMIntroPending, currentChatVersion, ts, ts)
introId <- insertedRowId db
pure GroupMemberIntro {introId, reMember, toMember, introStatus = GMIntroPending, introInvitation = Nothing}
@ -981,7 +1036,7 @@ updateIntroStatus db introId introStatus = do
saveIntroInvitation :: DB.Connection -> GroupMember -> GroupMember -> IntroInvitation -> ExceptT StoreError IO GroupMemberIntro
saveIntroInvitation db reMember toMember introInv = do
intro <- getIntroduction_ db reMember toMember
intro <- getIntroduction db reMember toMember
liftIO $ do
currentTs <- getCurrentTime
DB.executeNamed
@ -1022,8 +1077,8 @@ saveMemberInvitation db GroupMember {groupMemberId} IntroInvitation {groupConnRe
":group_member_id" := groupMemberId
]
getIntroduction_ :: DB.Connection -> GroupMember -> GroupMember -> ExceptT StoreError IO GroupMemberIntro
getIntroduction_ db reMember toMember = ExceptT $ do
getIntroduction :: DB.Connection -> GroupMember -> GroupMember -> ExceptT StoreError IO GroupMemberIntro
getIntroduction db reMember toMember = ExceptT $ do
toIntro
<$> DB.query
db
@ -1040,10 +1095,50 @@ getIntroduction_ db reMember toMember = ExceptT $ do
in Right GroupMemberIntro {introId, reMember, toMember, introStatus, introInvitation}
toIntro _ = Left SEIntroNotFound
getForwardIntroducedMembers :: DB.Connection -> User -> GroupMember -> Bool -> IO [GroupMember]
getForwardIntroducedMembers db user invitee highlyAvailable = do
memberIds <- map fromOnly <$> query
filter memberCurrent . rights <$> mapM (runExceptT . getGroupMemberById db user) memberIds
where
mId = groupMemberId' invitee
query
| highlyAvailable = DB.query db q (mId, GMIntroReConnected, GMIntroToConnected, GMIntroConnected)
| otherwise =
DB.query
db
(q <> " AND intro_chat_protocol_version >= ?")
(mId, GMIntroReConnected, GMIntroToConnected, GMIntroConnected, minVersion groupForwardVRange)
q =
[sql|
SELECT re_group_member_id
FROM group_member_intros
WHERE to_group_member_id = ? AND intro_status NOT IN (?,?,?)
|]
getForwardInvitedMembers :: DB.Connection -> User -> GroupMember -> Bool -> IO [GroupMember]
getForwardInvitedMembers db user forwardMember highlyAvailable = do
memberIds <- map fromOnly <$> query
filter memberCurrent . rights <$> mapM (runExceptT . getGroupMemberById db user) memberIds
where
mId = groupMemberId' forwardMember
query
| highlyAvailable = DB.query db q (mId, GMIntroReConnected, GMIntroToConnected, GMIntroConnected)
| otherwise =
DB.query
db
(q <> " AND intro_chat_protocol_version >= ?")
(mId, GMIntroReConnected, GMIntroToConnected, GMIntroConnected, minVersion groupForwardVRange)
q =
[sql|
SELECT to_group_member_id
FROM group_member_intros
WHERE re_group_member_id = ? AND intro_status NOT IN (?,?,?)
|]
createIntroReMember :: DB.Connection -> User -> GroupInfo -> GroupMember -> MemberInfo -> (CommandId, ConnId) -> Maybe (CommandId, ConnId) -> Maybe ProfileId -> SubscriptionMode -> ExceptT StoreError IO GroupMember
createIntroReMember db user@User {userId} gInfo@GroupInfo {groupId} _host@GroupMember {memberContactId, activeConn} memInfo@(MemberInfo _ _ memberChatVRange memberProfile) (groupCmdId, groupAgentConnId) directConnIds customUserProfileId subMode = do
let mcvr = maybe chatInitialVRange fromChatVRange memberChatVRange
cLevel = 1 + maybe 0 (connLevel :: Connection -> Int) activeConn
createIntroReMember db user@User {userId} gInfo@GroupInfo {groupId} _host@GroupMember {memberContactId, activeConn} memInfo@(MemberInfo _ _ memChatVRange memberProfile) (groupCmdId, groupAgentConnId) directConnIds customUserProfileId subMode = do
let mcvr = maybe chatInitialVRange fromChatVRange memChatVRange
cLevel = 1 + maybe 0 (\Connection {connLevel} -> connLevel) activeConn
currentTs <- liftIO getCurrentTime
newMember <- case directConnIds of
Just (directCmdId, directAgentConnId) -> do
@ -1051,10 +1146,10 @@ createIntroReMember db user@User {userId} gInfo@GroupInfo {groupId} _host@GroupM
liftIO $ setCommandConnId db user directCmdId directConnId
(localDisplayName, contactId, memProfileId) <- createContact_ db userId memberProfile "" (Just groupId) currentTs Nothing
liftIO $ DB.execute db "UPDATE connections SET contact_id = ?, updated_at = ? WHERE connection_id = ?" (contactId, currentTs, directConnId)
pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memInvitedBy = IBUnknown, localDisplayName, memContactId = Just contactId, memProfileId}
pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Just contactId, memProfileId}
Nothing -> do
(localDisplayName, memProfileId) <- createNewMemberProfile_ db user memberProfile currentTs
pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memInvitedBy = IBUnknown, localDisplayName, memContactId = Nothing, memProfileId}
pure $ NewGroupMember {memInfo, memCategory = GCPreMember, memStatus = GSMemIntroduced, memInvitedBy = IBUnknown, memInvitedByGroupMemberId = Nothing, localDisplayName, memContactId = Nothing, memProfileId}
liftIO $ do
member <- createNewMember_ db user gInfo newMember currentTs
conn@Connection {connId = groupConnId} <- createMemberConnection_ db userId (groupMemberId' member) groupAgentConnId mcvr memberContactId cLevel currentTs subMode
@ -1111,13 +1206,13 @@ getViaGroupMember db User {userId, userContactId} Contact {contactId} =
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
-- GroupInfo {membership}
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
-- GroupInfo {membership = GroupMember {memberProfile}}
pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- via GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages,
m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.custom_user_profile_id,
c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.auth_err_counter,
c.peer_chat_min_version, c.peer_chat_max_version
@ -1204,8 +1299,8 @@ getGroupInfo db User {userId, userContactId} groupId =
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
-- GroupMember - membership
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id

View File

@ -21,6 +21,7 @@ module Simplex.Chat.Store.Messages
createNewSndMessage,
createSndMsgDelivery,
createNewMessageAndRcvMsgDelivery,
createNewRcvMessage,
createSndMsgDeliveryEvent,
createRcvMsgDeliveryEvent,
createPendingGroupMessage,
@ -181,25 +182,53 @@ createSndMsgDelivery db sndMsgDelivery messageId = do
createMsgDeliveryEvent_ db msgDeliveryId MDSSndAgent currentTs
pure msgDeliveryId
createNewMessageAndRcvMsgDelivery :: forall e. MsgEncodingI e => DB.Connection -> ConnOrGroupId -> NewMessage e -> Maybe SharedMsgId -> RcvMsgDelivery -> IO RcvMessage
createNewMessageAndRcvMsgDelivery db connOrGroupId NewMessage {chatMsgEvent, msgBody} sharedMsgId_ RcvMsgDelivery {connId, agentMsgId, agentMsgMeta, agentAckCmdId} = do
currentTs <- getCurrentTime
DB.execute
db
"INSERT INTO messages (msg_sent, chat_msg_event, msg_body, created_at, updated_at, connection_id, group_id, shared_msg_id) VALUES (?,?,?,?,?,?,?,?)"
(MDRcv, toCMEventTag chatMsgEvent, msgBody, currentTs, currentTs, connId_, groupId_, sharedMsgId_)
msgId <- insertedRowId db
DB.execute
db
"INSERT INTO msg_deliveries (message_id, connection_id, agent_msg_id, agent_msg_meta, agent_ack_cmd_id, chat_ts, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)"
(msgId, connId, agentMsgId, msgMetaJson agentMsgMeta, agentAckCmdId, snd $ broker agentMsgMeta, currentTs, currentTs)
msgDeliveryId <- insertedRowId db
createMsgDeliveryEvent_ db msgDeliveryId MDSRcvAgent currentTs
pure RcvMessage {msgId, chatMsgEvent = ACME (encoding @e) chatMsgEvent, sharedMsgId_, msgBody}
where
(connId_, groupId_) = case connOrGroupId of
ConnectionId connId' -> (Just connId', Nothing)
GroupId groupId -> (Nothing, Just groupId)
createNewMessageAndRcvMsgDelivery :: forall e. MsgEncodingI e => DB.Connection -> ConnOrGroupId -> NewMessage e -> Maybe SharedMsgId -> RcvMsgDelivery -> Maybe GroupMemberId -> ExceptT StoreError IO RcvMessage
createNewMessageAndRcvMsgDelivery db connOrGroupId newMessage sharedMsgId_ RcvMsgDelivery {connId, agentMsgId, agentMsgMeta, agentAckCmdId} authorGroupMemberId_ = do
msg@RcvMessage {msgId} <- createNewRcvMessage db connOrGroupId newMessage sharedMsgId_ authorGroupMemberId_ Nothing
liftIO $ do
currentTs <- getCurrentTime
DB.execute
db
"INSERT INTO msg_deliveries (message_id, connection_id, agent_msg_id, agent_msg_meta, agent_ack_cmd_id, chat_ts, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?)"
(msgId, connId, agentMsgId, msgMetaJson agentMsgMeta, agentAckCmdId, snd $ broker agentMsgMeta, currentTs, currentTs)
msgDeliveryId <- insertedRowId db
createMsgDeliveryEvent_ db msgDeliveryId MDSRcvAgent currentTs
pure msg
createNewRcvMessage :: forall e. (MsgEncodingI e) => DB.Connection -> ConnOrGroupId -> NewMessage e -> Maybe SharedMsgId -> Maybe GroupMemberId -> Maybe GroupMemberId -> ExceptT StoreError IO RcvMessage
createNewRcvMessage db connOrGroupId NewMessage{chatMsgEvent, msgBody} sharedMsgId_ authorGroupMemberId forwardedByGroupMemberId =
case connOrGroupId of
ConnectionId connId -> liftIO $ insertRcvMsg (Just connId) Nothing
GroupId groupId -> case sharedMsgId_ of
Just sharedMsgId -> liftIO (duplicateGroupMsgMemberIds groupId sharedMsgId) >>= \case
Just (duplAuthorId, duplFwdMemberId) ->
throwError $ SEDuplicateGroupMessage groupId sharedMsgId duplAuthorId duplFwdMemberId
Nothing -> liftIO $ insertRcvMsg Nothing $ Just groupId
Nothing -> liftIO $ insertRcvMsg Nothing $ Just groupId
where
duplicateGroupMsgMemberIds :: Int64 -> SharedMsgId -> IO (Maybe (Maybe GroupMemberId, Maybe GroupMemberId))
duplicateGroupMsgMemberIds groupId sharedMsgId =
maybeFirstRow id
$ DB.query
db
[sql|
SELECT author_group_member_id, forwarded_by_group_member_id
FROM messages
WHERE group_id = ? AND shared_msg_id = ? LIMIT 1
|]
(groupId, sharedMsgId)
insertRcvMsg connId_ groupId_ = do
currentTs <- getCurrentTime
DB.execute
db
[sql|
INSERT INTO messages
(msg_sent, chat_msg_event, msg_body, created_at, updated_at, connection_id, group_id, shared_msg_id, author_group_member_id, forwarded_by_group_member_id)
VALUES (?,?,?,?,?,?,?,?,?,?)
|]
(MDRcv, toCMEventTag chatMsgEvent, msgBody, currentTs, currentTs, connId_, groupId_, sharedMsgId_, authorGroupMemberId, forwardedByGroupMemberId)
msgId <- insertedRowId db
pure RcvMessage{msgId, chatMsgEvent = ACME (encoding @e) chatMsgEvent, sharedMsgId_, msgBody, authorGroupMemberId, forwardedByGroupMemberId}
createSndMsgDeliveryEvent :: DB.Connection -> Int64 -> AgentMsgId -> MsgDeliveryStatus 'MDSnd -> ExceptT StoreError IO ()
createSndMsgDeliveryEvent db connId agentMsgId sndMsgDeliveryStatus = do
@ -318,7 +347,7 @@ updateChatTs db User {userId} chatDirection chatTs = case toChatInfo chatDirecti
createNewSndChatItem :: DB.Connection -> User -> ChatDirection c 'MDSnd -> SndMessage -> CIContent 'MDSnd -> Maybe (CIQuote c) -> Maybe CITimed -> Bool -> UTCTime -> IO ChatItemId
createNewSndChatItem db user chatDirection SndMessage {msgId, sharedMsgId} ciContent quotedItem timed live createdAt =
createNewChatItem_ db user chatDirection createdByMsgId (Just sharedMsgId) ciContent quoteRow timed live createdAt createdAt
createNewChatItem_ db user chatDirection createdByMsgId (Just sharedMsgId) ciContent quoteRow timed live createdAt Nothing createdAt
where
createdByMsgId = if msgId == 0 then Nothing else Just msgId
quoteRow :: NewQuoteRow
@ -333,8 +362,8 @@ createNewSndChatItem db user chatDirection SndMessage {msgId, sharedMsgId} ciCon
CIQGroupRcv Nothing -> (Just False, Nothing)
createNewRcvChatItem :: DB.Connection -> User -> ChatDirection c 'MDRcv -> RcvMessage -> Maybe SharedMsgId -> CIContent 'MDRcv -> Maybe CITimed -> Bool -> UTCTime -> UTCTime -> IO (ChatItemId, Maybe (CIQuote c))
createNewRcvChatItem db user chatDirection RcvMessage {msgId, chatMsgEvent} sharedMsgId_ ciContent timed live itemTs createdAt = do
ciId <- createNewChatItem_ db user chatDirection (Just msgId) sharedMsgId_ ciContent quoteRow timed live itemTs createdAt
createNewRcvChatItem db user chatDirection RcvMessage {msgId, chatMsgEvent, forwardedByGroupMemberId} sharedMsgId_ ciContent timed live itemTs createdAt = do
ciId <- createNewChatItem_ db user chatDirection (Just msgId) sharedMsgId_ ciContent quoteRow timed live itemTs forwardedByGroupMemberId createdAt
quotedItem <- mapM (getChatItemQuote_ db user chatDirection) quotedMsg
pure (ciId, quotedItem)
where
@ -349,14 +378,14 @@ createNewRcvChatItem db user chatDirection RcvMessage {msgId, chatMsgEvent} shar
(Just $ Just userMemberId == memberId, memberId)
createNewChatItemNoMsg :: forall c d. MsgDirectionI d => DB.Connection -> User -> ChatDirection c d -> CIContent d -> UTCTime -> UTCTime -> IO ChatItemId
createNewChatItemNoMsg db user chatDirection ciContent =
createNewChatItem_ db user chatDirection Nothing Nothing ciContent quoteRow Nothing False
createNewChatItemNoMsg db user chatDirection ciContent itemTs =
createNewChatItem_ db user chatDirection Nothing Nothing ciContent quoteRow Nothing False itemTs Nothing
where
quoteRow :: NewQuoteRow
quoteRow = (Nothing, Nothing, Nothing, Nothing, Nothing)
createNewChatItem_ :: forall c d. MsgDirectionI d => DB.Connection -> User -> ChatDirection c d -> Maybe MessageId -> Maybe SharedMsgId -> CIContent d -> NewQuoteRow -> Maybe CITimed -> Bool -> UTCTime -> UTCTime -> IO ChatItemId
createNewChatItem_ db User {userId} chatDirection msgId_ sharedMsgId ciContent quoteRow timed live itemTs createdAt = do
createNewChatItem_ :: forall c d. MsgDirectionI d => DB.Connection -> User -> ChatDirection c d -> Maybe MessageId -> Maybe SharedMsgId -> CIContent d -> NewQuoteRow -> Maybe CITimed -> Bool -> UTCTime -> Maybe GroupMemberId -> UTCTime -> IO ChatItemId
createNewChatItem_ db User {userId} chatDirection msgId_ sharedMsgId ciContent quoteRow timed live itemTs forwardedByGroupMemberId createdAt = do
DB.execute
db
[sql|
@ -364,18 +393,18 @@ createNewChatItem_ db User {userId} chatDirection msgId_ sharedMsgId ciContent q
-- user and IDs
user_id, created_by_msg_id, contact_id, group_id, group_member_id,
-- meta
item_sent, item_ts, item_content, item_text, item_status, shared_msg_id, created_at, updated_at, item_live, timed_ttl, timed_delete_at,
item_sent, item_ts, item_content, item_text, item_status, shared_msg_id, forwarded_by_group_member_id, created_at, updated_at, item_live, timed_ttl, timed_delete_at,
-- quote
quoted_shared_msg_id, quoted_sent_at, quoted_content, quoted_sent, quoted_member_id
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|]
((userId, msgId_) :. idsRow :. itemRow :. quoteRow)
ciId <- insertedRowId db
forM_ msgId_ $ \msgId -> insertChatItemMessage_ db ciId msgId createdAt
pure ciId
where
itemRow :: (SMsgDirection d, UTCTime, CIContent d, Text, CIStatus d, Maybe SharedMsgId) :. (UTCTime, UTCTime, Maybe Bool) :. (Maybe Int, Maybe UTCTime)
itemRow = (msgDirection @d, itemTs, ciContent, ciContentToText ciContent, ciCreateStatus ciContent, sharedMsgId) :. (createdAt, createdAt, justTrue live) :. ciTimedRow timed
itemRow :: (SMsgDirection d, UTCTime, CIContent d, Text, CIStatus d, Maybe SharedMsgId, Maybe GroupMemberId) :. (UTCTime, UTCTime, Maybe Bool) :. (Maybe Int, Maybe UTCTime)
itemRow = (msgDirection @d, itemTs, ciContent, ciContentToText ciContent, ciCreateStatus ciContent, sharedMsgId, forwardedByGroupMemberId) :. (createdAt, createdAt, justTrue live) :. ciTimedRow timed
idsRow :: (Maybe Int64, Maybe Int64, Maybe Int64)
idsRow = case chatDirection of
CDDirectRcv Contact {contactId} -> (Just contactId, Nothing, Nothing)
@ -436,8 +465,8 @@ getChatItemQuote_ db User {userId, userContactId} chatDirection QuotedMsg {msgRe
[sql|
SELECT i.chat_item_id,
-- GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category,
m.member_status, m.show_messages, m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category,
m.member_status, m.show_messages, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences
FROM group_members m
JOIN contact_profiles p ON p.contact_profile_id = COALESCE(m.member_profile_id, m.contact_profile_id)
@ -552,8 +581,8 @@ getGroupChatPreviews_ db User {userId, userContactId} = do
-- GroupInfo
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.description, gp.image, g.host_conn_custom_user_profile_id, g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, g.created_at, g.updated_at, g.chat_ts,
-- GroupMember - membership
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
mu.group_member_id, mu.group_id, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category,
mu.member_status, mu.show_messages, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
pu.display_name, pu.full_name, pu.image, pu.contact_link, pu.local_alias, pu.preferences,
-- ChatStats
COALESCE(ChatStats.UnreadCount, 0), COALESCE(ChatStats.MinUnread, 0), g.unread_chat,
@ -561,19 +590,21 @@ getGroupChatPreviews_ db User {userId, userContactId} = do
i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.shared_msg_id, i.item_deleted, i.item_deleted_ts, i.item_edited, i.created_at, i.updated_at, i.timed_ttl, i.timed_delete_at, i.item_live,
-- CIFile
f.file_id, f.file_name, f.file_size, f.file_path, f.file_crypto_key, f.file_crypto_nonce, f.ci_file_status, f.protocol,
-- CIMeta forwardedByGroupMemberId
i.forwarded_by_group_member_id,
-- Maybe GroupMember - sender
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category,
m.member_status, m.show_messages, m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category,
m.member_status, m.show_messages, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
-- quoted ChatItem
ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent,
-- quoted GroupMember
rm.group_member_id, rm.group_id, rm.member_id, rm.member_role, rm.member_category,
rm.member_status, rm.show_messages, rm.invited_by, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id,
rm.group_member_id, rm.group_id, rm.member_id, rm.peer_chat_min_version, rm.peer_chat_max_version, rm.member_role, rm.member_category,
rm.member_status, rm.show_messages, rm.invited_by, rm.invited_by_group_member_id, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id,
rp.display_name, rp.full_name, rp.image, rp.contact_link, rp.local_alias, rp.preferences,
-- deleted by GroupMember
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.show_messages, dbm.invited_by, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.peer_chat_min_version, dbm.peer_chat_max_version, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.show_messages, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
dbp.display_name, dbp.full_name, dbp.image, dbp.contact_link, dbp.local_alias, dbp.preferences
FROM groups g
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
@ -1016,7 +1047,7 @@ toDirectChatItem currentTs (((itemId, itemTs, AMsgDirection msgDir, itemContentT
DBCINotDeleted -> Nothing
_ -> Just (CIDeleted @'CTDirect deletedTs)
itemEdited' = fromMaybe False itemEdited
in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs createdAt updatedAt
in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs Nothing createdAt updatedAt
ciTimed :: Maybe CITimed
ciTimed = timedTTL >>= \ttl -> Just CITimed {ttl, deleteAt = timedDeleteAt}
@ -1027,7 +1058,7 @@ toDirectChatItemList _ _ = []
type GroupQuoteRow = QuoteRow :. MaybeGroupMemberRow
type MaybeGroupChatItemRow = MaybeChatItemRow :. MaybeGroupMemberRow :. GroupQuoteRow :. MaybeGroupMemberRow
type MaybeGroupChatItemRow = MaybeChatItemRow :. Only (Maybe GroupMemberId) :. MaybeGroupMemberRow :. GroupQuoteRow :. MaybeGroupMemberRow
toGroupQuote :: QuoteRow -> Maybe GroupMember -> Maybe (CIQuote 'CTGroup)
toGroupQuote qr@(_, _, _, _, quotedSent) quotedMember_ = toQuote qr $ direction quotedSent quotedMember_
@ -1038,8 +1069,8 @@ toGroupQuote qr@(_, _, _, _, quotedSent) quotedMember_ = toQuote qr $ direction
direction _ _ = Nothing
-- this function can be changed so it never fails, not only avoid failure on invalid json
toGroupChatItem :: UTCTime -> Int64 -> ChatItemRow :. MaybeGroupMemberRow :. GroupQuoteRow :. MaybeGroupMemberRow -> Either StoreError (CChatItem 'CTGroup)
toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_) = do
toGroupChatItem :: UTCTime -> Int64 -> ChatItemRow :. Only (Maybe GroupMemberId) :. MaybeGroupMemberRow :. GroupQuoteRow :. MaybeGroupMemberRow -> Either StoreError (CChatItem 'CTGroup)
toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir, itemContentText, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. (fileId_, fileName_, fileSize_, filePath, fileKey, fileNonce, fileStatus_, fileProtocol_)) :. Only forwardedByGroupMemberId :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_) = do
chatItem $ fromRight invalid $ dbParseACIContent itemContentText
where
member_ = toMaybeGroupMember userContactId memberRow_
@ -1075,13 +1106,13 @@ toGroupChatItem currentTs userContactId (((itemId, itemTs, AMsgDirection msgDir,
DBCIBlocked -> Just (CIBlocked @'CTGroup deletedTs)
_ -> Just (maybe (CIDeleted @'CTGroup deletedTs) (CIModerated deletedTs) deletedByGroupMember_)
itemEdited' = fromMaybe False itemEdited
in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs createdAt updatedAt
in mkCIMeta itemId content itemText status sharedMsgId itemDeleted' itemEdited' ciTimed itemLive currentTs itemTs forwardedByGroupMemberId createdAt updatedAt
ciTimed :: Maybe CITimed
ciTimed = timedTTL >>= \ttl -> Just CITimed {ttl, deleteAt = timedDeleteAt}
toGroupChatItemList :: UTCTime -> Int64 -> MaybeGroupChatItemRow -> [CChatItem 'CTGroup]
toGroupChatItemList currentTs userContactId (((Just itemId, Just itemTs, Just msgDir, Just itemContent, Just itemText, Just itemStatus, sharedMsgId) :. (Just itemDeleted, deletedTs, itemEdited, Just createdAt, Just updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. fileRow) :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_) =
either (const []) (: []) $ toGroupChatItem currentTs userContactId (((itemId, itemTs, msgDir, itemContent, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. fileRow) :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_)
toGroupChatItemList currentTs userContactId (((Just itemId, Just itemTs, Just msgDir, Just itemContent, Just itemText, Just itemStatus, sharedMsgId) :. (Just itemDeleted, deletedTs, itemEdited, Just createdAt, Just updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. fileRow) :. forwardedByGroupMemberId :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_) =
either (const []) (: []) $ toGroupChatItem currentTs userContactId (((itemId, itemTs, msgDir, itemContent, itemText, itemStatus, sharedMsgId) :. (itemDeleted, deletedTs, itemEdited, createdAt, updatedAt) :. (timedTTL, timedDeleteAt, itemLive) :. fileRow) :. forwardedByGroupMemberId :. memberRow_ :. (quoteRow :. quotedMemberRow_) :. deletedByGroupMemberRow_)
toGroupChatItemList _ _ _ = []
getAllChatItems :: DB.Connection -> User -> ChatPagination -> Maybe String -> ExceptT StoreError IO [AChatItem]
@ -1525,19 +1556,21 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do
i.chat_item_id, i.item_ts, i.item_sent, i.item_content, i.item_text, i.item_status, i.shared_msg_id, i.item_deleted, i.item_deleted_ts, i.item_edited, i.created_at, i.updated_at, i.timed_ttl, i.timed_delete_at, i.item_live,
-- CIFile
f.file_id, f.file_name, f.file_size, f.file_path, f.file_crypto_key, f.file_crypto_nonce, f.ci_file_status, f.protocol,
-- CIMeta forwardedByGroupMemberId
i.forwarded_by_group_member_id,
-- GroupMember
m.group_member_id, m.group_id, m.member_id, m.member_role, m.member_category,
m.member_status, m.show_messages, m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
m.group_member_id, m.group_id, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category,
m.member_status, m.show_messages, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id,
p.display_name, p.full_name, p.image, p.contact_link, p.local_alias, p.preferences,
-- quoted ChatItem
ri.chat_item_id, i.quoted_shared_msg_id, i.quoted_sent_at, i.quoted_content, i.quoted_sent,
-- quoted GroupMember
rm.group_member_id, rm.group_id, rm.member_id, rm.member_role, rm.member_category,
rm.member_status, rm.show_messages, rm.invited_by, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id,
rm.group_member_id, rm.group_id, rm.member_id, rm.peer_chat_min_version, rm.peer_chat_max_version, rm.member_role, rm.member_category,
rm.member_status, rm.show_messages, rm.invited_by, rm.invited_by_group_member_id, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id,
rp.display_name, rp.full_name, rp.image, rp.contact_link, rp.local_alias, rp.preferences,
-- deleted by GroupMember
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.show_messages, dbm.invited_by, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
dbm.group_member_id, dbm.group_id, dbm.member_id, dbm.peer_chat_min_version, dbm.peer_chat_max_version, dbm.member_role, dbm.member_category,
dbm.member_status, dbm.show_messages, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id,
dbp.display_name, dbp.full_name, dbp.image, dbp.contact_link, dbp.local_alias, dbp.preferences
FROM chat_items i
LEFT JOIN files f ON f.chat_item_id = i.chat_item_id

View File

@ -88,6 +88,7 @@ import Simplex.Chat.Migrations.M20231010_member_settings
import Simplex.Chat.Migrations.M20231019_indexes
import Simplex.Chat.Migrations.M20231030_xgrplinkmem_received
import Simplex.Chat.Migrations.M20231107_indexes
import Simplex.Chat.Migrations.M20231113_group_forward
import Simplex.Messaging.Agent.Store.SQLite.Migrations (Migration (..))
schemaMigrations :: [(String, Query, Maybe Query)]
@ -175,7 +176,8 @@ schemaMigrations =
("20231010_member_settings", m20231010_member_settings, Just down_m20231010_member_settings),
("20231019_indexes", m20231019_indexes, Just down_m20231019_indexes),
("20231030_xgrplinkmem_received", m20231030_xgrplinkmem_received, Just down_m20231030_xgrplinkmem_received),
("20231107_indexes", m20231107_indexes, Just down_m20231107_indexes)
("20231107_indexes", m20231107_indexes, Just down_m20231107_indexes),
("20231113_group_forward", m20231113_group_forward, Just down_m20231113_group_forward)
]
-- | The list of migrations in ascending order by date

View File

@ -98,6 +98,7 @@ data StoreError
| SEHostMemberIdNotFound {groupId :: Int64}
| SEContactNotFoundByFileId {fileId :: FileTransferId}
| SENoGroupSndStatus {itemId :: ChatItemId, groupMemberId :: GroupMemberId}
| SEDuplicateGroupMessage {groupId :: Int64, sharedMsgId :: SharedMsgId, authorGroupMemberId :: Maybe GroupMemberId, forwardedByGroupMemberId :: Maybe GroupMemberId}
deriving (Show, Exception, Generic)
instance ToJSON StoreError where
@ -204,6 +205,17 @@ setPeerChatVRange db connId (VersionRange minVer maxVer) =
|]
(minVer, maxVer, connId)
setMemberChatVRange :: DB.Connection -> GroupMemberId -> VersionRange -> IO ()
setMemberChatVRange db mId (VersionRange minVer maxVer) =
DB.execute
db
[sql|
UPDATE group_members
SET peer_chat_min_version = ?, peer_chat_max_version = ?
WHERE group_member_id = ?
|]
(minVer, maxVer, mId)
setCommandConnId :: DB.Connection -> User -> CommandId -> Int64 -> IO ()
setCommandConnId db User {userId} cmdId connId = do
updatedAt <- getCurrentTime

View File

@ -666,9 +666,9 @@ instance ToJSON MemberInfo where
memberInfo :: GroupMember -> MemberInfo
memberInfo GroupMember {memberId, memberRole, memberProfile, activeConn} =
MemberInfo memberId memberRole memberChatVRange (fromLocalProfile memberProfile)
MemberInfo memberId memberRole cvr (fromLocalProfile memberProfile)
where
memberChatVRange = ChatVersionRange . fromJVersionRange . peerChatVRange <$> activeConn
cvr = ChatVersionRange . fromJVersionRange . peerChatVRange <$> activeConn
data ReceivedGroupInvitation = ReceivedGroupInvitation
{ fromMember :: GroupMember,
@ -690,6 +690,7 @@ data GroupMember = GroupMember
memberStatus :: GroupMemberStatus,
memberSettings :: GroupMemberSettings,
invitedBy :: InvitedBy,
invitedByGroupMemberId :: Maybe GroupMemberId,
localDisplayName :: ContactName,
-- for membership, memberProfile can be either user's profile or incognito profile, based on memberIncognito test.
-- for other members it's whatever profile the local user can see (there is no info about whether it's main or incognito profile for remote users).
@ -699,7 +700,10 @@ data GroupMember = GroupMember
-- for membership it would always point to user's contact
-- it is used to test for incognito status by comparing with ID in memberProfile
memberContactProfileId :: ProfileId,
activeConn :: Maybe Connection
activeConn :: Maybe Connection,
-- member chat protocol version range; if member has active connection, its version range is preferred;
-- for membership current supportedChatVRange is set, it's not updated on protocol version increase
memberChatVRange :: JVersionRange
}
deriving (Eq, Show, Generic)
@ -717,11 +721,17 @@ groupMemberRef GroupMember {groupMemberId, memberProfile = p} =
GroupMemberRef {groupMemberId, profile = fromLocalProfile p}
memberConn :: GroupMember -> Maybe Connection
memberConn = activeConn
memberConn GroupMember {activeConn} = activeConn
memberConnId :: GroupMember -> Maybe ConnId
memberConnId GroupMember {activeConn} = aConnId <$> activeConn
memberChatVRange' :: GroupMember -> VersionRange
memberChatVRange' GroupMember {activeConn, memberChatVRange} =
fromJVersionRange $ case activeConn of
Just Connection {peerChatVRange} -> peerChatVRange
Nothing -> memberChatVRange
groupMemberId' :: GroupMember -> GroupMemberId
groupMemberId' GroupMember {groupMemberId} = groupMemberId
@ -745,6 +755,7 @@ data NewGroupMember = NewGroupMember
memCategory :: GroupMemberCategory,
memStatus :: GroupMemberStatus,
memInvitedBy :: InvitedBy,
memInvitedByGroupMemberId :: Maybe GroupMemberId,
localDisplayName :: ContactName,
memProfileId :: Int64,
memContactId :: Maybe Int64
@ -1469,7 +1480,7 @@ data GroupMemberIntroStatus
| GMIntroReConnected
| GMIntroToConnected
| GMIntroConnected
deriving (Show)
deriving (Eq, Show)
instance FromField GroupMemberIntroStatus where fromField = fromTextField_ introStatusT

View File

@ -449,7 +449,7 @@ viewChats ts tz = concatMap chatPreview . reverse
viewChatItem :: forall c d. MsgDirectionI d => ChatInfo c -> ChatItem c d -> Bool -> CurrentTime -> TimeZone -> [StyledString]
viewChatItem chat ci@ChatItem {chatDir, meta = meta, content, quotedItem, file} doShow ts tz =
withItemDeleted <$> case chat of
withGroupMsgForwarded . withItemDeleted <$> (case chat of
DirectChat c -> case chatDir of
CIDirectSnd -> case content of
CISndMsgContent mc -> hideLive meta $ withSndFile to $ sndMsg to quote mc
@ -483,11 +483,14 @@ viewChatItem chat ci@ChatItem {chatDir, meta = meta, content, quotedItem, file}
from = ttyFromGroup g m
where
quote = maybe [] (groupQuote g) quotedItem
_ -> []
_ -> [])
where
withItemDeleted item = case chatItemDeletedText ci (chatInfoMembership chat) of
Nothing -> item
Just t -> item <> styled (colored Red) (" [" <> t <> "]")
withGroupMsgForwarded item = case meta.forwardedByGroupMemberId of
Nothing -> item
Just _ -> item <> styled (colored Yellow) (" [>>]" :: String)
withSndFile = withFile viewSentFileInvitation
withRcvFile = withFile viewReceivedFileInvitation
withFile view dir l = maybe l (\f -> l <> view dir f ts tz meta) file

View File

@ -68,7 +68,8 @@ testOpts =
logServerHosts = False,
logAgent = Nothing,
logFile = Nothing,
tbqSize = 16
tbqSize = 16,
highlyAvailable = False
},
chatCmd = "",
chatCmdDelay = 3,

View File

@ -7,12 +7,14 @@ import ChatClient
import ChatTests.Utils
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (concurrently_)
import Control.Monad (when)
import Control.Monad (when, void)
import qualified Data.ByteString as B
import qualified Data.Text as T
import Simplex.Chat.Controller (ChatConfig (..))
import Simplex.Chat.Controller (ChatConfig (..), XFTPFileConfig (..))
import Simplex.Chat.Protocol (supportedChatVRange)
import Simplex.Chat.Store (agentStoreFile, chatStoreFile)
import Simplex.Chat.Types (GroupMemberRole (..))
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
import Simplex.Messaging.Version
import System.Directory (copyFile)
import System.FilePath ((</>))
@ -103,6 +105,8 @@ chatGroupTests = do
it "invited member replaces member contact reference if it already exists" testMemberContactInvitedConnectionReplaced
it "share incognito profile" testMemberContactIncognito
it "sends and updates profile when creating contact" testMemberContactProfileUpdate
describe "forwarding messages" $ do
it "admin should forward messages between invitee and introduced" testGroupMsgForward
where
_0 = supportedChatVRange -- don't create direct connections
_1 = groupCreateDirectVRange
@ -1522,6 +1526,13 @@ testGroupDelayedModeration tmp = do
cath <## "#team: you joined the group"
]
threadDelay 1000000
-- imitate not implemented group forwarding
-- (real client wouldn't have forwarding code, but tests use "current code" with configured version,
-- and forwarding client doesn't check compatibility)
void $ withCCTransaction alice $ \db ->
DB.execute_ db "UPDATE group_member_intros SET intro_status='con'"
cath #> "#team hi" -- message is pending for bob
alice <# "#team cath> hi"
alice ##> "\\\\ #team @cath hi"
@ -1561,6 +1572,13 @@ testGroupDelayedModerationFullDelete tmp = do
cath <## "#team: you joined the group"
]
threadDelay 1000000
-- imitate not implemented group forwarding
-- (real client wouldn't have forwarding code, but tests use "current code" with configured version,
-- and forwarding client doesn't check compatibility)
void $ withCCTransaction alice $ \db ->
DB.execute_ db "UPDATE group_member_intros SET intro_status='con'"
cath #> "#team hi" -- message is pending for bob
alice <# "#team cath> hi"
alice ##> "\\\\ #team @cath hi"
@ -3644,9 +3662,9 @@ testMemberContactProhibitedRepeatInv =
testMemberContactInvitedConnectionReplaced :: HasCallStack => FilePath -> IO ()
testMemberContactInvitedConnectionReplaced tmp = do
withNewTestChat tmp "alice" aliceProfile $ \a -> withTestOutput a $ \alice -> do
withNewTestChat tmp "bob" bobProfile $ \b -> withTestOutput b $ \bob -> do
withNewTestChat tmp "cath" cathProfile $ \c -> withTestOutput c $ \cath -> do
withNewTestChat tmp "alice" aliceProfile $ \alice -> do
withNewTestChat tmp "bob" bobProfile $ \bob -> do
withNewTestChat tmp "cath" cathProfile $ \cath -> do
createGroup3 "team" alice bob cath
alice ##> "/d bob"
@ -3881,3 +3899,109 @@ testMemberContactProfileUpdate =
cath #> "#team hello there"
alice <# "#team kate> hello there"
bob <# "#team kate> hello there" -- updated profile
testGroupMsgForward :: HasCallStack => FilePath -> IO ()
testGroupMsgForward =
testChatCfg4 cfg aliceProfile bobProfile cathProfile danProfile $
\alice bob cath dan -> withXFTPServer $ do
createGroup3 "team" alice bob cath
threadDelay 1000000 -- delay so intro_status doesn't get overwritten to connected
void $ withCCTransaction bob $ \db ->
DB.execute_ db "UPDATE connections SET conn_status='deleted' WHERE group_member_id = 3"
void $ withCCTransaction cath $ \db ->
DB.execute_ db "UPDATE connections SET conn_status='deleted' WHERE group_member_id = 3"
void $ withCCTransaction alice $ \db ->
DB.execute_ db "UPDATE group_member_intros SET intro_status='fwd'"
bob #> "#team hi there"
alice <# "#team bob> hi there"
cath <# "#team bob> hi there [>>]"
threadDelay 1000000
cath #> "#team hey team"
alice <# "#team cath> hey team"
bob <# "#team cath> hey team [>>]"
alice ##> "/tail #team 2"
alice <# "#team bob> hi there"
alice <# "#team cath> hey team"
bob ##> "/tail #team 2"
bob <# "#team hi there"
bob <# "#team cath> hey team [>>]"
cath ##> "/tail #team 2"
cath <# "#team bob> hi there [>>]"
cath <# "#team hey team"
bob ##> "! #team hello there"
bob <# "#team [edited] hello there"
alice <# "#team bob> [edited] hello there"
cath <# "#team bob> [edited] hello there" -- TODO show as forwarded
cath ##> "+1 #team hello there"
cath <## "added 👍"
alice <# "#team cath> > bob hello there"
alice <## " + 👍"
bob <# "#team cath> > bob hello there"
bob <## " + 👍"
bob ##> "\\ #team hello there"
bob <## "message marked deleted"
alice <# "#team bob> [marked deleted] hello there"
cath <# "#team bob> [marked deleted] hello there" -- TODO show as forwarded
bob #> "/f #team ./tests/fixtures/test.jpg"
bob <## "use /fc 1 to cancel sending"
bob <## "completed uploading file 1 (test.jpg) for #team"
concurrentlyN_
[ do
alice <# "#team bob> sends file test.jpg (136.5 KiB / 139737 bytes)"
alice <## "use /fr 1 [<dir>/ | <path>] to receive it",
do
cath <# "#team bob> sends file test.jpg (136.5 KiB / 139737 bytes) [>>]"
cath <## "use /fr 1 [<dir>/ | <path>] to receive it [>>]"
]
cath ##> "/fr 1 ./tests/tmp"
cath <## "saving file 1 from bob to ./tests/tmp/test.jpg"
cath <## "started receiving file 1 (test.jpg) from bob"
cath <## "completed receiving file 1 (test.jpg) from bob"
src <- B.readFile "./tests/fixtures/test.jpg"
dest <- B.readFile "./tests/tmp/test.jpg"
dest `shouldBe` src
cath ##> "/mr #team bob member"
cath <## "#team: you changed the role of bob from admin to member"
alice <## "#team: cath changed the role of bob from admin to member"
bob <## "#team: cath changed your role from admin to member" -- TODO show as forwarded
connectUsers cath dan
cath ##> "/a #team dan"
cath <## "invitation to join the group #team sent to dan"
dan <## "#team: cath invites you to join the group as member"
dan <## "use /j team to accept"
dan ##> "/j #team"
dan <## "#team: you joined the group"
concurrentlyN_
[ cath <## "#team: dan joined the group",
do
alice <## "#team: cath added dan (Daniel) to the group (connecting...)"
alice <## "#team: new member dan is connected",
-- bob will not connect to dan, as introductions are not forwarded (yet?)
bob <## "#team: cath added dan (Daniel) to the group (connecting...)", -- TODO show as forwarded
dan <## "#team: member alice (Alice) is connected"
]
dan #> "#team hello all"
alice <# "#team dan> hello all"
-- bob <# "#team dan> hello all [>>]"
cath <# "#team dan> hello all"
bob #> "#team hi all"
alice <# "#team bob> hi all"
cath <# "#team bob> hi all [>>]"
-- dan <# "#team bob> hi all"
where
cfg = testCfg {xftpFileConfig = Just $ XFTPFileConfig {minFileSize = 0}, tempDir = Just "./tests/tmp"}

View File

@ -122,7 +122,7 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
"{\"v\":\"1\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}"
##==## ChatMessage chatInitialVRange (Just $ SharedMsgId "\1\2\3\4") (XMsgNew (MCSimple (extMsgContent (MCText "hello") Nothing)))
it "x.msg.new chat message with chat version range" $
"{\"v\":\"1-3\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}"
"{\"v\":\"1-4\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}"
##==## ChatMessage supportedChatVRange (Just $ SharedMsgId "\1\2\3\4") (XMsgNew (MCSimple (extMsgContent (MCText "hello") Nothing)))
it "x.msg.new quote" $
"{\"v\":\"1\",\"msgId\":\"AQIDBA==\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello to you too\",\"type\":\"text\"},\"quote\":{\"content\":{\"text\":\"hello there!\",\"type\":\"text\"},\"msgRef\":{\"msgId\":\"BQYHCA==\",\"sent\":true,\"sentAt\":\"1970-01-01T00:00:01.000000001Z\"}}}}"
@ -232,13 +232,13 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
"{\"v\":\"1\",\"event\":\"x.grp.mem.new\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
#==# XGrpMemNew MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile}
it "x.grp.mem.new with member chat version range" $
"{\"v\":\"1\",\"event\":\"x.grp.mem.new\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-3\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
"{\"v\":\"1\",\"event\":\"x.grp.mem.new\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-4\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
#==# XGrpMemNew MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile}
it "x.grp.mem.intro" $
"{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
#==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile}
it "x.grp.mem.intro with member chat version range" $
"{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-3\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
"{\"v\":\"1\",\"event\":\"x.grp.mem.intro\",\"params\":{\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-4\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
#==# XGrpMemIntro MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile}
it "x.grp.mem.inv" $
"{\"v\":\"1\",\"event\":\"x.grp.mem.inv\",\"params\":{\"memberId\":\"AQIDBA==\",\"memberIntro\":{\"directConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\",\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"}}}"
@ -250,7 +250,7 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
"{\"v\":\"1\",\"event\":\"x.grp.mem.fwd\",\"params\":{\"memberIntro\":{\"directConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\",\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
#==# XGrpMemFwd MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Nothing, profile = testProfile} IntroInvitation {groupConnReq = testConnReq, directConnReq = Just testConnReq}
it "x.grp.mem.fwd with member chat version range and w/t directConnReq" $
"{\"v\":\"1\",\"event\":\"x.grp.mem.fwd\",\"params\":{\"memberIntro\":{\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-3\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
"{\"v\":\"1\",\"event\":\"x.grp.mem.fwd\",\"params\":{\"memberIntro\":{\"groupConnReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"},\"memberInfo\":{\"memberRole\":\"admin\",\"memberId\":\"AQIDBA==\",\"v\":\"1-4\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}}"
#==# XGrpMemFwd MemberInfo {memberId = MemberId "\1\2\3\4", memberRole = GRAdmin, v = Just $ ChatVersionRange supportedChatVRange, profile = testProfile} IntroInvitation {groupConnReq = testConnReq, directConnReq = Nothing}
it "x.grp.mem.info" $
"{\"v\":\"1\",\"event\":\"x.grp.mem.info\",\"params\":{\"memberId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}"
@ -276,6 +276,12 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
it "x.grp.direct.inv without content" $
"{\"v\":\"1\",\"event\":\"x.grp.direct.inv\",\"params\":{\"connReq\":\"simplex:/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D1-2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D\"}}"
#==# XGrpDirectInv testConnReq Nothing
-- it "x.grp.msg.forward"
-- $ "{\"v\":\"1\",\"event\":\"x.grp.msg.forward\",\"params\":{\"msgForward\":{\"memberId\":\"AQIDBA==\",\"msg\":\"{\"v\":\"1\",\"event\":\"x.msg.new\",\"params\":{\"content\":{\"text\":\"hello\",\"type\":\"text\"}}}\",\"msgTs\":\"1970-01-01T00:00:01.000000001Z\"}}}"
-- #==# XGrpMsgForward
-- (MemberId "\1\2\3\4")
-- (ChatMessage chatInitialVRange (Just $ SharedMsgId "\1\2\3\4") (XMsgNew (MCSimple (extMsgContent (MCText "hello") Nothing))))
-- (systemToUTCTime $ MkSystemTime 1 1)
it "x.info.probe" $
"{\"v\":\"1\",\"event\":\"x.info.probe\",\"params\":{\"probe\":\"AQIDBA==\"}}"
#==# XInfoProbe (Probe "\1\2\3\4")

View File

@ -35,12 +35,12 @@
"hero-overlay-1-title": "Comment fonctionne SimpleX ?",
"hero-overlay-2-title": "Pourquoi les IDs d'utilisateur sont nuisibles pour votre vie privée ?",
"feature-1-title": "Messages chiffrés E2E avec édition et format markdown",
"feature-2-title": "Images et fichiers<br>chiffrés E2E",
"feature-3-title": "Groupes secrets décentralisés &mdash;<br>seuls ses membres connaissent leur existence",
"feature-2-title": "Images, vidéos et fichiers<br>chiffrés E2E",
"feature-3-title": "Groupes chiffrés E2E décentralisés &mdash; où seuls les membres en connaissent l'existence",
"feature-4-title": "Messages vocaux chiffrés E2E",
"feature-5-title": "Conversations secrètes éphémères",
"feature-6-title": "Appels audio et vidéo<br>chiffrés E2E",
"feature-7-title": "Base de données chiffrée portable &mdash; déplacez votre profil vers un autre appareil",
"feature-7-title": "Stockage de l'app portable chiffré &mdash; déplacez votre profil vers un autre appareil",
"feature-8-title": "Mode incognito &mdash;<br>unique à SimpleX Chat",
"simplex-network-overlay-1-title": "Comparaison avec des protocoles de messagerie P2P",
"simplex-private-1-title": "2 couches de<br>chiffrement de bout en bout",

View File

@ -154,12 +154,12 @@
"home": "Home",
"developers": "Sviluppatori",
"simplex-explained-tab-1-p-1": "Puoi creare contatti e gruppi, ed avere conversazioni bidirezionali, come in qualsiasi altro messenger.",
"feature-2-title": "Immagini e file<br>crittografati E2E",
"feature-2-title": "Immagini, video e file<br>crittografati E2E",
"simplex-private-card-4-point-2": "Per usare SimpleX tramite Tor, installa <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\">l'app Orbot</a> e attiva il proxy SOCKS5 (o VPN <a href=\"https://apps.apple.com/us/app/orbot/id1609461599?platform=iphone\" target=\"_blank\">su iOS</a>).",
"reference": "Riferimenti",
"simplex-explained-tab-3-text": "3. Cosa vedono i server",
"chat-bot-example": "Esempio di chat bot",
"feature-3-title": "Gruppi segreti decentralizzati &mdash;<br>solo gli utenti sanno che esistono",
"feature-3-title": "Gruppi decentralizzati crittografati E2E &mdash; solo gli utenti sanno che esistono",
"blog": "Blog",
"simplex-explained-tab-2-p-1": "Per ogni connessione usi due code di messaggi distinte per inviare e ricevere i messaggi attraverso server diversi.",
"simplex-explained-tab-2-p-2": "I server passano i messaggi solo in una direzione, senza avere il quadro completo della conversazione dell'utente o delle connessioni.",
@ -169,7 +169,7 @@
"feature-5-title": "Conversazioni segrete a tempo",
"feature-6-title": "Chiamate audio e video<br>crittografate E2E",
"simplex-private-6-title": "Scambio di chiavi<br>fuori banda",
"feature-7-title": "Database crittografato trasferibile &mdash; sposta il tuo profilo su un altro dispositivo",
"feature-7-title": "Archiviazione dell'app crittografata e trasferibile &mdash; sposta il profilo su un altro dispositivo",
"simplex-private-card-1-point-2": "Cryptobox NaCL in ogni coda per evitare correlazioni di traffico tra code di messaggi se il TLS è compromesso.",
"simplex-private-card-3-point-3": "Ripresa della connessione disattivata per evitare attacchi alla sessione.",
"hero-overlay-card-1-p-4": "Questo design impedisce la fuoriuscita di metadati degli utenti a livello di applicazione. Per aumentare ulteriormente la privacy e proteggere il tuo indirizzo IP puoi connetterti ai server di messaggistica tramite Tor.",

View File

@ -28,8 +28,8 @@
"hero-overlay-1-title": "Hoe werkt SimpleX?",
"hero-overlay-2-title": "Waarom zijn gebruikers-ID's slecht voor de privacy?",
"feature-1-title": "E2E-versleutelde berichten met markdown en bewerking",
"feature-2-title": "E2E-versleutelde<br>afbeeldingen en bestanden",
"feature-3-title": "Gedecentraliseerde geheime groepen -<br>alleen gebruikers weten dat ze bestaan",
"feature-2-title": "E2E-versleutelde<br>afbeeldingen,videos en bestanden",
"feature-3-title": "E2E-gecodeerde gedecentraliseerde groepen - alleen gebruikers weten dat ze bestaan",
"feature-4-title": "E2E-versleutelde spraakberichten",
"feature-5-title": "Verdwijnende geheime gesprekken",
"feature-6-title": "E2E-versleutelde<br>audio- en videogesprekken",
@ -60,7 +60,7 @@
"hero-p-1": "Andere apps hebben gebruikers-ID's: Signal, Matrix, Session, Briar, Jami, Cwtch, enz.<br> SimpleX niet, <strong>zelfs geen willekeurige getallen</strong>.<br> Dit verbetert uw privacy.",
"hero-2-header-desc": "De video laat zien hoe je verbinding maakt met een vriend via een persoonlijk of videolink gedeelde eenmalige QR-code. U kunt ook verbinding maken door een uitnodigingslink te delen.",
"hero-header": "Privacy opnieuw gedefinieerd",
"feature-7-title": "Portable versleutelde database &mdash; verplaats je profiel naar een ander apparaat",
"feature-7-title": "Draagbare gecodeerde app-opslag - profiel naar een ander apparaat verplaatsen",
"simplex-private-card-1-point-1": "Protocol met double-ratchet -<br>OTR-berichten met perfecte voorwaartse geheimhouding en inbraak herstel.",
"simplex-private-6-title": "Out-of-band<br>sleuteluitwisseling",
"simplex-private-7-title": "Bericht integriteit<br>verificatie",

View File

@ -27,11 +27,11 @@
"hero-overlay-1-title": "Jak działa SimpleX?",
"hero-overlay-2-title": "Dlaczego identyfikatory użytkowników (ID) są złe dla prywatności?",
"feature-1-title": "Wiadomości szyfrowane przez E2E ze składnią markdown i edycją",
"feature-3-title": "Zdecentralizowane tajne grupy &mdash;<br>tylko użytkownicy wiedzą, że te grupy istnieją",
"feature-3-title": "Zaszyfrowane E2E zdecentralizowane grupy &mdash; tylko użytkownicy wiedzą, że te grupy istnieją",
"feature-4-title": "Wiadomości głosowe zaszyfrowane przez E2E",
"feature-5-title": "Znikające wiadomości",
"feature-6-title": "Połączenia audio i wideo<br>szyfrowane przez E2E",
"feature-7-title": "Przenośna zaszyfrowana baza danych &mdash; przenieś swój profil na inne urządzenie",
"feature-7-title": "Przenośna zaszyfrowana pamięć aplikacji &mdash; przenieś profil na inne urządzenie",
"simplex-private-4-title": "Możliwy<br>dostęp za pośrednictwem sieci Tor",
"simplex-private-5-title": "Wielowarstwowy<br>padding treści",
"simplex-private-6-title": "Wymiana kluczy<br> out-of-band",
@ -49,7 +49,7 @@
"simplex-explained-tab-2-p-2": "Serwery przekazują wiadomości tylko w jedną stronę, nie mając pełnego obrazu konwersacji i połączeń użytkownika.",
"simplex-explained-tab-3-p-2": "Użytkownicy mogą jeszcze bardziej zwiększyć prywatność metadanych, używając Tor do uzyskania dostępu do serwerów, co zapobiega korelacji na podstawie adresu IP.",
"hero-p-1": "Inne aplikacje mają identyfikatory użytkowników (ID): Signal, Matrix, Session, Briar, Jami, Cwtch itp.<br> SimpleX nie, <strong>nie ma nawet losowych numerów</strong>.<br> To radykalnie poprawia Twoją prywatność.",
"feature-2-title": "Obrazy i pliki<br>zaszyfrowane przez E2E",
"feature-2-title": "Obrazy, wideo i pliki<br>zaszyfrowane przez E2E",
"feature-8-title": "Tryb incognito &mdash;<br>unikalny dla SimpleX Chat",
"simplex-network-overlay-1-title": "Porównanie z protokołami komunikacyjnymi P2P",
"simplex-private-1-title": "Dwie warstwy<br>szyfrowania typu end-to-end",
@ -243,5 +243,12 @@
"f-droid-org-repo": "Repo F-Droid.org",
"stable-versions-built-by-f-droid-org": "Wersje stabilne zbudowane przez F-Droid.org",
"releases-to-this-repo-are-done-1-2-days-later": "Wydania na tym repo są 1-2 dni później",
"comparison-section-list-point-4a": "Przekaźniki SimpleX nie mogą skompromitować szyfrowania e2e. Zweryfikuj kody bezpieczeństwa aby złagodzić atak na kanał pozapasmowy"
"comparison-section-list-point-4a": "Przekaźniki SimpleX nie mogą skompromitować szyfrowania e2e. Zweryfikuj kody bezpieczeństwa aby złagodzić atak na kanał pozapasmowy",
"hero-overlay-3-title": "Ocena bezpieczeństwa",
"hero-overlay-card-3-p-2": "Trail of Bits przejrzał komponenty kryptograficzne i sieciowe platformy SimpleX w listopadzie 2022.",
"hero-overlay-card-3-p-3": "Przeczytaj więcej w <a href=\"/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html\">ogłoszeniach</a>.",
"jobs": "Dołącz do zespołu",
"hero-overlay-3-textlink": "Ocena bezpieczeństwa",
"hero-overlay-card-3-p-1": "<a href=\"https://www.trailofbits.com/about/\">Trail of Bits</a> jest wiodącą firmą konsultingową w zakresie bezpieczeństwa i technologii, której klientami są duże firmy technologiczne, agencje rządowe i główne projekty blockchain.",
"docs-dropdown-9": "Pliki do pobrania"
}

View File

@ -1 +1,254 @@
{}
{
"copy-the-command-below-text": "скопируйте приведенную ниже команду и используйте ее в чате:",
"copyright-label": "© 2020-2023 SimpleX | Проект с открытым исходным кодом",
"chat-bot-example": "Пример Чат бота",
"simplex-private-card-9-point-1": "Каждая очередь сообщений передает сообщения в одном направлении с разными адресами отправки и получения.",
"simplex-private-card-1-point-2": "Криптобокс NaCL в каждой очереди для предотвращения корреляции трафика между очередями сообщений, в случае компрометации TLS.",
"contact-hero-p-1": "Открытые ключи и адрес очереди сообщений по этой ссылке НЕ отправляются по сети при просмотре этой страницы &mdash; они содержатся в хэш-фрагменте URL-адреса ссылки.",
"guide-dropdown-5": "Управление данными",
"scan-the-qr-code-with-the-simplex-chat-app": "Отсканируйте QR-код с помощью приложения SimpleX Chat",
"simplex-private-card-9-point-2": "Это уменьшает векторы атак и доступные метаданные, по сравнению с традиционными посредниками для доставки сообщений.",
"simplex-unique-card-3-p-2": "Сквозные зашифрованные сообщения временно хранятся на серверах SimpleX до получения, после чего они удаляются безвозвратно.",
"feature-7-title": "Портативное, зашифрованное хранилище в приложении &mdash; можно перенести профиль на другое устройство",
"no-federated": "Нет - федеративный",
"hero-2-header": "Как начать общаться приватно",
"simplex-unique-overlay-card-3-p-3": "В отличие от серверов федеративных сетей (электронной почты, XMPP или Matrix), серверы SimpleX не хранят учетные записи пользователей, они только ретранслируют сообщения, защищая конфиденциальность обеих сторон.",
"hero-subheader": "Первый мессенджер<br>не нуждающийся в идентификаторах<br>пользователя",
"privacy-matters-overlay-card-3-p-2": "Одна из самых шокирующих историй - это опыт <a href='https://ru.wikipedia.org/wiki/Слахи,_Мохаммед_Ульд' target='_blank'>Слахи, Мохаммеда Ульда</a>, описанный в его мемуарах и показанный в фильме <a href='https://ru.wikipedia.org/wiki/Мавританец' target='_blank'>Мавританец</a>. Он был помещен в лагерь Гуантанамо без суда и следствия и подвергался там пыткам в течение 15 лет после телефонного звонка своему родственнику в Афганистан под подозревается в причастности к терактам 11 сентября, хотя предыдущие 10 лет он жил в Германии.",
"signing-key-fingerprint": "Отпечаток ключа подписи (SHA-256)",
"simplex-network-2-desc": "Серверные узлы SimpleX НЕ хранят профили пользователей, контакты и доставленные сообщения, НЕ подключаются друг к другу, и НЕ имеют каталога серверов.",
"simplex-privacy": "Конфиденциальность SimpleX",
"docs-dropdown-5": "Свой XFTP Сервер",
"simplex-private-card-3-point-2": "Отпечаток сервера и привязка канала предотвращают MITM атаки и Атаки повторного воспроизведения.",
"docs-dropdown-3": "Доступ к в базе данных чата",
"installing-simplex-chat-to-terminal": "Установка SimpleX Chat в терминале",
"use-this-command": "Используйте эту команду:",
"simplex-explained": "Простое объяснение вкратце",
"to-make-a-connection": "Чтобы установить соединение:",
"comparison-section-list-point-6": "Хотя P2P распределены, они не являются федеративными, то есть P2P - работают как единая сеть",
"hero-overlay-2-textlink": "Как работает SimpleX?",
"simplex-chat-via-f-droid": "SimpleX Chat в F-Droid",
"privacy-matters-overlay-card-1-p-1": "Многие крупные компании используют информацию о том, с кем вы связаны, чтобы оценить ваш доход, продавать вам больше товаров, которые вам на самом деле не нужны, и определять из этой информации, выгодные для них цены.",
"privacy-matters-1-overlay-1-title": "Конфиденциальность экономит ваши деньги",
"simplex-private-card-5-point-1": "SimpleX использует заполнение содержимого для каждого уровня шифрования, чтобы предотвратить атаки на размер сообщения.",
"privacy-matters-2-overlay-1-linkText": "Конфиденциальность дает вам власть",
"hero-overlay-3-title": "Оценка безопасности",
"enter-your-email-address": "Email адрес",
"simplex-explained-tab-1-text": "1. Как это видят пользователи",
"tap-to-close": "Нажмите, чтобы закрыть",
"simplex-unique-card-4-p-2": "Вы можете <strong>использовать SimpleX со своими собственными серверами</strong> или с серверами, предоставленными нами &mdash; и при этом подключаться к любому пользователю SimpleX.",
"hero-overlay-card-3-p-2": "В ноябре 2022 года Trail of Bits провела обзор криптографии и сетевых компонентов SimpleX.",
"feature-1-title": "Сообщения зашифрованные E2E-шифрованием<br>с поддержкой markdown и редактированием",
"comparison-point-4-text": "Единая или Централизованная сеть",
"guide-dropdown-9": "Установление соединений",
"simplex-unique-1-overlay-1-title": "Полная конфиденциальность вашей личности, профиля, контактов и других метаданных",
"hero-overlay-card-2-p-4": "SimpleX защищает от этих атак, поскольку в его конструкции нет никаких идентификаторов пользователей. И, если вы используете режим инкогнито, у вас будет другое отображаемое имя для каждого контакта, что позволит избежать какого-либо пересечения между ними.",
"privacy-matters-overlay-card-2-p-2": "Чтобы быть объективным и принимать независимые решения, вам необходимо контролировать свое информационное пространство. Это возможно только в том случае, если вы используете приватную, коммуникационную платформу, которая не имеет доступа к вашему социальному графу.",
"hero-overlay-card-2-p-1": "Когда у пользователей есть постоянные идентификаторы, даже если это просто случайное число, например идентификатор сеанса, существует риск того, что провайдер или злоумышленник могут наблюдайте за тем, как подключены пользователи и сколько сообщений они отправляют.",
"feature-3-title": "Децентрализованные группы &mdash; только<br>их участники знают, что они существуют",
"glossary": "Глоссарий",
"simplex-network-overlay-1-title": "Сравнение с протоколами обмена сообщениями P2P",
"comparison-section-list-point-7": "Сети P2P либо имеют центральный орган управления, либо вся сеть может быть скомпрометирована",
"simplex-unique-overlay-card-4-p-1": "Вы можете <strong>использовать SimpleX со своими собственными серверами</strong> или предоставленными нами серверами, при этом имея возможность общаться с любым пользователем.",
"simplex-explained-tab-3-p-1": "Серверы имеют отдельные, Анонимные учётные данные для каждой очереди и не знают, к каким пользователям они принадлежат.",
"docs-dropdown-1": "Платформа SimpleX",
"hero-overlay-card-1-p-5": "Только клиентские устройства хранят профили пользователей, контакты и группы; сообщения отправляются с двухуровневым, Сквозным шифрованием.",
"simplex-chat-for-the-terminal": "SimpleX Chat для терминала",
"simplex-network-overlay-card-1-li-3": "P2P не решает проблему <a href='https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%B0%D0%BA%D0%B0_%D0%BF%D0%BE%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D0%BA%D0%B0'>MITM-атаки (Атака посредника)</a>, и большинство существующих реализаций не используют внеполосные сообщения для первоначального обмена ключами. SimpleX использует внеполосные сообщения или, в некоторых случаях, ранее существовавшие защищенные и доверенные соединения для первоначального обмена ключами.",
"the-instructions--source-code": "SimpleX Chat.",
"simplex-network-section-desc": "SimpleX Chat обеспечивает наилучшую конфиденциальность, сочетая преимущества P2P и федеративных сетей.",
"privacy-matters-section-subheader": "Сохранение конфиденциальности ваших метаданных &mdash; <span class='text-active-blue'>с кем вы общаетесь</span> &mdash; защищает вас от:",
"if-you-already-installed": "Если вы уже установили",
"simplex-explained-tab-3-p-2": "Пользователи могут еще больше повысить свою конфиденциальность скрыв свой IP-адрес, например используя сеть Tor для доступа к серверам.",
"join": "Присоединяйся к",
"privacy-matters-section-header": "Почему приватность <span class='gradient-text'>важна</span>",
"hero-overlay-1-textlink": "Почему идентификаторы пользователя - вредны для приватности?",
"on-this-page": "На этой странице",
"privacy-matters-overlay-card-1-p-2": "Интернет-магазины знают, что люди с более низкими доходами с большей вероятностью совершают срочные покупки, поэтому они могут устанавливать более высокие цены или отменять скидки.",
"simplex-unique-3-overlay-1-title": "Контроль и безопасность ваших данных",
"protocol-3-text": "Протоколы P2P",
"simplex-private-card-6-point-2": "Чтобы предотвратить это, приложения SimpleX передают одноразовые ключи внеполосно, когда вы делитесь адресом в виде ссылки или QR-кода.",
"no": "Нет",
"contact-hero-header": "Вы получили адрес для подключения в SimpleX Chat",
"feature-8-title": "Режим инкогнито &mdash;<br>уникальный для SimpleX Chat",
"why-simplex": "Что делает SimpleX уникальным",
"simplex-private-card-4-point-2": "Чтобы использовать SimpleX через сеть Tor, пожалуйста, установите <a href=\"https://guardianproject.info/apps/org.torproject.android/\" target=\"_blank\">приложение Orbot</a> и включите прокси (или режим VPN <a href=\"https://apps.apple.com/us/app/orbot/id1609461599?platform=iphone\" target=\"_blank\">на iOS</a>).",
"contact-hero-subheader": "Отсканируйте QR-код с помощью приложения SimpleX Chat на вашем телефоне или планшете.",
"simplex-unique-2-overlay-1-title": "Лучшая защита от спама и злоупотреблений",
"simplex-private-6-title": "Внеполосный<br>Обмен ключами",
"join-us-on-GitHub": "Присоединяйтесь к нам на GitHub",
"hero-overlay-card-3-p-3": "Подробнее читайте в <a href=\"/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html\">анонсе</a>.",
"comparison-section-header": "Сравнение с другими протоколами",
"invitation-hero-header": "Вы получили одноразовую ссылку для подключения в SimpleX Chat",
"no-secure": "Нет - безопасно",
"hero-overlay-card-1-p-2": "Для доставки сообщений вместо идентификаторов пользователей, используемых всеми другими платформами, SimpleX использует временные, анонимные, попарные идентификаторы очередей сообщений, отдельно для каждого из ваших контактов &mdash; нет долгосрочных идентификаторов.",
"simplex-explained-tab-1-p-2": "Как это может работать с однонаправленными очередями и без идентификаторов профиля пользователя?",
"simplex-network-1-header": "В отличие от P2P-сетей",
"jobs": "Присоединиться к команде",
"simplex-private-card-7-point-2": "Если какое-либо сообщение будет добавлено, удалено или изменено, получатель будет предупрежден об этом.",
"simplex-unique-3-title": "Только вы контролируете<br>свои данные",
"guide-dropdown-3": "Секретные группы",
"no-resilient": "Нет - устойчив",
"hide-info": "Спрятать информацию",
"privacy-matters-overlay-card-3-p-4": "Недостаточно просто использовать мессенджер со сквозным шифрованием, мы все должны использовать мессенджеры, которые защищают конфиденциальность наших личных сетей &mdash; с какими людьми мы связаны.",
"releases-to-this-repo-are-done-1-2-days-later": "Выпуск новых версий в этом репозитории выходит с задержкой в 1-2 дня",
"comparison-point-1-text": "Требуется глобальный идентификатор",
"comparison-section-list-point-5": "Не защищает конфиденциальность пользовательских метаданных",
"hero-overlay-card-2-p-2": "Затем они могли бы сопоставить эту информацию с существующими общедоступными социальными сетями и определить некоторые реальные личности.",
"privacy-matters-overlay-card-1-p-3": "Некоторые финансовые и страховые компании используют социальные графики для определения процентных ставок и премий. Это часто заставляет людей с более низкими доходами платить больше &mdash; это известно как <a href='https://fairbydesign.com/povertypremium/' target='_blank'>\"премия за бедность\"</a>.",
"comparison-point-3-text": "Зависимость от DNS",
"yes": "Да",
"docs-dropdown-6": "Сервера WebRTC",
"newer-version-of-eng-msg": "Существует более новая версия этой страницы на английском языке.",
"install-simplex-app": "Установите приложение SimpleX",
"hero-overlay-3-textlink": "Оценка безопасности",
"comparison-point-2-text": "Возможность MITM",
"scan-the-qr-code-with-the-simplex-chat-app-description": "Открытые ключи и адрес очереди сообщений, указанные в этой ссылке, НЕ отправляются по сети при просмотре этой страницы &mdash;<br> они содержатся в хэш-фрагменте URL-адреса ссылки.",
"guide-dropdown-8": "Настройки приложения",
"simplex-explained-tab-2-p-2": "Серверы передают сообщения только в одну сторону, не имея полной картины общения пользователя или подключений.",
"smp-protocol": "Протокол SMP",
"open-simplex-app": "Откройте приложение SimpleX",
"see-simplex-chat": "Инструкции по загрузке или компиляции SimpleX Chat из исходного кода приведены в",
"terminal-cli": "Приложение для терминала (CLI)",
"comparison-section-list-point-1": "Обычно требуется номера телефона, в некоторых случаях — имя пользователя",
"simplex-explained-tab-3-text": "3. Что видят сервера",
"github-repository": "репозиторий Github",
"feature-5-title": "Исчезающие сообщения",
"connect-in-app": "Подключитесь в приложении",
"menu": "Меню",
"simplex-private-card-4-point-1": "Чтобы защитить свой IP-адрес вы можете подключаться к серверам через сеть Tor или какую-либо другую транспортную оверлейную сеть.",
"privacy-matters-3-title": "Судебное преследование не виновных",
"comparison-point-5-text": "Атака на центральный компонент или другая сетевая атака",
"click-to-see": "Нажать здесь, чтобы увидеть",
"donate-here-to-help-us": "Пожертвуйте здесь, чтобы помочь нам",
"simplex-private-1-title": "2-уровневое<br>сквозное шифрование",
"simplex-unique-card-1-p-2": "В отличие от любой другой существующей платформы обмена сообщениями, SimpleX не имеет идентификаторов пользователей &mdash; <strong>нету даже случайных цифр</strong>.",
"privacy-matters-2-overlay-1-title": "Конфиденциальность дает вам власть",
"simplex-unique-overlay-card-2-p-2": "Хоть злоумышленники и могут использовать постоянный адрес для отправки нежелательных запросов или спама, вы можете легко его изменить или просто удалить, не теряя связи с уже установленными контактами.",
"simplex-unique-4-overlay-1-title": "Полностью децентрализованная &mdash; пользователи владеют сетью SimpleX",
"guide-dropdown-2": "Отправка сообщений",
"simplex-network-overlay-card-1-li-5": "Все известные P2P-сети могут быть уязвимы для <a href='https://ru.wikipedia.org/wiki/Sybil_attack'>Атаки Сивиллы</a>, поскольку каждый узел доступен для обнаружения, и сеть работает как единое целое. Известные меры по его смягчению требуют либо централизованного компонента, либо дорогостоящего <a href='https://ru.wikipedia.org/wiki/Proof-of-work'>Proof-of-work</a>. Сеть SimpleX не имеет функционала по обмену серверами, она фрагментирована и работает как множество изолированных подсетей, из-за чего провести атаку по всей сети - невозможно.",
"simplex-private-2-title": "Дополнительный уровень<br>шифрования сервера",
"hero-overlay-card-1-p-4": "Такая конструкция предотвращает утечку любых пользовательских метаданных на уровне приложения. Для дальнейшего улучшения конфиденциальности и защиты вашего IP-адреса вы можете подключиться к серверам обмена сообщениями через сеть Tor.",
"f-droid-org-repo": "Репозиторий F-Droid.org",
"guide-dropdown-4": "Профили чата",
"simplex-network-2-header": "В отличие от федеративных сетей",
"see-here": "подробней тут",
"simplex-private-3-title": "Безопасный аутентифицированный<br>протокол TLS",
"comparison-section-list-point-3": "Открытый ключ или какой-либо другой глобально уникальный идентификатор",
"hero-overlay-card-2-p-3": "Даже в самых приватных приложениях, использующих скрытые сервисы Tor v3, если вы общаетесь с двумя разными контактами через один и тот же профиль, они могут доказать, что они являются связаны с одним и тем же человеком.",
"simplex-private-4-title": "Вариант доступа<br>через сеть Tor",
"privacy-matters-1-title": "Реклама и ценовая дискриминация",
"simplex-unique-card-3-p-1": "SimpleX хранит все пользовательские данные на клиентских устройствах в <strong>портативном формате зашифрованной базы данных</strong> &mdash; их можно перенести на другое устройство.",
"hero-overlay-1-title": "Как работает SimpleX?",
"stable-versions-built-by-f-droid-org": "Стабильные версии, созданные F-Droid.org",
"contact-hero-p-3": "Воспользуйтесь ссылками ниже, чтобы загрузить приложение.",
"simplex-network": "Сеть SimpleX",
"privacy-matters-3-overlay-1-title": "Конфиденциальность защищает вашу свободу",
"docs-dropdown-7": "Перевести SimpleX Chat",
"back-to-top": "Вернуться к началу",
"simplex-network-1-desc": "Все сообщения отправляются через серверы, что обеспечивает лучшую конфиденциальность метаданных и надежную асинхронную доставку сообщений, избегая при этом многих",
"simplex-chat-repo": "Репозиторий SimpleX Chat",
"simplex-private-card-6-point-1": "Многие коммуникационные платформы уязвимы для MITM-атак со стороны серверов или сетевых провайдеров.",
"privacy-matters-3-overlay-1-linkText": "Конфиденциальность защищает вашу свободу",
"simplex-unique-overlay-card-1-p-2": "Для доставки сообщений SimpleX использует <a href='https://csrc.nist.gov/glossary/term/Pairwise_Pseudonymous_Identifier'>попарные, анонимные адреса</a> однонаправленных очередей сообщений, раздельные для полученных и отправленных сообщений, обычно через разные серверы. Использование SimpleX это как иметь <strong>отдельный &ldquo;одноразовый&rdquo; адрес электронной почты или номер телефона для каждого контакта</strong>, при это, не обременяя вас управлять эти вручную.",
"simplex-unique-overlay-card-3-p-4": "Со стороны не видно разницу между отправлением или получением сообщений &mdash; если кто-то наблюдает за этим, он не cможет легко определить, кто с кем общается, даже если протокол TLS будет скомпрометирован.",
"docs-dropdown-2": "Доступ к файлам в версии для Android",
"get-simplex": "Скачать SimpleX <a href=\"/downloads/#desktop-app\">для ПК</a>",
"privacy-matters-overlay-card-3-p-1": "Каждый должен заботиться о конфиденциальности и безопасности своих коммуникаций &mdash; безобидные разговоры могут подвергнуть вас опасности, например за ваши политические взгляды, даже если кажется, что вам \"нечего скрывать\".",
"simplex-unique-2-title": "Вы защищены от<br>спама и злоупотреблений",
"simplex-unique-overlay-card-4-p-3": "Если вы рассматриваете возможность разработки платформе SimpleX, например, чат-бота для пользователей SimpleX или интеграции библиотеки SimpleX Chat в ваше мобильное приложение, пожалуйста, <a href='https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D' target='_blank'>обращайтесь</a> за любыми советами и поддержкой.",
"comparison-section-list-point-2": "Адреса на основе DNS",
"stable-and-beta-versions-built-by-developers": "Стабильные и бета-версии, созданные разработчиками",
"simplex-network-3-header": "Сеть SimpleX",
"simplex-unique-card-2-p-1": "Поскольку у вас нет идентификатора или фиксированного адреса на платформе SimpleX, никто не сможет связаться с вами, без вашего явного согласия, только если вы сами поделитесь адресом в виде QR-кода или ссылки.",
"hero-overlay-card-3-p-1": "<a href=\"https://www.trailofbits.com/about/\">Trail of Bits</a> - ведущая консалтинговая компания в области безопасности и технологий, клиентами которой являются крупные технологические компании, правительственные агентства и крупные блокчейн проекты.",
"hero-header": "Иной взгляд на приватность",
"comparison-section-list-point-4": "Если операторы серверов скомпрометированы. В Signal, и некоторых других приложениях, есть возможность подтвердить код безопасности",
"simplex-private-card-2-point-1": "Дополнительный уровень серверного шифрования для доставки получателю, чтобы предотвратить корреляцию между полученным и отправленным трафиком сервера, если используемый протокол TLS скомпрометированный.",
"f-droid-page-simplex-chat-repo-section-text": "Чтобы добавить его в свой клиент F-Droid, <span class='hide-on-mobile'>отсканируйте QR-код или </span>воспользуйтесь этим URL-адресом:",
"guide-dropdown-7": "Приватность и безопасность",
"join-the-REDDIT-community": "Присоединяйтесь к нам в сообществе REDDIT",
"simplex-private-card-10-point-2": "Это позволяет доставлять сообщения без идентификаторов профиля пользователя, обеспечивая лучшую конфиденциальность метаданных, чем другие альтернативы.",
"privacy-matters-2-title": "Манипулирование выборами",
"home": "Домашняя страница",
"chat-protocol": "Протокол чата",
"simplex-private-card-5-point-2": "Это позволяет сообщениям разного размера выглядеть одинаково для серверов и сетевых наблюдателей.",
"hero-overlay-card-1-p-1": "Многие спрашивают:<em>Если у SimpleX нету никаких идентификаторов пользователя, то как приложение знает, куда доставлять сообщения?</em>",
"feature-6-title": "Зашифрованные E2E-шифрованием аудио и видео звонки",
"hero-p-1": "Другие приложения имеют ID своих пользователей: Signal, Matrix, Session, Briar, Jami, Cwtch и т. п.<br>SimpleX не имет, <strong>нету даже случайных цифр</strong>.<br>Это значительно повышает вашу приватность.",
"simplex-network-overlay-card-1-li-2": "В отличие от многих P2P сетей, SimpleX спроектирован так, чтобы не нуждаться в глобальных идентификаторов его пользователей, даже временных, используя только временные попарные идентификаторы, обеспечивая лучшую анонимность и защиту метаданных пользователя.",
"simplex-unique-4-title": "Только вы владеете<br>сетью SimpleX",
"privacy-matters-overlay-card-3-p-3": "Обычных людей арестовывают за то, чем они делятся в Интернете, даже через свои \"анонимные\" аккаунты, <a href='https://www.dailymail.co.uk/news/article-11282263/Moment-police-swoop-house-devout-catholic-mother-malicious-online-posts.html' target='_blank'>даже в демократических странах</a>.",
"simplex-unique-overlay-card-3-p-2": "Сквозные зашифрованные сообщения временно хранятся на серверах SimpleX до получения, после чего они удаляются безвозвратно.",
"blog": "Новости",
"simplex-private-card-7-point-1": "Чтобы гарантировать целостность, сообщения последовательно нумеруются и включают в себя хэш предыдущего сообщения.",
"simplex-unique-overlay-card-4-p-2": "Платформа SimpleX использует <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>открытый протокол</a> и предоставляет <a href='https://github.com/simplex-chat/simplex-chat/tree/stable/packages/simplex-chat-client/typescript' target='_blank'>SDK для создания чат-ботов</a>, позволяя внедрять сервисы, с которыми пользователи могут взаимодействовать через приложение SimpleX Chat &mdash; мы с нетерпением ждем возможности увидеть, какие сервисы SimpleX вы сможете создать.",
"simplex-explained-tab-1-p-1": "Вы можете создавать контакты и группы, а также вести двусторонние беседы, как и в любом другом мессенджере.",
"contact-hero-p-2": "Еще не скачали SimpleX Chat?",
"why-simplex-is": "Почему SimpleX",
"simplex-network-section-header": "<span class='gradient-text'>Сеть</span> SimpleX",
"simplex-private-10-title": "Временные анонимные парные идентификаторы",
"privacy-matters-1-overlay-1-linkText": "Конфиденциальность экономит ваши деньги",
"tap-the-connect-button-in-the-app": "Нажмите на кнопку <span class='text-active-blue'>’подключиться’</span> в приложении",
"comparison-section-list-point-4a": "Сервера SimpleX не могут скомпрометировать сквозное шифрование",
"unique": "уникальный",
"simplex-network-1-overlay-linktext": "проблем P2P сетей",
"no-private": "Нет - приватно",
"simplex-unique-1-title": "У вас есть полная<br>конфиденциальность",
"protocol-2-text": "XMPP, Matrix",
"guide": "Руководство",
"simplex-network-overlay-card-1-li-4": "Реализации P2P могут быть заблокированы некоторыми интернет-провайдерами (например, <a href='https://ru.wikipedia.org/wiki/BitTorrent'>BitTorrent</a>). SimpleX не зависит от транспорта - он может работать по стандартным веб-протоколам, например WebSockets.",
"hero-overlay-2-title": "Почему идентификаторы пользователя - вредны для приватности?",
"simplex-explained-tab-2-text": "2. Как это работает",
"docs-dropdown-4": "Свой SMP Сервер",
"feature-4-title": "Зашифрованные E2E-шифрованием голосовые сообщения",
"privacy-matters-overlay-card-2-p-1": "Не так давно мы наблюдали, как <a href='https://en.wikipedia.org/wiki/FacebookCambridge_Analytica_data_scandal' target='_blank'>авторитетная консалтинговая компания</a> манипулировала крупными выборами, используя наши социальные графики для искажения нашего мнения из реального мира и манипулируют нашими голосами.",
"privacy-matters-overlay-card-2-p-3": "SimpleX - это первая платформа, которая по своей конструкции не имеет никаких идентификаторов пользователей, таким образом защищая график ваших контактов лучше, чем любая известная альтернатива.",
"learn-more": "Учить больше",
"donate": "Пожертвовать",
"simplex-private-8-title": "Смешивание сообщений<br>для уменьшения корреляции",
"scan-qr-code-from-mobile-app": "Отсканируйте QR-код в мобильном приложении",
"simplex-private-card-3-point-3": "Возобновление соединения отключено для предотвращения сеансовых атак.",
"simplex-private-card-10-point-1": "SimpleX использует временные анонимные попарные адреса и учетные данные для каждого контакта пользователя или члена группы.",
"guide-dropdown-6": "Аудио и видео Звонки",
"more-info": "Больше информации",
"no-decentralized": "Нет - децентрализованный",
"protocol-1-text": "Signal, большие платформы",
"hero-2-header-desc": "В видео показано, как подключиться к своему другу с помощью его одноразового QR-кода, лично или по видеосвязи. Вы также можете подключиться, поделившись ссылкой-приглашением.",
"simplex-network-overlay-card-1-li-6": "Сети P2P могут быть уязвимы для <a href='https://www.usenix.org/conference/woot15/workshop-program/presentation/p2p-file-sharing-hell-exploiting-bittorrent'>DRDoS атаки</a>, когда клиенты могут ретранслировать и усиливать/увеличивать объём трафика, что приводит к отказу в обслуживании по всей сети. Клиенты SimpleX ретранслируют трафик только из известного соединения и не могут быть использованы злоумышленником для нагрузки трафика всей сети.",
"if-you-already-installed-simplex-chat-for-the-terminal": "Если вы уже установили SimpleX Chat для терминала",
"docs-dropdown-8": "Служба Каталогов SimpleX",
"simplex-private-card-1-point-1": "Протокол с двойным храповым механизмом &mdash;<br> обмен сообщениями OTR с идеальной секретностью пересылки и восстановлением после взлома.",
"simplex-private-card-8-point-1": "Серверы SimpleX действуют как узлы-миксеры с низкой задержкой &mdash; входящие и исходящие сообщения имеют разный порядок.",
"simplex-unique-overlay-card-2-p-1": "Поскольку у вас нет идентификатора на платформе SimpleX, никто не сможет связаться с вами, если вы сами не предоставите одноразовый или временный адрес в виде QR-кода или ссылки.",
"sign-up-to-receive-our-updates": "Введите ваш Email, чтобы получать рассылку обновлений от нас",
"guide-dropdown-1": "Быстрый старт",
"simplex-explained-tab-2-p-1": "Для каждого подключения вы используете две отдельные очереди обмена сообщениями, то есть отправка и получения сообщений происходит через разные серверы.",
"simplex-private-section-header": "Что делает SimpleX <span class='gradient-text'>приватным</span>",
"we-invite-you-to-join-the-conversation": "Мы приглашаем вас присоединиться к беседе",
"feature-2-title": "Изображения, видео и файлы<br>зашифрованные E2E-шифрованием",
"simplex-private-9-title": "Однонаправленные<br>очереди сообщений",
"simplex-unique-overlay-card-1-p-3": "Этот дизайн защищает конфиденциальность того, с кем вы общаетесь, скрывая это от серверов SimpleX и от любых наблюдателей из вне. Чтобы скрыть свой IP-адрес от серверов, вы можете <strong>подключиться к серверам SimpleX через сеть Tor</strong>.",
"developers": "Разработчики",
"simplex-private-7-title": "Проверка целостности<br>сообщения",
"privacy-matters-overlay-card-1-p-4": "Платформа SimpleX защищает конфиденциальность ваших контактов лучше, чем любая другая альтернатива, полностью предотвращая доступ к вашему социальному графику каким-либо компаниям или организациям. Даже когда люди используют серверы, предоставляемые SimpleX Chat, мы не знаем точное количество пользователей или с кем они общаются.",
"hero-overlay-card-1-p-6": "Подробнее читайте в <a href='https://github.com/simplex-chat/simplexmq/blob/stable/protocol/overview-tjr.md' target='_blank'>техническом документе SimpleX</a>.",
"simplex-network-overlay-card-1-p-1": "Протоколы и приложения для обмена сообщениями <a href='https://ru.wikipedia.org/wiki/Peer-to-peer'>P2P</a> имеют различные проблемы, которые делают их менее надежными, чем SimpleX, более сложными для анализа и уязвимыми для нескольких типов атак.",
"terms-and-privacy-policy": "Условия & Политика Конфиденциальности",
"simplex-network-overlay-card-1-li-1": "Сети P2P полагаются на тот или иной вариант <a href='https://ru.wikipedia.org/wiki/Distributed_hash_table'>DHT</a> для маршрутизации сообщений. Проекты DHT должны обеспечивать баланс между гарантией доставки и задержкой. SimpleX имеет как лучшую гарантию доставки, так и меньшую задержку, чем P2P. В сетях P2P сообщение передается через нескольких узлов, последовательно, кол-во узлов-посредников будет расти параллельно размеру сети - <em>O(log N)</em>.",
"privacy-matters-section-label": "Убедитесь, что ваш мессенджер не может получить доступ к вашим данным!",
"simplex-unique-overlay-card-3-p-1": "SimpleX Chat хранит все пользовательские данные на клиентских устройствах в <strong>портативном формате зашифрованной базы данных</strong> которую можно перенести на другое устройство.",
"simplex-network-3-desc": "серверы предоставляют <span class='text-active-blue'>однонаправленные очереди</span> для подключения пользователей, но у них нет видимости графика сетевых подключений &mdash; это делают только пользователи.",
"simplex-unique-card-1-p-1": "SimpleX защищает конфиденциальность вашего профиля, контактов и метаданных, скрывая их от серверов платформы SimpleX и любых наблюдателей.",
"simplex-private-card-3-point-1": "Для соединений клиент-сервер используется только протокол TLS 1.2/1.3 с надежными алгоритмами.",
"simplex-unique-card-4-p-1": "Сеть SimpleX полностью децентрализована и независима от любой криптовалюты/блокчейна или любой другой платформы, кроме Интернета.",
"features": "Возможности",
"hero-overlay-card-1-p-3": "Вы определяете, какие серверы будете использовать для получения сообщений, а ваши контакты &mdash; серверы, которые вы используете для отправки им сообщений. Каждый новый чат, скорее всего, будет вестись на двух разных серверах.",
"docs-dropdown-9": "Скачать",
"simplex-chat-protocol": "Протокол SimpleX Chat",
"simplex-unique-overlay-card-1-p-1": "В отличие от других платформ обмена сообщениями, SimpleX <strong>не имеет идентификаторов, присвоенных пользователям</strong>. Он не полагается на номера телефонов, доменные адреса (например, электронную почту или XMPP), имена пользователей, открытые ключи или даже случайные числа для идентификации своих пользователей &mdash; мы не знаем, сколько людей пользуются нашими SimpleX серверами.",
"reference": "Ссылки",
"f-droid-page-f-droid-org-repo-section-text": "Приложение SimpleX Chat от разработчиков и от репозитория F-Droid.org имеют разные ключи подписи. Если вы хотите сменить одно на другое, вам сначала нужно будет <a href='/docs/guide/chat-profiles.html#move-your-chat-profiles-to-another-device'>экспортировать</a> базу данных и только потом скачать другое приложение.",
"simplex-private-5-title": "Многоуровневое<br>Заполнения содержимого"
}

View File

@ -65,13 +65,13 @@
"hero-overlay-2-textlink": "SimpleX 是如何工作的?",
"hero-2-header-desc": "右侧的视频向您展示了如何通过一次性二维码、面对面交流或通过视频交换链接来连接到您的朋友。您同样可以通过共享邀请链接来进行连接。",
"hero-overlay-1-title": "SimpleX 是如何工作的?",
"feature-2-title": "端到端加密的图像和文件",
"feature-2-title": "端到端加密的<br>图片、视频和文件",
"feature-1-title": "端到端加密的文字消息支持markdown和编辑",
"feature-4-title": "端到端加密的语音消息",
"feature-3-title": "去中心化的秘密群组——只有用户知道它们的存在",
"feature-3-title": "端到端加密的去中心化的秘密群组 &mdash;只有用户知道它们的存在",
"feature-5-title": "支持消息自动销毁",
"simplex-network-overlay-1-title": "与 P2P 通讯协议的比较",
"feature-7-title": "随身的加密数据库——可将您的个人资料移至另一台设备",
"feature-7-title": "便携的加密应用存储&mdash; 可将您的个人资料移至另一台设备",
"simplex-private-10-title": "临时匿名成对标识符",
"simplex-private-8-title": "通过消息混合减少相关性",
"simplex-private-card-1-point-2": "每个队列中的网络与密码学库加密盒(NaCL cryptobox)可防止 TLS 受到威胁时消息队列之间的流量关联。",