diff --git a/CHANGES.rst b/CHANGES.rst index e5fc8597d..d39122e9d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,4 @@ -Changes in 0.9.3 (2019-08-) +Changes in 0.10.0 (2019-10-) =============================================== Improvements: @@ -6,6 +6,9 @@ Improvements: * Widgets: Whitelist [MSC1961](https://github.com/matrix-org/matrix-doc/pull/1961) widget urls. * Settings: CALLS section: Always display the CallKit option but grey it out when not available (only on China). * VoIP: Fallback to matrix.org STUN server with a confirmation dialog (#2646). + * Widgets: Whitelist [MSC1961](https://github.com/matrix-org/matrix-doc/pull/1961) widget urls + * i18n: Enable Polish (pl). + * Room members: third-party invites can now be revoked * Privacy: Prompt to accept integration manager policies on use (#2600). * Privacy: Make clear that device names are publicly readable (#2662). * Privacy: Remove the ability to set an IS at login/registration (#2661). @@ -26,6 +29,28 @@ Improvements: Bug fix: * Theme: Make button theming work (#2734). +Changes in 0.9.5 (2019-09-20) +=============================================== + +Bug fix: + * VoiceOver: RoomVC: Fix some missing accessibility labels for buttons (#2722). + * VoiceOver: RoomVC: Make VoiceOver focus on the contextual menu when selecting an event (#2721). + * VoiceOver: RoomVC: Do not lose the focus on the timeline when paginating (with 3 fingers) (#2720). + * VoiceOver: RoomVC: No VoiceOver on media (#2726). + +Changes in 0.9.4 (2019-09-13) +=============================================== + +Improvements: + * Authentication: Improve the webview used for SSO (#2715). + +Changes in 0.9.3 (2019-09-10) +=============================================== + +Improvements: + * Support Riot configuration link to customise HS and IS (#2703). + * Authentication: Create a way to filter and prioritise flows (with handleSupportedFlowsInAuthenticationSession). + Changes in 0.9.2 (2019-08-08) =============================================== diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index d92e5da02..453ca730d 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ 3232ABBC2257BE6500AD6A5C /* DeviceVerificationVerifyViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABB42257BE6400AD6A5C /* DeviceVerificationVerifyViewAction.swift */; }; 3232ABC022594C0900AD6A5C /* VerifyEmojiCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABBF22594C0900AD6A5C /* VerifyEmojiCollectionViewCell.swift */; }; 3232ABC2225B996200AD6A5C /* Themable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3232ABC1225B996100AD6A5C /* Themable.swift */; }; + 323AB947232BD74600C1451F /* AuthFallBackViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 323AB946232BD74600C1451F /* AuthFallBackViewController.m */; }; 324A204F225FC571004FE8B0 /* DeviceVerificationIncomingViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 324A2047225FC571004FE8B0 /* DeviceVerificationIncomingViewController.storyboard */; }; 324A2050225FC571004FE8B0 /* DeviceVerificationIncomingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 324A2048225FC571004FE8B0 /* DeviceVerificationIncomingViewController.swift */; }; 324A2051225FC571004FE8B0 /* DeviceVerificationIncomingViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 324A2049225FC571004FE8B0 /* DeviceVerificationIncomingViewState.swift */; }; @@ -685,6 +686,8 @@ 3232ABB42257BE6400AD6A5C /* DeviceVerificationVerifyViewAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationVerifyViewAction.swift; sourceTree = ""; }; 3232ABBF22594C0900AD6A5C /* VerifyEmojiCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifyEmojiCollectionViewCell.swift; sourceTree = ""; }; 3232ABC1225B996100AD6A5C /* Themable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Themable.swift; sourceTree = ""; }; + 323AB945232BD74600C1451F /* AuthFallBackViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthFallBackViewController.h; sourceTree = ""; }; + 323AB946232BD74600C1451F /* AuthFallBackViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthFallBackViewController.m; sourceTree = ""; }; 324A2047225FC571004FE8B0 /* DeviceVerificationIncomingViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = DeviceVerificationIncomingViewController.storyboard; sourceTree = ""; }; 324A2048225FC571004FE8B0 /* DeviceVerificationIncomingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationIncomingViewController.swift; sourceTree = ""; }; 324A2049225FC571004FE8B0 /* DeviceVerificationIncomingViewState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceVerificationIncomingViewState.swift; sourceTree = ""; }; @@ -735,6 +738,9 @@ 32D7159E2146CC6F00DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Vector.strings; sourceTree = ""; }; 32D7159F2146CC7F00DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; 32D715A02146CC8800DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; + 32DAF8DB231813C800654A44 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = ""; }; + 32DAF8DC231813D500654A44 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + 32DAF8DD231813E100654A44 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Vector.strings; sourceTree = ""; }; 32DB556922FDADE50016329E /* ServiceTermsModalCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalCoordinatorType.swift; sourceTree = ""; }; 32DB556A22FDADE50016329E /* ServiceTermsModalCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalCoordinatorBridgePresenter.swift; sourceTree = ""; }; 32DB556B22FDADE50016329E /* ServiceTermsModalCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceTermsModalCoordinator.swift; sourceTree = ""; }; @@ -1652,6 +1658,15 @@ path = Views; sourceTree = ""; }; + 323AB944232BD71900C1451F /* Fallback */ = { + isa = PBXGroup; + children = ( + 323AB945232BD74600C1451F /* AuthFallBackViewController.h */, + 323AB946232BD74600C1451F /* AuthFallBackViewController.m */, + ); + path = Fallback; + sourceTree = ""; + }; 324A2046225FC571004FE8B0 /* Incoming */ = { isa = PBXGroup; children = ( @@ -2388,6 +2403,7 @@ B1B5568420EE6C4C00210D55 /* Home */ = { isa = PBXGroup; children = ( + 323AB944232BD71900C1451F /* Fallback */, B1B5568620EE6C4C00210D55 /* HomeViewController.h */, B1B5568520EE6C4C00210D55 /* HomeViewController.m */, B1B5593D20EF7BD000210D55 /* Views */, @@ -3896,6 +3912,7 @@ es, ja, hu, + pl, ); mainGroup = F094A9991B78D8F000B1FBBF; productRefGroup = F094A9A31B78D8F000B1FBBF /* Products */; @@ -4607,6 +4624,7 @@ B157FAA223264AE900EBFBD4 /* SettingsDiscoveryThreePidDetailsViewAction.swift in Sources */, 3232ABA1225730E100AD6A5C /* DeviceVerificationCoordinatorType.swift in Sources */, B1C562D9228C0B760037F12A /* RoomContextualMenuItem.swift in Sources */, + 323AB947232BD74600C1451F /* AuthFallBackViewController.m in Sources */, B1C562E1228C7C8C0037F12A /* RoomContextualMenuToolbarView.swift in Sources */, B1B557BF20EF5B4500210D55 /* DisabledRoomInputToolbarView.m in Sources */, B1B5578620EF564900210D55 /* GroupTableViewCellWithSwitch.m in Sources */, @@ -4737,6 +4755,7 @@ 32D7159E2146CC6F00DF59C9 /* es */, 3D78489221AC9E6500B98A7D /* ja */, 3D78489521ACA25300B98A7D /* hu */, + 32DAF8DD231813E100654A44 /* pl */, ); name = Vector.strings; sourceTree = ""; @@ -4759,6 +4778,7 @@ 32D715A02146CC8800DF59C9 /* es */, 3D78489021AC9E6400B98A7D /* ja */, 3D78489321ACA25200B98A7D /* hu */, + 32DAF8DB231813C800654A44 /* pl */, ); name = InfoPlist.strings; sourceTree = ""; @@ -4781,6 +4801,7 @@ 32D7159F2146CC7F00DF59C9 /* es */, 3D78489121AC9E6500B98A7D /* ja */, 3D78489421ACA25300B98A7D /* hu */, + 32DAF8DC231813D500654A44 /* pl */, ); name = Localizable.strings; sourceTree = ""; diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index d20dd38fa..a3a8b4184 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -2109,6 +2109,11 @@ NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDe // iOS Patch: fix vector.im urls before using it webURL = [Tools fixURLWithSeveralHashKeys:webURL]; + + if ([webURL.path hasPrefix:@"/config"]) + { + return [self handleServerProvionningLink:webURL]; + } NSString *validateEmailSubmitTokenPath = @"validate/email/submitToken"; @@ -2585,6 +2590,93 @@ NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDe *outQueryParams = queryParams; } + +- (BOOL)handleServerProvionningLink:(NSURL*)link +{ + NSLog(@"[AppDelegate] handleServerProvionningLink: %@", link); + + NSString *homeserver, *identityServer; + [self parseServerProvionningLink:link homeserver:&homeserver identityServer:&identityServer]; + + if (homeserver) + { + if ([MXKAccountManager sharedManager].activeAccounts.count) + { + [self displayServerProvionningLinkBuyAlreadyLoggedInAlertWithCompletion:^(BOOL logout) { + + NSLog(@"[AppDelegate] handleServerProvionningLink: logoutWithConfirmation: logout: %@", @(logout)); + if (logout) + { + [self logoutWithConfirmation:NO completion:^(BOOL isLoggedOut) { + [self handleServerProvionningLink:link]; + }]; + } + }]; + } + else + { + [_masterTabBarController showAuthenticationScreen]; + [_masterTabBarController.authViewController showCustomHomeserver:homeserver andIdentityServer:identityServer]; + } + + return YES; + } + + return NO; +} + +- (void)parseServerProvionningLink:(NSURL*)link homeserver:(NSString**)homeserver identityServer:(NSString**)identityServer +{ + if ([link.path isEqualToString:@"/config/config"]) + { + NSURLComponents *linkURLComponents = [NSURLComponents componentsWithURL:link resolvingAgainstBaseURL:NO]; + for (NSURLQueryItem *item in linkURLComponents.queryItems) + { + if ([item.name isEqualToString:@"hs_url"]) + { + *homeserver = item.value; + } + else if ([item.name isEqualToString:@"is_url"]) + { + *identityServer = item.value; + break; + } + } + } + else + { + NSLog(@"[AppDelegate] parseServerProvionningLink: Error: Unknown path: %@", link.path); + } + + + NSLog(@"[AppDelegate] parseServerProvionningLink: homeserver: %@ - identityServer: %@", *homeserver, *identityServer); +} + +- (void)displayServerProvionningLinkBuyAlreadyLoggedInAlertWithCompletion:(void (^)(BOOL logout))completion +{ + // Ask confirmation + self.logoutConfirmation = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"error_user_already_logged_in", @"Vector", nil) message:nil preferredStyle:UIAlertControllerStyleAlert]; + + [self.logoutConfirmation addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_sign_out", @"Vector", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + self.logoutConfirmation = nil; + completion(YES); + }]]; + + [self.logoutConfirmation addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * action) + { + self.logoutConfirmation = nil; + completion(NO); + }]]; + + [self.logoutConfirmation mxk_setAccessibilityIdentifier: @"AppDelegateLogoutConfirmationAlert"]; + [self showNotificationAlert:self.logoutConfirmation]; +} + #pragma mark - Matrix sessions handling - (void)initMatrixSessions diff --git a/Riot/Assets/bg.lproj/Vector.strings b/Riot/Assets/bg.lproj/Vector.strings index 734db3585..5744475ee 100644 --- a/Riot/Assets/bg.lproj/Vector.strings +++ b/Riot/Assets/bg.lproj/Vector.strings @@ -820,3 +820,12 @@ "image_picker_action_library" = "Избери от библиотеката"; "camera_unavailable" = "Не е достъпна камера на вашето устройство"; "photo_library_access_not_granted" = "%@ няма достъп до библиотеката със снимки. Моля, променете настройките на поверителността"; +"auth_forgot_password_error_no_configured_identity_server" = "Не е конфигуриран сървър за самоличност: добавете такъв за да може да възстановите паролата си."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Не е конфигуриран сървър за самоличност, така че не можете да поканите участник по имейл адрес."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Не е конфигуриран сървър за самоличност, така че не можете да започнете чат с контакт посредством имейл адрес."; +// Service terms +"service_terms_modal_title" = "Условия за ползване"; +"service_terms_modal_message" = "За да продължите е необходимо да приемете Условията за ползване."; +"service_terms_modal_accept_button" = "Приемам"; +"service_terms_modal_description_for_identity_server" = "Бъдете откриваеми от потребители"; +"service_terms_modal_description_for_integration_manager" = "Използвайте ботове, връзки към други мрежи и стикери"; diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 504066561..4b8092ce1 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -309,7 +309,7 @@ "room_event_action_redact" = "Entfernen"; "room_warning_about_encryption" = "Ende-zu-Ende Verschlüsselung ist in Beta und ist evtl. nicht zuverlässig.\n\nMan sollte noch nicht darauf vertrauen, dass die Daten sicher sind.\n\nGeräte werden den Verlauf vor dem Beitritt des Raumes nicht entschlüsseln können.\n\nVerschlüsselte Nachrichten sind nicht lesbar auf Clients, die Verschlüsselung noch nicht implementiert haben."; "unknown_devices_alert" = "Dieser Raum enthält unbekannte Geräte, die nicht verifiziert wurden.\nDas bedeutet, es gibt keine Garantie, dass sie dem User gehören, der angegeben ist.\nWir empfehlen eine Überprüfung für jedes Gerät, bevor du weitermachst, aber du kannst die Nachricht erneut senden ohne Verifikation."; -"room_preview_unlinked_email_warning" = "Diese Einladung wurde an %@ gesendet, die Adresse ist nicht mit diesem Konto verbunden. Du kannst dich mit einem anderen Konto anmelden, oder diese E-Mail-Adresse deinem Konto hinzufügen."; +"room_preview_unlinked_email_warning" = "Diese Einladung wurde an %@ gesendet, das diesem Konto nicht zugeordnet ist. Möglicherweise möchten Sie sich mit einem anderen Konto anmelden oder diese E-Mail zu Ihrem Konto hinzufügen."; "room_preview_try_join_an_unknown_room" = "Du versuchst auf %@ zuzugreifen. Möchtest du dem Raum beitreten um teilzunehmen?"; "settings_config_identity_server" = "Identitätsserver ist %@"; "settings_labs" = "Labor"; @@ -511,8 +511,8 @@ "room_do_not_have_permission_to_post" = "Du hast keine Berechtigung in diesem Raum zu posten"; "room_event_action_kick_prompt_reason" = "Grund für den Rauswurf des Benutzers"; "room_event_action_ban_prompt_reason" = "Grund für die Verbannung des Benutzers"; -"room_action_send_photo_or_video" = "Sende Foto oder Video"; -"room_action_send_sticker" = "Sende Sticker"; +"room_action_send_photo_or_video" = "Foto oder Video senden"; +"room_action_send_sticker" = "Sticker senden"; "settings_deactivate_account" = "DEAKTIVIERE ACCOUNT"; "settings_deactivate_my_account" = "Deaktivere meinen Account"; "widget_sticker_picker_no_stickerpacks_alert" = "Du hast aktuell keine Sticker-Packete aktiviert."; @@ -544,7 +544,7 @@ "room_replacement_link" = "Die Konversation wird hier fortgesetzt."; "room_predecessor_information" = "Dieser Raum ist die Fortsetzung einer anderen Konversation."; "room_predecessor_link" = "Tippe hier um ältere Nachrichten zu sehen."; -"settings_labs_room_members_lazy_loading" = "Raummitglieder nachladen"; +"settings_labs_room_members_lazy_loading" = "Raummitglieder später laden"; "settings_labs_room_members_lazy_loading_error_message" = "Dein Heimserver unterstützt das verzögerte Laden von Raummitgliedern noch nicht. Versuche es später erneut."; "room_event_action_view_decrypted_source" = "Zeige entschlüsselten Quellcode"; "room_recents_server_notice_section" = "SYSTEMBENACHRICHTIGUNGEN"; @@ -561,11 +561,11 @@ "settings_key_backup_info" = "Verschlüsselte Nachrichten sind durch Ende-zu-Ende-Verschlüsselung gesichert. Ausschließlich du und der/die Empfänger besitzen die Schlüssel, um diese Nachrichten zu lesen."; "settings_key_backup_info_checking" = "Überprüfe..."; "settings_key_backup_info_none" = "Deine Schlüssel werden von diesem Gerät nicht gesichert."; -"settings_key_backup_info_signout_warning" = "Sichere deine Schlüssel bevor du dich abmeldest, damit du sie nicht verlierst."; +"settings_key_backup_info_signout_warning" = "Schließen Sie dieses Gerät an die Schlüsselsicherung an, bevor Sie sich abmelden, um den Verlust von Schlüsseln zu vermeiden, die sich möglicherweise nur auf diesem Gerät befinden."; "settings_key_backup_info_version" = "Schlüssel Sicherheitskopie Version: %@"; "settings_key_backup_info_algorithm" = "Algorithmus"; "settings_key_backup_info_valid" = "Dieses Gerät sichert deine Schlüssel."; -"settings_key_backup_info_not_valid" = "Dieses Gerät sichert deine Schlüssel nicht."; +"settings_key_backup_info_not_valid" = "Dieses Gerät sichert Ihre Schlüssel nicht, es ist jedoch eine Sicherungskopie vorhanden, die Sie wiederherstellen und später hinzufügen können."; "settings_key_backup_info_progress" = "Sichere %@ Schlüssel..."; "settings_key_backup_info_progress_done" = "Alle Schlüssel wurden gesichert"; "settings_key_backup_info_trust_signature_unknown" = "Sicherheitskopie hat eine Signatur vom Gerät mit der ID: %@"; @@ -674,7 +674,7 @@ "key_backup_recover_connent_banner_subtitle" = "Schlüssel dieses Geräts sichern"; // MARK: - Device Verification "device_verification_title" = "Gerät verifizieren"; -"device_verification_cancelled" = "Die Gegenseite hat die Verifikation abgebrochen"; +"device_verification_cancelled" = "Die Gegenstelle hat die Überprüfung abgebrochen."; "device_verification_cancelled_by_me" = "Die Verifikation wurde abgebrochen. Grund: %@"; "device_verification_error_cannot_load_device" = "Konnte Geräteinformationen nicht laden."; // Mark: Incoming @@ -736,7 +736,7 @@ "device_verification_emoji_bell" = "Glocke"; "device_verification_emoji_anchor" = "Anker"; "device_verification_emoji_headphones" = "Kopfhörer"; -"close" = "Schließen"; +"close" = "Beenden"; "auth_softlogout_signed_out" = "Sie sind abgemeldet"; "auth_softlogout_sign_in" = "Einloggen"; "auth_softlogout_reason" = "Ihr Homeserver-Administrator (%1$@) hat Sie von Ihrem Konto %2$@ (%3$@) abgemeldet."; @@ -775,7 +775,7 @@ "device_verification_emoji_rooster" = "Hahn"; "device_verification_emoji_globe" = "Globus"; "device_verification_emoji_smiley" = "Lächeln"; -"device_verification_emoji_spanner" = "Spanner"; +"device_verification_emoji_spanner" = "Schraubenschlüssel"; "device_verification_emoji_thumbs up" = "Daumen hoch"; "device_verification_emoji_hourglass" = "Sanduhr"; "device_verification_emoji_clock" = "Uhr"; @@ -798,3 +798,20 @@ "emoji_picker_flags_category" = "Flaggen"; // MARK: Reaction history "reaction_history_title" = "Reaktionen"; +"room_action_camera" = "Foto oder Video aufnehmen"; +// Media picker +"media_picker_title" = "Mediathek"; +// Image picker +"image_picker_action_camera" = "Foto aufnehmen"; +"image_picker_action_library" = "Aus der Mediathek auswählen"; +"camera_unavailable" = "Die Kamera ist auf Ihrem Gerät nicht verfügbar"; +"photo_library_access_not_granted" = "%@ hat keine Berechtigung zum Zugriff auf die Fotobibliothek. Bitte ändern Sie die Datenschutzeinstellungen"; +"auth_forgot_password_error_no_configured_identity_server" = "Es ist kein Identitätsserver konfiguriert: Fügen Sie einen hinzu, um Ihr Kennwort zurückzusetzen."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Es ist kein Identitätsserver konfiguriert, sodass Sie keinen Teilnehmer mit einer E-Mail hinzufügen können."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Es ist kein Identitätsserver konfiguriert, sodass Sie keinen Chat mit einem Kontakt über eine E-Mail starten können."; +// Service terms +"service_terms_modal_title" = "Nutzungsbedingungen"; +"service_terms_modal_message" = "Um fortzufahren, müssen Sie die Bedingungen dieses Dienstes akzeptieren."; +"service_terms_modal_accept_button" = "Akzeptieren"; +"service_terms_modal_description_for_identity_server" = "Für andere auffindbar sein"; +"service_terms_modal_description_for_integration_manager" = "Verwenden Sie Bots, Bridges, Widgets und Sticker-Packs"; diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 26cb0dc4f..3628e8f62 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -130,6 +130,8 @@ "auth_softlogout_clear_data_sign_out_msg" = "Are you sure you want to clear all data currently stored on this device? Sign in again to access your account data and messages."; "auth_softlogout_clear_data_sign_out" = "Sign out"; +// Errors +"error_user_already_logged_in" = "It looks like you’re trying to connect to another homeserver. Do you want to sign out?"; // Chat creation "room_creation_title" = "New Chat"; @@ -215,7 +217,7 @@ "room_participants_leave_prompt_msg" = "Are you sure you want to leave the room?"; "room_participants_remove_prompt_title" = "Confirmation"; "room_participants_remove_prompt_msg" = "Are you sure you want to remove %@ from this chat?"; -"room_participants_remove_third_party_invite_msg" = "Remove third-party invite is not supported yet until the api exists"; +"room_participants_remove_third_party_invite_prompt_msg" = "Are you sure you want to revoke this invite?"; "room_participants_invite_prompt_title" = "Confirmation"; "room_participants_invite_prompt_msg" = "Are you sure you want to invite %@ to this chat?"; "room_participants_filter_room_members" = "Filter room members"; @@ -254,6 +256,7 @@ // Chat "room_jump_to_first_unread" = "Jump to first unread message"; +"room_accessiblity_scroll_to_bottom" = "Scroll to bottom"; "room_new_message_notification" = "%d new message"; "room_new_messages_notification" = "%d new messages"; "room_one_user_is_typing" = "%@ is typing…"; @@ -321,6 +324,18 @@ "room_resource_usage_limit_reached_message_2" = "some users will not be able to log in."; "room_resource_usage_limit_reached_message_contact_3" = " to get this limit increased."; "room_message_edits_history_title" = "Message edits"; +"room_accessibility_search" = "Search"; +"room_accessibility_integrations" = "Integrations"; +"room_accessibility_upload" = "Upload"; +"room_accessibility_call" = "Call"; +"room_accessibility_hangup" = "Hang up"; + +"media_type_accessibility_image" = "Image"; +"media_type_accessibility_audio" = "Audio"; +"media_type_accessibility_video" = "Video"; +"media_type_accessibility_location" = "Location"; +"media_type_accessibility_file" = "File"; +"media_type_accessibility_sticker" = "Sticker"; // Unknown devices "unknown_devices_alert_title" = "Room contains unknown devices"; @@ -748,6 +763,9 @@ "widget_integration_missing_user_id" = "Missing user_id in request."; "widget_integration_room_not_visible" = "Room %@ is not visible."; +// Widget Picker +"widget_picker_title" = "Integrations"; + // Share extension "share_extension_auth_prompt" = "Login in the main app to share content"; "share_extension_failed_to_encrypt" = "Failed to send. Check in the main app the encryption settings for this room"; diff --git a/Riot/Assets/eu.lproj/InfoPlist.strings b/Riot/Assets/eu.lproj/InfoPlist.strings index 028fbdef0..ca1a6aa7a 100644 --- a/Riot/Assets/eu.lproj/InfoPlist.strings +++ b/Riot/Assets/eu.lproj/InfoPlist.strings @@ -2,5 +2,5 @@ "NSCameraUsageDescription" = "Kamera argazkiak eta bideoak ateratzeko eta bideo deiak egiteko erabiltzen da."; "NSPhotoLibraryUsageDescription" = "Argazkien liburutegia argazkiak eta bideoak bidaltzeko erabiltzen da."; "NSMicrophoneUsageDescription" = "Mikrofonoa bideoak atera eta deiak egiteko erabiltzen da."; -"NSContactsUsageDescription" = "Zure kontaktuetatik Riot edo Matrix jada darabiltenak erakusteko, zure kontaktu liburuko e-mail helbideak eta telefono zenbakiak bidali ditzakegu identitate zerbitzarira. New Vector enpresak ez ditu datu hauek gordetzen edo beste ezertarako erabiltzen. Informazio gehiagorako ikusi pribatutasun politikari buruzko orria aplikazioaren ezarpenetan."; +"NSContactsUsageDescription" = "Zure kontaktuetatik Riot edo Matrix jada darabiltenak erakusteko, zure kontaktu liburuko e-mail helbideak eta telefono zenbakiak bidali ditzakegu identitate-zerbitzarira. New Vector enpresak ez ditu datu hauek gordetzen edo beste ezertarako erabiltzen. Informazio gehiagorako ikusi pribatutasun politikari buruzko orria aplikazioaren ezarpenetan."; "NSCalendarsUsageDescription" = "Ikusi zure programatutako batzarrak aplikazioan."; diff --git a/Riot/Assets/eu.lproj/Vector.strings b/Riot/Assets/eu.lproj/Vector.strings index a9c7e91a6..98b415fe1 100644 --- a/Riot/Assets/eu.lproj/Vector.strings +++ b/Riot/Assets/eu.lproj/Vector.strings @@ -798,3 +798,23 @@ "emoji_picker_objects_category" = "Objektuak"; "emoji_picker_symbols_category" = "Sinboloak"; "emoji_picker_flags_category" = "Banderak"; +"auth_forgot_password_error_no_configured_identity_server" = "Ez da identitate zerbitzaririk konfiguratu: gehitu bat zure pasahitza berrezartzeko."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Ez da identitate zerbitzaririk konfiguratu, beraz ezin duzu parte-hartzaile bat e-mail bidez gehitu."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Ez da identitate zerbitzaririk konfiguratu, beraz ezin duzu kontaktu batekin txat bat hasi e-mail bat erabiliz."; +"room_event_action_reaction_history" = "Erreakzioen historiala"; +"room_action_camera" = "Atera argazkia edo bideoa"; +// Media picker +"media_picker_title" = "Multimedia liburutegia"; +// Image picker +"image_picker_action_camera" = "Atera argazkia"; +"image_picker_action_library" = "Hautatu liburutegitik"; +"camera_unavailable" = "Kamera ez dago erabilgarri zure gailuan"; +"photo_library_access_not_granted" = "%@(e)k ez du argazki liburutegia erabiltzeko baimenik, aldatu pribatutasun ezarpenak"; +// Service terms +"service_terms_modal_title" = "Erabilera baldintzak"; +"service_terms_modal_message" = "Jarraitzeko, zerbitzu honen erabilera baldintzak onartu behar dituzu."; +"service_terms_modal_accept_button" = "Onartu"; +"service_terms_modal_description_for_identity_server" = "Izan besteentzat aurkigarria"; +"service_terms_modal_description_for_integration_manager" = "Erabili botak, zubiak, trepetak eta eranskailu multzoak"; +// MARK: Reaction history +"reaction_history_title" = "Erreakzioak"; diff --git a/Riot/Assets/fr.lproj/InfoPlist.strings b/Riot/Assets/fr.lproj/InfoPlist.strings index aa5c6d53c..895cb223b 100644 --- a/Riot/Assets/fr.lproj/InfoPlist.strings +++ b/Riot/Assets/fr.lproj/InfoPlist.strings @@ -2,5 +2,5 @@ "NSCameraUsageDescription" = "L'appareil photo est utilisé pour prendre des photos et des vidéos et pour passer des appels vidéo."; "NSPhotoLibraryUsageDescription" = "La photothèque est utilisée pour envoyer des photos et des vidéos."; "NSMicrophoneUsageDescription" = "Le microphone est utilisé pour prendre des vidéos et passer des appels."; -"NSContactsUsageDescription" = "Afin d’afficher qui parmis vos contacts utilise déjà Riot ou Matrix, nous pouvons envoyer les adresses e-mails et les numéros de téléphone de votre carnet d'adresse à votre Serveur d'Identité Matrix. New Vector ne stocke pas ces données et ne les utilise pas à d'autres fins. Pour plus d'informations, veuillez consulter la page de politique de confidentialité dans les paramètres de l'application."; +"NSContactsUsageDescription" = "Afin d’afficher qui parmi vos contacts utilise déjà Riot ou Matrix, nous pouvons envoyer les adresses e-mails et les numéros de téléphone de votre carnet d’adresse à votre serveur d’identité Matrix. New Vector ne stocke pas ces données et ne les utilise pas à d’autres fins. Pour plus d’informations, consultez la page de politique de confidentialité dans les paramètres de l’application."; "NSCalendarsUsageDescription" = "Voir vos rendez-vous prévus dans l’application."; diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index 9d23275a8..2afac462c 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -821,3 +821,12 @@ "image_picker_action_library" = "Choisir dans la médiathèque"; "camera_unavailable" = "L’appareil photo n’est pas disponible sur votre appareil"; "photo_library_access_not_granted" = "%@ n’a pas la permission pour accéder à la médiathèque, veuillez modifier les options de vie privée"; +"auth_forgot_password_error_no_configured_identity_server" = "Aucun serveur d’identité n’est configuré : ajoutez-en un pour réinitialiser votre mot de passe."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de participant avec un e-mail."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas commencer de discussion avec un contact en utilisant un e-mail."; +// Service terms +"service_terms_modal_title" = "Conditions de service"; +"service_terms_modal_message" = "Pour continuer vous devez accepter les conditions de ce service."; +"service_terms_modal_accept_button" = "Accepter"; +"service_terms_modal_description_for_identity_server" = "Se rendre découvrable pour les autres"; +"service_terms_modal_description_for_integration_manager" = "Utiliser des robots, des passerelles, des widgets et des packs de stickers"; diff --git a/Riot/Assets/hu.lproj/InfoPlist.strings b/Riot/Assets/hu.lproj/InfoPlist.strings index fcca04acb..c7e0fe6d0 100644 --- a/Riot/Assets/hu.lproj/InfoPlist.strings +++ b/Riot/Assets/hu.lproj/InfoPlist.strings @@ -2,5 +2,5 @@ "NSCameraUsageDescription" = "A kamera fényképek, videók készítéséhez és videóhívásokhoz lesz használva."; "NSPhotoLibraryUsageDescription" = "A fénykép galéria fényképek és videók küldéséhez lesz használva."; "NSMicrophoneUsageDescription" = "A mikrofon videók készítéséhez és hívásokhoz lesz használva."; -"NSContactsUsageDescription" = "Ahhoz, hogy meg tudjuk mutatni melyik ismerősöd használja már a Riot-ot vagy Matrix-ot, el tudjuk küldeni az e-mail címeket és telefonszámokat a címjegyzékedből a Matrix Azonosítási Szerverének. „New Vector” nem tárolja és semmilyen más célra nem használja ezeket az információkat. További információkért olvasd el az adatkezelési oldalt az alkalmazás beállításaiban."; +"NSContactsUsageDescription" = "Ahhoz, hogy meg tudjuk mutatni melyik ismerősöd használja már a Riot-ot vagy Matrix-ot, el tudjuk küldeni az e-mail címeket és telefonszámokat a címjegyzékedből a Matrix azonosítási szerverének. „New Vector” nem tárolja és semmilyen más célra nem használja ezeket az információkat. További információkért olvasd el az adatkezelési oldalt az alkalmazás beállításaiban."; "NSCalendarsUsageDescription" = "Nézd meg a találkozóidat az alkalmazásban."; diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index 23df1cd1a..6979c54ee 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -818,3 +818,20 @@ "room_event_action_reaction_history" = "Reakciók története"; // MARK: Reaction history "reaction_history_title" = "Reakciók"; +"auth_forgot_password_error_no_configured_identity_server" = "Azonosítási szerver nincs beállítva: a jelszó visszaállításhoz adj hozzá egyet."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Azonosítási szerver nincs beállítva, így e-mail cím alapján nem tudsz hozzáadni résztvevőt."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Azonosítási szerver nincs beállítva, így e-mail cím alapján nem tudsz beszélgetést kezdeményezni."; +"room_action_camera" = "Fotó vagy videó készítése"; +// Media picker +"media_picker_title" = "Média könyvtár"; +// Image picker +"image_picker_action_camera" = "Fotó készítése"; +"image_picker_action_library" = "Válassz a könyvtárból"; +"camera_unavailable" = "A kamera nem érhető el az eszközödön"; +"photo_library_access_not_granted" = "A fénykép könyvár eléréséhez %@ nem rendelkezik engedéllyel, kérlek változtasd meg az adatvédelmi beállításokat"; +// Service terms +"service_terms_modal_title" = "Felhasználási feltételek"; +"service_terms_modal_message" = "A folytatáshoz el kell fogadnod a felhasználási feltételeket."; +"service_terms_modal_accept_button" = "Elfogad"; +"service_terms_modal_description_for_identity_server" = "Látható mások számára"; +"service_terms_modal_description_for_integration_manager" = "Használjon botokat, hidakat, kisalkalmazásokat és matrica csomagokat"; diff --git a/Riot/Assets/it.lproj/InfoPlist.strings b/Riot/Assets/it.lproj/InfoPlist.strings index 046971b31..9ab9fd61f 100644 --- a/Riot/Assets/it.lproj/InfoPlist.strings +++ b/Riot/Assets/it.lproj/InfoPlist.strings @@ -2,4 +2,5 @@ "NSCameraUsageDescription" = "La fotocamera viene utilizzata per scattare fotografie, registrare video ed eseguire videochiamate."; "NSPhotoLibraryUsageDescription" = "La libreria fotografica viene utilizzata per inviare foto e video."; "NSMicrophoneUsageDescription" = "Il microfono viene utilizzato per registrare video ed effettuare chiamate."; -"NSContactsUsageDescription" = "Per mostrare i tuoi contatti che stanno già usando Riot o Matrix, possiamo inviare gli indirizzi email e i numeri di telefono della tua rubrica al tuo server identità. New Vector non memorizza e non usa per altri scopi questi dati. Per maggiori informazioni guarda l'informativa sulla privacy presente nelle impostazioni di questa applicazione."; +"NSContactsUsageDescription" = "Per mostrare i tuoi contatti che stanno già usando Riot o Matrix, possiamo inviare gli indirizzi email e i numeri di telefono della tua rubrica al tuo server identità. Il nuovo Vector non memorizza e non usa per altri scopi questi dati. Per maggiori informazioni vedi l'informativa sulla privacy presente nelle impostazioni di questa applicazione."; +"NSCalendarsUsageDescription" = "Vedi le tue riunioni programmate nell'app."; diff --git a/Riot/Assets/it.lproj/Vector.strings b/Riot/Assets/it.lproj/Vector.strings index c5c5d48e9..46dc69b94 100644 --- a/Riot/Assets/it.lproj/Vector.strings +++ b/Riot/Assets/it.lproj/Vector.strings @@ -372,11 +372,11 @@ "settings_key_backup_info" = "I messaggi criptati sono protetti con la cifratura end-to-end. Solo tu e il/i destinatario/i avete le chiavi per leggere questi messaggi."; "settings_key_backup_info_checking" = "Verifica..."; "settings_key_backup_info_none" = "Nessun backup programmato per le chiavi da questo dispositivo."; -"settings_key_backup_info_signout_warning" = "Fai un backup sicuro delle tue chiavi prima di uscire per evitare di perderle."; +"settings_key_backup_info_signout_warning" = "Connetti questo dispositivo al backup chiavi prima di disconnetterti per evitare di perdere eventuali chiavi presenti solo qui."; "settings_key_backup_info_version" = "Versione backup chiave: %@"; "settings_key_backup_info_algorithm" = "Algoritmo: %@"; "settings_key_backup_info_valid" = "Questo dispositivo sta eseguendo il backup delle tue chiavi."; -"settings_key_backup_info_not_valid" = "Questo dispositivo non sta eseguendo il backup delle tue chiavi."; +"settings_key_backup_info_not_valid" = "Questo dispositivo non sta eseguendo il backup delle tue chiavi, ma hai un backup esistente da cui puoi ripristinare ed usare da ora in avanti."; "settings_key_backup_info_progress" = "Backup di %@ chiavi…"; "settings_key_backup_info_progress_done" = "Backup di tutte le chiavi completato"; "settings_key_backup_info_trust_signature_unknown" = "Il backup ha una firma dal dispositivo con ID: %@"; @@ -655,3 +655,28 @@ "sign_out_key_backup_in_progress_alert_title" = "Backup chiave in corso. Se ti disconnetti ora, perderai l'accesso ai tuoi messaggi cifrati."; "sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Non voglio i miei messaggi cifrati"; "sign_out_key_backup_in_progress_alert_cancel_action" = "Aspetto"; +"close" = "Chiudi"; +"auth_forgot_password_error_no_configured_identity_server" = "Nessun identità server è configurata: aggiungine uno per reimpostare la password."; +"auth_softlogout_signed_out" = "Sei uscito"; +"auth_softlogout_sign_in" = "Accedi"; +"auth_softlogout_reason" = "L'amministratore homeserver (%1$@) ti ha disconnesso dal tuo account %2$@ (%3$@)."; +"auth_softlogout_recover_encryption_keys" = "Accedi per recuperare le chiavi di crittografia archiviate esclusivamente su questo dispositivo. Ti servono per leggere tutti i tuoi messaggi sicuri su qualsiasi dispositivo."; +"auth_softlogout_clear_data" = "Cancella dati personali"; +"auth_softlogout_clear_data_message_1" = "Avviso: i tuoi dati personali (comprese le chiavi di crittografia) sono ancora memorizzati su questo dispositivo."; +"auth_softlogout_clear_data_message_2" = "Cancellalo se hai finito di utilizzare questo dispositivo o desideri accedere a un altro account."; +"auth_softlogout_clear_data_button" = "Cancella tutti i dati"; +"auth_softlogout_clear_data_sign_out_title" = "Sei sicuro?"; +"auth_softlogout_clear_data_sign_out_msg" = "Sei sicuro di voler cancellare tutti i dati attualmente memorizzati su questo dispositivo? Accedi di nuovo per accedere ai dati e ai messaggi del tuo account."; +"auth_softlogout_clear_data_sign_out" = "disconnessione"; +"room_creation_error_invite_user_by_email_without_identity_server" = "Nessuna identità server è configurata, quindi non è possibile aggiungere un partecipante con un'e-mail."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Nessuna identità server è configurata, quindi non è possibile avviare una chat con un contatto tramite e-mail."; +"room_event_action_reply" = "Rispondi"; +"room_event_action_edit" = "Modifica"; +"room_event_action_reaction_show_all" = "Mostra tutto"; +"room_event_action_reaction_show_less" = "Mostra meno"; +"room_event_action_reaction_history" = "Cronologia reazioni"; +"room_action_camera" = "Scatta foto o video"; +"room_action_send_file" = "Invia File"; +"room_action_reply" = "Rispondi"; +"room_message_edits_history_title" = "Modifica messaggio"; +"settings_labs_message_reaction" = "Reagisci ai messaggi con emoji"; diff --git a/Riot/Assets/ko.lproj/InfoPlist.strings b/Riot/Assets/ko.lproj/InfoPlist.strings index 5ce0ebe82..3f14273bb 100644 --- a/Riot/Assets/ko.lproj/InfoPlist.strings +++ b/Riot/Assets/ko.lproj/InfoPlist.strings @@ -1,6 +1,6 @@ // Permissions usage explanations -"NSCameraUsageDescription" = "카메라는 사진과 영상 촬영, 영상통화를 하는데 쓰입니다."; +"NSCameraUsageDescription" = "카메라는 사진과 영상 촬영, 영상 통화를 하는 데 쓰입니다."; "NSPhotoLibraryUsageDescription" = "포토 라이브러리는 사진과 영상을 보내는데 쓰입니다."; "NSMicrophoneUsageDescription" = "마이크는 영상 촬영, 통화에 쓰입니다."; -"NSContactsUsageDescription" = "연락처에 있는 상대가 이미 Riot이나 Matrix를 이용하고 있다는 걸 보여주기 위해 연락처의 이메일 주소와 전화번호를 Matrix 아이덴티티 서버로 보낼 수 있습니다. 새 Vector는 이 자료를 저장하거나 다른 용도로 사용하지 않습니다. 자세한 내용은 애플리케이션 설정에 있는 개인정보 보호정책을 읽어주세요."; +"NSContactsUsageDescription" = "연락처에 있는 상대가 이미 Riot이나 Matrix를 이용하고 있다는 걸 보여주기 위해 연락처의 이메일 주소와 전화번호를 Matrix ID 서버로 보낼 수 있습니다. 새 Vector는 이 자료를 저장하거나 다른 용도로 사용하지 않습니다. 자세한 내용은 애플리케이션 설정에 있는 개인정보 보호 정책을 읽어주세요."; "NSCalendarsUsageDescription" = "앱에서 예정된 회의를 봅니다."; diff --git a/Riot/Assets/ko.lproj/Localizable.strings b/Riot/Assets/ko.lproj/Localizable.strings index 779227e7f..32f536333 100644 --- a/Riot/Assets/ko.lproj/Localizable.strings +++ b/Riot/Assets/ko.lproj/Localizable.strings @@ -1,34 +1,56 @@ /* New message from a specific person, not referencing a room */ -"MSG_FROM_USER" = "%@가 보낸 메시지"; +"MSG_FROM_USER" = "%@님이 메시지를 보냈습니다"; /* New message from a specific person in a named room */ -"MSG_FROM_USER_IN_ROOM" = "%@ 방에 게시 %@"; +"MSG_FROM_USER_IN_ROOM" = "%@님, %@ 방에 게시함"; /* New message from a specific person, not referencing a room. Content included. */ "MSG_FROM_USER_WITH_CONTENT" = "%@: %@"; /* New message from a specific person in a named room. Content included. */ -"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@: %@ 안의 %@"; +"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@님, %@ 방에서: %@"; /* New action message from a specific person, not referencing a room. */ "ACTION_FROM_USER" = "* %@ %@"; /* New action message from a specific person in a named room. */ "ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@"; /* New action message from a specific person, not referencing a room. */ -"IMAGE_FROM_USER" = "%@ 보낸 사진 %@"; +"IMAGE_FROM_USER" = "%@님이 사진을 보냈습니다 %@"; /* A single unread message in a room */ -"SINGLE_UNREAD_IN_ROOM" = "%@에서 메시지를 받았습니다"; +"SINGLE_UNREAD_IN_ROOM" = "%@ 방에서 메시지를 받았습니다"; /* A single unread message */ "SINGLE_UNREAD" = "메시지를 받았습니다"; /* A user has invited you to a chat */ -"USER_INVITE_TO_CHAT" = "%@가 대화에 당신을 초대했습니다"; +"USER_INVITE_TO_CHAT" = "%@님이 당신을 대화에 초대했습니다"; /* A user has invited you to an (unamed) group chat */ -"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@가 그룹 대화에 당신을 초대했습니다"; +"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@님이 그룹 대화에 당신을 초대했습니다"; /* Incoming one-to-one voice call */ -"VOICE_CALL_FROM_USER" = "%@이 건 통화"; +"VOICE_CALL_FROM_USER" = "%@님이 건 전화"; /* Incoming one-to-one video call */ -"VIDEO_CALL_FROM_USER" = "%@가 건 영상통화"; +"VIDEO_CALL_FROM_USER" = "%@님이 건 영상 통화"; /* Incoming unnamed voice conference invite from a specific person */ -"VOICE_CONF_FROM_USER" = "%@이 건 그룹통화"; +"VOICE_CONF_FROM_USER" = "%@님이 건 그룹 통화"; /* Incoming unnamed video conference invite from a specific person */ -"VIDEO_CONF_FROM_USER" = "%@이 건 영상그룹통화"; +"VIDEO_CONF_FROM_USER" = "%@님이 건 영상 그룹 통화"; /* Sticker from a specific person, not referencing a room. */ -"STICKER_FROM_USER" = "%@가 스티커를 보냈습니다"; +"STICKER_FROM_USER" = "%@님이 스티커를 보냈습니다"; /* A user has invited you to a named room */ -"USER_INVITE_TO_NAMED_ROOM" = "%@가 %@로 당신을 초대했습니다"; +"USER_INVITE_TO_NAMED_ROOM" = "%@님이 %@ 방으로 당신을 초대했습니다"; +/* Message title for a specific person in a named room */ +"MSG_FROM_USER_IN_ROOM_TITLE" = "%@님, %@ 방에 있음"; +/* New action message from a specific person in a named room. */ +"IMAGE_FROM_USER_IN_ROOM" = "%@님이 사진을 보냈습니다 %@, %@ 방에서"; +/* Multiple unread messages in a room */ +"UNREAD_IN_ROOM" = "%@개의 새 메시지, %@ 방에서"; +/* Multiple unread messages from a specific person, not referencing a room */ +"MSGS_FROM_USER" = "%@개의 새 메시지, %@님으로부터"; +/* Multiple unread messages from two people */ +"MSGS_FROM_TWO_USERS" = "%@개의 새 메시지, %@님과 %@님으로부터"; +/* Multiple unread messages from three people */ +"MSGS_FROM_THREE_USERS" = "%@개의 새 메시지, %@님과 %@님, %@님으로부터"; +/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */ +"MSGS_FROM_TWO_PLUS_USERS" = "%@개의 새 메시지, %@님과 %@님 외 여러 명으로부터"; +/* Multiple messages in two rooms */ +"MSGS_IN_TWO_ROOMS" = "%@개의 새 메시지, %@ 방과 %@ 방에서"; +/* Look, stuff's happened, alright? Just open the app. */ +"MSGS_IN_TWO_PLUS_ROOMS" = "%@개의 새 메시지, %@ 방과 %@ 방 외 여러 방에서"; +/* Incoming named voice conference invite from a specific person */ +"VOICE_CONF_NAMED_FROM_USER" = "%@님이 건 그룹 통화: '%@'"; +/* Incoming named video conference invite from a specific person */ +"VIDEO_CONF_NAMED_FROM_USER" = "%@님이 건 영상 그룹 통화: '%@'"; diff --git a/Riot/Assets/ko.lproj/Vector.strings b/Riot/Assets/ko.lproj/Vector.strings index cd578248f..36f48a5bb 100644 --- a/Riot/Assets/ko.lproj/Vector.strings +++ b/Riot/Assets/ko.lproj/Vector.strings @@ -13,12 +13,793 @@ "create" = "만들기"; "start" = "시작"; "leave" = "떠나기"; -"remove" = "지우기"; +"remove" = "감추기"; "invite" = "초대"; -"retry" = "다시해보기"; +"retry" = "다시 시도"; "on" = "켜기"; "off" = "끄기"; "cancel" = "취소"; "save" = "저장"; -"preview" = "미리보기"; +"preview" = "미리 보기"; "camera" = "카메라"; +// String for App Store +"store_short_description" = "안전한 분산 대화/VoIP"; +"store_full_description" = "여러분의 통제 하에 완전히 유연한 대화 앱. Riot은 여러분이 원하는 방식으로 대화할 수 있도록 합니다. 개방형 분산 커뮤니티의 표준 - [matrix]를 위해 제작됨. \n \n무료 matrix.org 계정을 만들고, https://modular.im에서 자신만의 서버, 혹은 다른 Matrix 서버를 얻으세요. \n \n왜 Riot.im을 선택해야 하나요? \n \n완전한 대화: 원하는 대로 팀이나 친구, 커뮤니티를 중심으로 방을 만드세요! 대화, 파일 공유, 위젯 추가와 음성 및 영상 통화 - 모두 무료입니다. \n \n강력한 통합: 여러분이 알고 사랑하는 도구와 함께 Riot.im을 사용하세요. Riot.im이라면 다른 대화 앱의 사용자와 그룹까지도 대화할 수 있습니다. \n \n개인 및 보안: 대화를 비밀로 유지하세요. 최첨단 종단간 암호화로 비밀 대화를 은밀하게 유지해줍니다. \n \n오픈 소스: Matrix로 만들어진 오픈 소스입니다. 자신의 데이터를 자신의 서버에 소유하거나, 신뢰하는 서버에 맡기세요. \n \n어디에 있든: 모든 기기나 https://riot.im에서 완전히 동기화된 메시지 기록으로 연락을 유지합니다."; +"join" = "참가"; +"decline" = "끊기"; +"accept" = "수락"; +"voice" = "음성"; +"video" = "영상"; +"active_call" = "현재 전화"; +"active_call_details" = "현재 전화 (%@)"; +"later" = "나중에"; +"rename" = "이름 다시 짓기"; +"collapse" = "접기"; +"send_to" = "%@님에게 보내기"; +"sending" = "보내는 중"; +"close" = "닫기"; +// Authentication +"auth_login" = "로그인"; +"auth_register" = "등록"; +"auth_submit" = "제출"; +"auth_skip" = "넘기기"; +"auth_login_single_sign_on" = "통합 인증(SSO)으로 로그인"; +"auth_send_reset_email" = "초기화 이메일 보내기"; +"auth_return_to_login" = "로그인 화면으로 돌아가기"; +"auth_user_id_placeholder" = "이메일 혹은 사용자 이름"; +"auth_password_placeholder" = "비밀번호"; +"auth_new_password_placeholder" = "새 비밀번호"; +"auth_user_name_placeholder" = "사용자 이름"; +"auth_optional_email_placeholder" = "이메일 주소 (선택)"; +"auth_email_placeholder" = "이메일 주소"; +"auth_optional_phone_placeholder" = "전화번호 (선택)"; +"auth_phone_placeholder" = "전화번호"; +"auth_repeat_password_placeholder" = "비밀번호 다시 입력"; +"auth_repeat_new_password_placeholder" = "새 비밀번호 확인"; +"auth_home_server_placeholder" = "URL (예: https://matrix.org)"; +"auth_identity_server_placeholder" = "URL (예: https://matrix.org)"; +"auth_invalid_login_param" = "맞지 않은 사용자 이름 혹은 비밀번호"; +"auth_invalid_user_name" = "사용자 이름에는 문자, 숫자, 점, 하이픈(-)과 밑줄(_)만 들어갑니다"; +"auth_invalid_password" = "비밀번호가 너무 짧음 (최소 6자 이상)"; +"auth_invalid_email" = "올바른 이메일 주소가 아닙니다"; +"auth_invalid_phone" = "올바른 전화번호가 아닙니다"; +"auth_missing_password" = "비밀번호가 누락되었습니다"; +"auth_add_email_message" = "계정에 이메일 주소를 추가해 다른 사용자가 당신을 검색할 수 있고, 비밀번호를 다시 설정할 수 있습니다."; +"auth_add_phone_message" = "계정에 전화번호를 추가해 다른 사용자가 당신을 검색할 수 있습니다."; +"auth_add_email_phone_message" = "계정에 이메일 주소 그리고/혹은 전화번호를 추가해 다른 사용자가 당신을 검색할 수 있습니다. 이메일 주소는 비밀번호를 다시 설정하는 데에도 사용됩니다."; +"auth_add_email_and_phone_message" = "이메일 주소와 전화번호를 추가해 다른 사용자가 당신을 검색할 수 있습니다. 이메일 주소는 비밀번호를 다시 설정하는 데에도 사용됩니다."; +"auth_missing_email" = "이메일 주소가 누락되었습니다"; +"auth_missing_phone" = "전화번호가 누락되었습니다"; +"auth_missing_email_or_phone" = "이메일 주소 혹은 전화번호가 누락되었습니다"; +"auth_email_in_use" = "이 이메일 주소는 이미 사용 중입니다"; +"auth_phone_in_use" = "이 전화번호는 이미 사용 중입니다"; +"auth_untrusted_id_server" = "ID 서버를 신뢰할 수 없습니다"; +"auth_password_dont_match" = "비밀번호가 맞지 않음"; +"auth_username_in_use" = "사용 중인 사용자 이름"; +"auth_forgot_password" = "비밀번호를 잊었습니까?"; +"auth_forgot_password_error_no_configured_identity_server" = "ID 서버를 설정할 수 없음: 비밀번호를 다시 설정하기 위해 하나를 추가하세요."; +"auth_email_not_found" = "이메일 전송에 실패함: 이 이메일 주소를 찾을 수 없음"; +"auth_use_server_options" = "맞춤 서버 옵션 사용 (고급)"; +"auth_email_validation_message" = "가입을 계속하려면 이메일을 확인해주세요"; +"auth_msisdn_validation_title" = "확인 보류 중"; +"auth_msisdn_validation_message" = "활성 코드가 있는 SMS를 보냈습니다. 아래에 이 코드를 입력해주세요."; +"auth_msisdn_validation_error" = "전화번호를 확인할 수 없습니다."; +"auth_recaptcha_message" = "이 홈서버는 당신이 로봇이 아닌지 알고 싶습니다"; +"auth_reset_password_message" = "비밀번호를 다시 설정하려면, 계정에 연결된 이메일 주소를 입력하세요:"; +"auth_reset_password_missing_email" = "계정에 연결된 이메일 주소를 입력해야 합니다."; +"auth_reset_password_missing_password" = "새 비밀번호를 입력해야 합니다."; +"auth_reset_password_email_validation_message" = "이메일을 %@(으)로 보냈습니다. 링크를 따라간 뒤, 아래를 클릭하세요."; +"auth_reset_password_next_step_button" = "저는 제 이메일 주소를 확인했습니다"; +"auth_reset_password_error_unauthorized" = "이메일 주소 확인에 실패함: 이메일에 있는 링크를 클릭했는 지 확인하세요"; +"auth_reset_password_error_not_found" = "이메일 주소가 이 홈서버의 Matrix ID에 연결되어 있지 않습니다."; +"auth_reset_password_success_message" = "비밀번호가 다시 설정되었습니다.\n\n모든 기기에서 로그아웃되며 더 이상 푸시 알림을 받을 수 없습니다. 알림을 다시 켜려면 각 기기마다 다시 로그인하세요."; +"auth_add_email_and_phone_warning" = "API가 있기 전까진 이메일과 전화번호를 동시에 등록하는 것을 지원하지 않습니다. 오직 계정에는 전화번호만 들어갑니다. 설정에서 프로필에 이메일을 추가할 수 있습니다."; +"auth_accept_policies" = "이 홈서버의 정책을 검토하고 수락해주세요:"; +"auth_autodiscover_invalid_response" = "잘못된 홈서버 검색 응답"; +"auth_softlogout_signed_out" = "로그아웃했습니다"; +"auth_softlogout_sign_in" = "로그인"; +"auth_softlogout_reason" = "당신의 홈서버 (%1$@) 관리자가 당신의 계정 %2$@을(를) 로그아웃했습니다 (%3$@)."; +"auth_softlogout_recover_encryption_keys" = "이 기기에 독점적으로 저장된 암호화 키를 복구하려면 로그인하세요. 이 키가 있어야 기기에서 모든 보안 메시지를 읽을 수 있습니다."; +"auth_softlogout_clear_data" = "개인 정보 지우기"; +"auth_softlogout_clear_data_message_1" = "경고: (암호화 키를 포함한) 개인 정보는 이 기기에 여전히 저장됩니다."; +"auth_softlogout_clear_data_message_2" = "이 기기를 그만 사용하거나 다른 계정으로 로그인하고 싶은 경우에 지우세요."; +"auth_softlogout_clear_data_button" = "모든 데이터 지우기"; +"auth_softlogout_clear_data_sign_out_title" = "확신합니까?"; +"auth_softlogout_clear_data_sign_out_msg" = "현재 이 기기에 저장된 모든 데이터를 지우겠습니까? 계정 데이터와 메시지에 접근하도록 다시 로그인하세요."; +"auth_softlogout_clear_data_sign_out" = "로그아웃"; +// Chat creation +"room_creation_title" = "새 대화"; +"room_creation_account" = "계정"; +"room_creation_appearance" = "모습"; +"room_creation_appearance_name" = "이름"; +"room_creation_appearance_picture" = "대화 사진 (선택)"; +"room_creation_privacy" = "개인"; +"room_creation_private_room" = "이 대화는 개인입니다"; +"room_creation_public_room" = "이 대화는 공개입니다"; +"room_creation_make_public" = "공개로 하기"; +"room_creation_make_public_prompt_title" = "이 대화를 공개로 합니까?"; +"room_creation_make_public_prompt_msg" = "이 대화를 공개로 하겠습니까? 누구나 메시지를 읽고 대화에 참여할 수 있습니다."; +"room_creation_keep_private" = "개인으로 유지"; +"room_creation_make_private" = "개인으로 하기"; +"room_creation_wait_for_creation" = "방을 이미 만드는 중입니다. 기다려주세요."; +"room_creation_invite_another_user" = "검색 / 사용자 ID, 이름 또는 이메일로 초대"; +"room_creation_error_invite_user_by_email_without_identity_server" = "ID 서버가 설정되지 않아 이메일로 참가자를 추가할 수 없습니다."; +// Room recents +"room_recents_directory_section" = "방 목록"; +"room_recents_directory_section_network" = "네트워크"; +"room_recents_favourites_section" = "즐겨찾기"; +"room_recents_people_section" = "사람"; +"room_recents_conversations_section" = "방"; +"room_recents_no_conversation" = "방 없음"; +"room_recents_low_priority_section" = "중요하지 않음"; +"room_recents_server_notice_section" = "시스템 경고"; +"room_recents_invites_section" = "초대"; +"room_recents_start_chat_with" = "대화 시작"; +"room_recents_create_empty_room" = "방 만들기"; +"room_recents_join_room" = "방 참가"; +"room_recents_join_room_title" = "방 참가"; +"room_recents_join_room_prompt" = "방 ID 또는 방 별칭을 입력"; +// People tab +"people_invites_section" = "초대"; +"people_conversation_section" = "대화"; +"people_no_conversation" = "대화 없음"; +// Rooms tab +"room_directory_no_public_room" = "이용할 수 있는 공개 방 없음"; +// Groups tab +"group_invite_section" = "초대"; +"group_section" = "커뮤니티"; +// Search +"search_rooms" = "방"; +"search_messages" = "메시지"; +"search_people" = "사람"; +"search_files" = "파일"; +"search_default_placeholder" = "검색"; +"search_people_placeholder" = "사용자 ID, 이름 또는 이메일로 검색"; +"search_no_result" = "결과 없음"; +"search_in_progress" = "검색 중…"; +// Directory +"directory_cell_title" = "목록 찾기"; +"directory_cell_description" = "%tu개의 방"; +"directory_search_results_title" = "목록 결과 찾기"; +"directory_search_results" = "%@(으)로 찾은 %tu개의 결과"; +"directory_search_results_more_than" = ">%@(으)로 찾은 %tu개의 결과"; +"directory_searching_title" = "목록 검색 중…"; +"directory_search_fail" = "데이터 가져오기에 실패함"; +// Contacts +"contacts_address_book_section" = "로컬 연락처"; +"contacts_address_book_matrix_users_toggle" = "Matrix 사용자만"; +"contacts_address_book_no_contact" = "로컬 연락처 없음"; +"contacts_address_book_permission_required" = "로컬 연락처에 접근하는데 필요한 권한"; +"contacts_address_book_permission_denied" = "Riot이 로컬 연락처에 접근하도록 허용하지 않음"; +"contacts_user_directory_section" = "사용자 목록"; +"contacts_user_directory_offline_section" = "사용자 목록 (오프라인)"; +// Chat participants +"room_participants_title" = "참가자"; +"room_participants_add_participant" = "참가자 추가"; +"room_participants_one_participant" = "1명의 참가자"; +"room_participants_multi_participants" = "%d명의 참가자"; +"room_participants_leave_prompt_title" = "방 떠나기"; +"room_participants_leave_prompt_msg" = "방을 떠나겠습니까?"; +"room_participants_remove_prompt_title" = "확인"; +"room_participants_remove_prompt_msg" = "이 대화에서 %@을(를) 제거하겠습니까?"; +"room_participants_remove_third_party_invite_msg" = "API가 있기 전까진 제 3자 초대를 제거하는 것은 아직 지원하지 않습니다"; +"room_participants_invite_prompt_title" = "확인"; +"room_participants_invite_prompt_msg" = "%@님을 이 대화에 초대하겠습니까?"; +"room_participants_filter_room_members" = "방 구성원 필터"; +"room_participants_invite_another_user" = "검색 / 사용자 ID, 이름 또는 이메일로 초대"; +"room_participants_invite_malformed_id_title" = "초대 오류"; +"room_participants_invite_malformed_id" = "잘못된 ID. 이메일 주소 혹은 '@localpart:domain'과 같은 Matrix ID이어야 합니다"; +"room_participants_invited_section" = "초대받음"; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "ID 서버가 설정되지 않아서 이메일을 사용하는 연락처와 대화를 시작할 수 없습니다."; +"room_participants_online" = "온라인"; +"room_participants_offline" = "오프라인"; +"room_participants_unknown" = "알 수 없음"; +"room_participants_idle" = "대기 중"; +"room_participants_now" = "지금"; +"room_participants_ago" = "전"; +"room_participants_action_section_admin_tools" = "관리자 도구"; +"room_participants_action_section_direct_chats" = "다이렉트 대화"; +"room_participants_action_section_devices" = "기기"; +"room_participants_action_section_other" = "기타"; +"room_participants_action_invite" = "초대"; +"room_participants_action_leave" = "이 방 떠나기"; +"room_participants_action_remove" = "이 방에서 제거"; +"room_participants_action_ban" = "이 방에서 차단"; +"room_participants_action_unban" = "차단 풀기"; +"room_participants_action_ignore" = "이 사용자의 모든 메시지 숨기기"; +"room_participants_action_unignore" = "이 사용자의 모든 메시지 보이기"; +"room_participants_action_set_default_power_level" = "보통 사용자로 다시 설정"; +"room_participants_action_set_moderator" = "중재자로 하기"; +"room_participants_action_set_admin" = "관리자로 하기"; +"room_participants_action_start_new_chat" = "새 대화 시작"; +"room_participants_action_start_voice_call" = "음성 통화 시작"; +"room_participants_action_start_video_call" = "영상 통화 시작"; +"room_participants_action_mention" = "언급"; +// Chat +"room_jump_to_first_unread" = "처음으로 읽지 않은 메시지로 가기"; +"room_new_message_notification" = "%d개의 새 메시지"; +"room_new_messages_notification" = "%d개의 새 메시지"; +"room_one_user_is_typing" = "%@님이 입력하는 중…"; +"room_two_users_are_typing" = "%@님 & %@님이 입력하는 중…"; +"room_many_users_are_typing" = "%@님, %@님 외 여러 명이 입력하는 중…"; +"room_message_placeholder" = "(암호화 안 된) 메시지를 보내세요…"; +"room_message_reply_to_placeholder" = "(암호화 안 된) 답장을 보내세요…"; +"room_message_unable_open_link_error_message" = "링크를 열 수 없습니다."; +"room_do_not_have_permission_to_post" = "이 방에 글을 올릴 권한이 없습니다"; +"encrypted_room_message_placeholder" = "암호화된 메시지를 보내세요…"; +"encrypted_room_message_reply_to_placeholder" = "암호화된 답장을 보내세요…"; +"room_message_short_placeholder" = "메시지를 보내세요…"; +"room_message_reply_to_short_placeholder" = "답장을 보내세요…"; +"room_offline_notification" = "서버와의 연결이 끊겼습니다."; +"room_unsent_messages_notification" = "메시지가 보내지지 않았습니다. %1$s, %2$s, 둘 중 어느 것을 하겠습니까?"; +"room_unsent_messages_unknown_devices_notification" = "알 수 없는 기기가 있어 메시지가 보내지지 않았습니다. %1$s, %2$s, 둘 중 어느 것을 하겠습니까?"; +"room_ongoing_conference_call" = "회의 전화가 진행 중입니다. %1$s 또는 %2$s로 참가하세요."; +"room_ongoing_conference_call_with_close" = "회의 전화가 진행 중입니다. %1$s 또는 %2$s로 참가하세요. %@."; +"room_ongoing_conference_call_close" = "닫기"; +"room_conference_call_no_power" = "이 방에서 회의 전화를 관리할 권한이 필요합니다"; +"room_prompt_resend" = "모두 다시 보내기"; +"room_prompt_cancel" = "모두 취소하기"; +"room_resend_unsent_messages" = "보내지지 않은 메시지 다시 보내기"; +"room_delete_unsent_messages" = "보내지지 않은 메시지 삭제하기"; +"room_event_action_copy" = "복사"; +"room_event_action_quote" = "인용"; +"room_event_action_redact" = "감추기"; +"room_event_action_more" = "더 보기"; +"room_event_action_share" = "공유"; +"room_event_action_permalink" = "고유 링크"; +"room_event_action_view_source" = "소스 보기"; +"room_event_action_view_decrypted_source" = "암호화된 소스 보기"; +"room_event_action_report" = "내용 보고하기"; +"room_event_action_report_prompt_reason" = "이 내용을 보고하는 이유"; +"room_event_action_kick_prompt_reason" = "이 사용자를 추방하는 이유"; +"room_event_action_ban_prompt_reason" = "이 사용자를 차단하는 이유"; +"room_event_action_report_prompt_ignore_user" = "이 사용자의 모든 메시지를 숨기겠습니까?"; +"room_event_action_save" = "저장"; +"room_event_action_resend" = "다시 보내기"; +"room_event_action_delete" = "삭제"; +"room_event_action_cancel_send" = "보내기 취소"; +"room_event_action_cancel_download" = "다운로드 취소"; +"room_event_action_view_encryption" = "암호화 정보"; +"room_event_action_reply" = "답장"; +"room_event_action_edit" = "편집"; +"room_event_action_reaction_show_all" = "모두 보이기"; +"room_event_action_reaction_show_less" = "적게 보이기"; +"room_event_action_reaction_history" = "리액션 기록"; +"room_warning_about_encryption" = "종단간 암호화는 베타 버전이고 신뢰하지 못할 수 있습니다.\n\n아직 데이터를 보호한다고 신뢰하지 마세요.\n\n기기가 방에 참가하기 전에 아직 기록을 해독할 수 없습니다.\n\n아직 암호화를 구현하지 않았기 때문에 암호화된 메시지는 클라이언트에 나타나지 않습니다."; +"room_event_failed_to_send" = "보내기에 실패함"; +"room_action_camera" = "사진 또는 영상 찍기"; +"room_action_send_photo_or_video" = "사진 또는 영상 보내기"; +"room_action_send_sticker" = "스티커 보내기"; +"room_action_send_file" = "파일 보내기"; +"room_action_reply" = "답장"; +"room_replacement_information" = "이 방은 대체되었으며 더 이상 활동하지 않습니다."; +"room_replacement_link" = "대화는 여기서 이어집니다."; +"room_predecessor_information" = "이 방에서 다른 대화가 이어집니다."; +"room_predecessor_link" = "여기를 눌러 과거 메시지를 보세요."; +"room_resource_limit_exceeded_message_contact_1" = " 제발 "; +"room_resource_limit_exceeded_message_contact_2_link" = "서비스 관리자와 연락해서"; +"room_resource_limit_exceeded_message_contact_3" = " 이 서비스를 계속 사용하세요."; +"room_resource_usage_limit_reached_message_1_default" = "이 홈서버가 리소스 한도를 초과했습니다 따라서 "; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "이 홈서버가 월 간 활성 사용자 한도를 초과했습니다 따라서 "; +"room_resource_usage_limit_reached_message_2" = "일부 사용자는 로그인할 수 없습니다."; +"room_resource_usage_limit_reached_message_contact_3" = " 한도를 높이세요."; +"room_message_edits_history_title" = "메시지 편집"; +// Unknown devices +"unknown_devices_alert_title" = "방에 알 수 없는 기기가 있음"; +"unknown_devices_alert" = "이 방에 확인되지 않은 알 수 없는 기기가 있습니다.이 기기가 확인한 사용자의 것이라는 보장이 없습니다.\n계속하기 전에 각 기기마다 확인 절차를 거치기를 권합니다, 하지만 원한다면 확인하지 않고 메시지를 다시 보낼 수 있습니다."; +"unknown_devices_send_anyway" = "무시하고 보내기"; +"unknown_devices_call_anyway" = "무시하고 전화"; +"unknown_devices_answer_anyway" = "무시하고 답하기"; +"unknown_devices_verify" = "확인하기…"; +"unknown_devices_title" = "알 수 없는 기기"; +// Room Title +"room_title_new_room" = "새 방"; +"room_title_multiple_active_members" = "%@/%@ 활동 중인 구성원"; +"room_title_one_active_member" = "%@/%@ 활동 중인 구성원"; +"room_title_invite_members" = "구성원 초대"; +"room_title_members" = "%@명의 구성원"; +"room_title_one_member" = "1명의 구성원"; +// Room Preview +"room_preview_invitation_format" = "%@님에게 이 방을 초대받았습니다"; +"room_preview_subtitle" = "이 방의 미리 보기입니다. 방 상호작용은 꺼져 있습니다."; +"room_preview_unlinked_email_warning" = "이 초대는 %@님이 보냈습니다, 이 계정과는 연관이 없습니다. 다른 계정으로 로그인하거나, 이 이메일을 계정에 추가하세요."; +"room_preview_try_join_an_unknown_room" = "%@(으)로 접근하려 했습니다. 토론에 참여하기 위해 참가하는 건가요?"; +"room_preview_try_join_an_unknown_room_default" = "방"; +// Settings +"settings_title" = "설정"; +"account_logout_all" = "모든 계정에서 로그아웃"; +"settings_config_no_build_info" = "빌드 정보 없음"; +"settings_mark_all_as_read" = "모든 메시지를 읽음으로 표시"; +"settings_report_bug" = "버그 신고"; +"settings_clear_cache" = "캐시 지우기"; +"settings_config_home_server" = "홈서버: %@"; +"settings_config_identity_server" = "ID 서버: %@"; +"settings_config_user_id" = "사용자 ID: %@"; +"settings_user_settings" = "사용자 설정"; +"settings_notifications_settings" = "알림 설정"; +"settings_calls_settings" = "전화"; +"settings_user_interface" = "사용자 인터페이스"; +"settings_ignored_users" = "무시한 사용자"; +"settings_contacts" = "로컬 연락처"; +"settings_advanced" = "고급"; +"settings_other" = "기타"; +"settings_labs" = "연구실"; +"settings_flair" = "허용되는 곳에 재능 보이기"; +"settings_devices" = "기기"; +"settings_cryptography" = "암호화"; +"settings_key_backup" = "키 백업"; +"settings_deactivate_account" = "계정 비활성화"; +"settings_sign_out" = "로그아웃"; +"settings_sign_out_confirmation" = "확신합니까?"; +"settings_sign_out_e2e_warn" = "종단간 암호화 키를 잃게 됩니다. 더 이상 이 기기로 암호화된 방의 예전 메시지를 읽을 수 없게 됩니다."; +"settings_profile_picture" = "프로필 사진"; +"settings_display_name" = "표시 이름"; +"settings_first_name" = "성"; +"settings_surname" = "이름"; +"settings_remove_prompt_title" = "확인"; +"settings_remove_email_prompt_msg" = "이메일 주소 %@을(를) 제거하겠습니까?"; +"settings_remove_phone_prompt_msg" = "전화번호 %@을(를) 지우겠습니까?"; +"settings_email_address" = "이메일"; +"settings_email_address_placeholder" = "이메일 주소를 입력하세요"; +"settings_add_email_address" = "이메일 주소 추가"; +"settings_phone_number" = "휴대 전화"; +"settings_add_phone_number" = "전화번호 추가"; +"settings_change_password" = "비밀번호 변경"; +"settings_night_mode" = "야간 모드"; +"settings_fail_to_update_profile" = "프로필 업데이트에 실패함"; +"settings_enable_push_notif" = "이 기기에서 알림"; +"settings_show_decrypted_content" = "암호화된 내용 보이기"; +"settings_global_settings_info" = "당신의 %@ 웹 클라이언트에 전역 알림 설정이 켜졌습니다"; +"settings_pin_rooms_with_missed_notif" = "알림을 놓친 방을 고정"; +"settings_pin_rooms_with_unread" = "읽지 않은 메시지가 있는 방을 고정"; +"settings_on_denied_notification" = "%@에 의해 알림이 거부됬습니다, 기기 설정에서 %@을(를) 허용해주세요"; +"settings_enable_callkit" = "통합 전화"; +"settings_callkit_info" = "잠금 화면에서 오는 전화를 받습니다. 시스템의 통화 내역에서 Riot 통화를 확인하세요. iCloud가 켜져있다면, 이 통화 기록은 Apple과 공유됩니다."; +"settings_ui_language" = "언어"; +"settings_ui_theme" = "테마"; +"settings_ui_theme_auto" = "자동"; +"settings_ui_theme_light" = "밝게"; +"settings_ui_theme_dark" = "어둡게"; +"settings_ui_theme_black" = "검정"; +"settings_ui_theme_picker_title" = "테마를 선택하세요"; +"settings_ui_theme_picker_message" = "\"자동\"은 기기의 \"색상 반전\" 설정을 사용합니다"; +"settings_unignore_user" = "%@님의 모든 메시지를 표시합니까?"; +"settings_contacts_discover_matrix_users" = "이메일과 전화번호로 사용자를 검색"; +"settings_contacts_phonebook_country" = "국제전화 나라 번호"; +"settings_labs_e2e_encryption" = "종단간 암호화"; +"settings_labs_e2e_encryption_prompt_message" = "암호화 설정을 마치려면 다시 로그인하세요."; +"settings_labs_room_members_lazy_loading" = "방 구성원 불러오기 지연"; +"settings_labs_room_members_lazy_loading_error_message" = "홈서버가 아직 방 구성원 불러오기 지연을 지원하지 않습니다. 나중에 다시 시도해보세요."; +"settings_labs_create_conference_with_jitsi" = "Jitsi로 회의 전화 만들기"; +"settings_labs_message_reaction" = "메시지에 이모지로 리액션하기"; +"settings_version" = "버전 %@"; +"settings_olm_version" = "Olm 버전 %@"; +"settings_copyright" = "저작권"; +"settings_copyright_url" = "https://riot.im/copyright"; +"settings_term_conditions" = "이용 약관"; +"settings_term_conditions_url" = "https://riot.im/tac_apple"; +"settings_privacy_policy" = "개인 정보 정책"; +"settings_privacy_policy_url" = "https://riot.im/privacy"; +"settings_third_party_notices" = "제 3자 공지"; +"settings_send_crash_report" = "충돌 & 사용 데이터 보내기"; +"settings_enable_rageshake" = "분노의 흔들기로 버그 신고"; +"settings_old_password" = "이전 비밀번호"; +"settings_new_password" = "새 비밀번호"; +"settings_confirm_password" = "비밀번호 확인"; +"settings_fail_to_update_password" = "비밀번호 업데이트에 실패함"; +"settings_password_updated" = "비밀번호가 업데이트되었습니다"; +"settings_crypto_device_name" = "기기 이름: "; +"settings_crypto_device_id" = "\n기기 ID: "; +"settings_crypto_device_key" = "\n기기 키: "; +"settings_crypto_export" = "키 내보내기"; +"settings_crypto_blacklist_unverified_devices" = "확인된 기기만 암호화"; +"settings_deactivate_my_account" = "내 계정 비활성화"; +"settings_key_backup_info" = "암호화된 메시지는 종단간 암호화로 보호됩니다. 오직 당신과 참가자만 키를 갖고 있어서 이 메시지를 읽을 수 있습니다."; +"settings_key_backup_info_checking" = "확인 중..."; +"settings_key_backup_info_none" = "키가 이 기기에서 백업되지 않았습니다."; +"settings_key_backup_info_signout_warning" = "이 기기에만 있을 수 있는 키를 잃지 않도록, 로그아웃하기 전에 이 기기를 키 백업에 연결하세요."; +"settings_key_backup_info_version" = "키 백업 버전: %@"; +"settings_key_backup_info_algorithm" = "알고리즘: %@"; +"settings_key_backup_info_valid" = "이 기기는 키를 백업하고 있습니다."; +"settings_key_backup_info_not_valid" = "이 기기는 키를 백업하고 있지 않습니다, 하지만 존재하는 백업이 있고 이것을 복구한 뒤 키를 추가할 수 있습니다."; +"settings_key_backup_info_progress" = "%@ 키를 백업하는 중..."; +"settings_key_backup_info_progress_done" = "모든 키가 백업됨"; +"settings_key_backup_info_trust_signature_unknown" = "백업은 기기로부터 ID로 된 서명을 갖습니다: %@"; +"settings_key_backup_info_trust_signature_valid" = "백업이 이 기기로부터 올바른 서명을 갖고 있음"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "백업이 %@(으)로부터 올바른 서명을 갖고 있음"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "백업이 %@(으)로부터 서명을 갖고 있음"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "백업이 %@(으)로부터 올바르지 않은 서명을 갖고 있음"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "백업이 %@(으)로부터 올바르지 않은 서명을 갖고 있음"; +"settings_key_backup_button_create" = "키 백업 시작"; +"settings_key_backup_button_restore" = "백업에서 복구"; +"settings_key_backup_button_delete" = "백업 삭제"; +"settings_key_backup_button_connect" = "이 기기를 키 백업에 연결"; +"settings_key_backup_delete_confirmation_prompt_title" = "백업 삭제"; +"settings_key_backup_delete_confirmation_prompt_msg" = "확신합니까? 키가 정상적으로 백업되지 않으면 암호화된 메시지를 잃게 됩니다."; +// Room Details +"room_details_title" = "방 세부 사항"; +"room_details_people" = "구성원"; +"room_details_files" = "파일"; +"room_details_settings" = "설정"; +"room_details_photo" = "방 사진"; +"room_details_room_name" = "방 이름"; +"room_details_topic" = "주제"; +"room_details_favourite_tag" = "즐겨찾기"; +"room_details_low_priority_tag" = "중요하지 않음"; +"room_details_mute_notifs" = "알림 음소거"; +"room_details_direct_chat" = "다이렉트 대화"; +"room_details_access_section" = "이 방에 누가 접근할 수 있나요?"; +"room_details_access_section_invited_only" = "초대한 사람들만"; +"room_details_access_section_anyone_apart_from_guest" = "방의 링크를 아는 누구나, 손님 제외"; +"room_details_access_section_anyone" = "방의 링크를 아는 누구나, 손님 포함"; +"room_details_access_section_no_address_warning" = "방으로 링크를 주려면, 주소가 필요합니다"; +"room_details_access_section_directory_toggle" = "이 방을 방 목록에 배치"; +"room_details_history_section" = "누가 기록을 읽을 수 있나요?"; +"room_details_history_section_anyone" = "누구나"; +"room_details_history_section_members_only" = "(이 옵션을 선택한 시점부터) 구성원만"; +"room_details_history_section_members_only_since_invited" = "(초대받은 시점부터) 구성원만"; +"room_details_history_section_members_only_since_joined" = "(참가한 시점부터) 구성원만"; +"room_details_history_section_prompt_title" = "개인 정보 경고"; +"room_details_history_section_prompt_msg" = "이 방에서 기록을 읽을 수 있는 사람의 변경 사항은 이후 메시지부터 적용됩니다. 존재하는 기록의 가시성은 변하지 않습니다."; +"room_details_addresses_section" = "주소"; +"room_details_no_local_addresses" = "이 방은 로컬 주소가 없습니다"; +"room_details_new_address" = "새 주소 추가"; +"room_details_new_address_placeholder" = "새 주소 추가 (예: #foo%@)"; +"room_details_addresses_invalid_address_prompt_title" = "잘못된 별칭 형식"; +"room_details_addresses_invalid_address_prompt_msg" = "%@은(는) 별칭에 올바른 형식이 아닙니다"; +"room_details_addresses_disable_main_address_prompt_title" = "기본 주소 경고"; +"room_details_addresses_disable_main_address_prompt_msg" = "지정한 기본 주소가 없습니다. 이 방의 기본 주소는 무작위로 지정됩니다"; +"room_details_flair_section" = "커뮤니티 별 재능 보이기"; +"room_details_new_flair_placeholder" = "새 커뮤니티 ID 추가 (예: +foo%@)"; +"room_details_flair_invalid_id_prompt_title" = "잘못된 형식"; +"room_details_flair_invalid_id_prompt_msg" = "%@은(는) 커뮤니티의 올바른 ID가 아닙니다"; +"room_details_banned_users_section" = "차단한 사용자"; +"room_details_advanced_section" = "고급"; +"room_details_advanced_room_id" = "방 ID:"; +"room_details_advanced_enable_e2e_encryption" = "암호화 켜짐 (경고: 다시 끌 수 없습니다!)"; +"room_details_advanced_e2e_encryption_enabled" = "이 방의 암호화가 켜졌습니다"; +"room_details_advanced_e2e_encryption_disabled" = "이 방의 암호화가 꺼졌습니다."; +"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "확인된 기기만 암호화"; +"room_details_fail_to_update_avatar" = "방 사진 업데이트에 실패함"; +"room_details_fail_to_update_room_name" = "방 이름 업데이트에 실패함"; +"room_details_fail_to_update_topic" = "주제 업데이트에 실패함"; +"room_details_fail_to_update_room_guest_access" = "방 손님 접근 업데이트에 실패함"; +"room_details_fail_to_update_room_join_rule" = "참가 규칙 업데이트에 실패함"; +"room_details_fail_to_update_room_directory_visibility" = "방 목록 가시성 업데이트에 실패함"; +"room_details_fail_to_update_history_visibility" = "기록 가시성 업데이트에 실패함"; +"room_details_fail_to_add_room_aliases" = "새 방 주소 추가에 실패함"; +"room_details_fail_to_remove_room_aliases" = "방 주소 삭제에 실패함"; +"room_details_fail_to_update_room_canonical_alias" = "기본 주소 업데이트에 실패함"; +"room_details_fail_to_update_room_communities" = "관련된 커뮤니티 업데이트에 실패함"; +"room_details_fail_to_update_room_direct" = "이 방의 다이렉트 플래그 업데이트에 실패함"; +"room_details_fail_to_enable_encryption" = "이 방의 암호화 켜기에 실패함"; +"room_details_save_changes_prompt" = "변경 사항을 저장할까요?"; +"room_details_set_main_address" = "기본 주소로 설정"; +"room_details_unset_main_address" = "기본 주소로 설정 해제"; +"room_details_copy_room_id" = "방 ID 복사"; +"room_details_copy_room_address" = "방 주소 복사"; +"room_details_copy_room_url" = "방 URL 복사"; +// Group Details +"group_details_title" = "커뮤니티 세부 사항"; +"group_details_home" = "홈"; +"group_details_people" = "사람"; +"group_details_rooms" = "방"; +// Group Home +"group_home_one_member_format" = "1멍의 구성원"; +"group_home_multi_members_format" = "%tu명의 구성원"; +"group_home_one_room_format" = "1개의 방"; +"group_home_multi_rooms_format" = "%tu개의 방"; +"group_invitation_format" = "%@님이 이 커뮤니티에 당신을 초대했습니다"; +// Group participants +"group_participants_add_participant" = "참가자 추가"; +"group_participants_leave_prompt_title" = "그룹 떠나기"; +"group_participants_leave_prompt_msg" = "그룹을 떠나겠습니까?"; +"group_participants_remove_prompt_title" = "확인"; +"group_participants_remove_prompt_msg" = "이 그룹에서 %@을(를) 감추겠습니까?"; +"group_participants_invite_prompt_title" = "확인"; +"group_participants_invite_prompt_msg" = "이 그룹에 %@님을 초대하겠습니까?"; +"group_participants_filter_members" = "커뮤니티 구성원 필터"; +"group_participants_invite_another_user" = "사용자 ID 또는 이름으로 검색 / 초대"; +"group_participants_invite_malformed_id_title" = "초대 오류"; +"group_participants_invite_malformed_id" = "잘못된 ID. '@localpart:domain'과 같은 Matrix ID이어야 합니다"; +"group_participants_invited_section" = "초대받음"; +// Group rooms +"group_rooms_filter_rooms" = "커뮤니티 방 필터"; +// Read Receipts +"read_receipts_list" = "읽은 기록 목록"; +"receipt_status_read" = "읽음: "; +// Media picker +"media_picker_title" = "미디어 라이브러리"; +"media_picker_library" = "라이브러리"; +"media_picker_select" = "선택"; +// Image picker +"image_picker_action_camera" = "사진 찍기"; +"image_picker_action_library" = "라이브러리에서 선택"; +// Directory +"directory_title" = "목록"; +"directory_server_picker_title" = "목록을 선택"; +"directory_server_all_rooms" = "%@ 서버에 있는 모든 방"; +"directory_server_all_native_rooms" = "모든 네이티브 Matrix 방"; +"directory_server_type_homeserver" = "홈서버를 입력하면 공개 방 목록을 나열합니다"; +"directory_server_placeholder" = "matrix.org"; +// Events formatter +"event_formatter_member_updates" = "%tu명의 구성원 변경 사항"; +"event_formatter_widget_added" = "%@ 위젯을 %@님이 추가했습니다"; +"event_formatter_widget_removed" = "%@ 위젯을 %@님이 제거했습니다"; +"event_formatter_jitsi_widget_added" = "%@님이 VoIP 회의를 추가했습니다"; +"event_formatter_jitsi_widget_removed" = "%@님이 VoIP 회의를 제거했습니다"; +"event_formatter_rerequest_keys_part1_link" = "암호화 키 다시 요청"; +"event_formatter_rerequest_keys_part2" = " 다른 기기에서."; +"event_formatter_message_edited_mention" = "(편집됨)"; +// Others +"or" = "또는"; +"you" = "당신"; +"today" = "오늘"; +"yesterday" = "어제"; +"network_offline_prompt" = "인터넷이 오프라인입니다."; +"homeserver_connection_lost" = "홈 서버에 연결할 수 없습니다."; +"public_room_section_title" = "공개 방 (%@에 있음):"; +"bug_report_prompt" = "애플리케이션이 방금 충돌했군요.\n충돌 보고서를 제출하겠습니까?"; +"rage_shake_prompt" = "좌절감에 휴대 전화를 흔들고 있군요. 버그 보고서를 제출하겠습니까?"; +"do_not_ask_again" = "다시 묻지 않기"; +"camera_access_not_granted" = "%@님은 카메라를 사용할 권한이 없습니다, 개인 정보 설정을 바꿔주세요"; +"camera_unavailable" = "카메라는 이 기기에서 이용할 수 없습니다"; +"photo_library_access_not_granted" = "%@님은 사진 라이브러리에 접근할 권한이 없습니다, 개인 정보 설정을 바꿔주세요"; +"large_badge_value_k_format" = "%.1fK"; +"room_does_not_exist" = "%@님은 없습니다"; +// Call +"call_incoming_voice_prompt" = "%@님으로부터 온 음성 통화"; +"call_incoming_video_prompt" = "%@님으로부터 온 영상 통화"; +"call_incoming_voice" = "전화 오는 중..."; +"call_incoming_video" = "오는 영상 통화..."; +"call_already_displayed" = "이미 전화가 진행 중입니다."; +"call_jitsi_error" = "회의 전화 참가에 실패했습니다."; +// No VoIP support +"no_voip_title" = "전화 오는 중"; +"no_voip" = "%@님이 당신에게 전화를 걸고 있지만 %@은(는) 아직 전화를 지원하지 않습니다.\n이 알림을 무시하고 다른 기기에서 전화를 받거나 전화를 거절할 수 있습니다."; +// Crash report +"google_analytics_use_prompt" = "%@이(가) 개선하도록 자동으로 익명의 충돌 보고서와 사용 데이터를 제공하겠습니까?"; +// Crypto +"e2e_enabling_on_app_update" = "Riot는 이제 종단간 암호화를 지원하지만 암호화를 켜려면 다시 로그인해야 합니다.\n\n지금 다시 로그인하거나 나중에 애플리케이션 설정에서 할 수 있습니다."; +"e2e_need_log_in_again" = "이 기기에 종단간 암호화 키를 생성하고 공개 키를 홈서버에 제출하려면 다시 로그인해야 함니다.\n한 번만 하면 됩니다, 불편을 드려 죄송합니다."; +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "새 키 백업"; +"e2e_key_backup_wrong_version" = "새 보안 메시지 키 백업이 감지되었습니다.\n\n당신이 한 것이 아니라면 설정에서 새 암호를 설정하세요."; +"e2e_key_backup_wrong_version_button_settings" = "설정"; +"e2e_key_backup_wrong_version_button_wasme" = "접니다"; +// Bug report +"bug_report_title" = "버그 신고"; +"bug_report_description" = "버그를 설명해주세요. 무엇을 했나요? 무엇을 생각하고 했나요? 실제로 어떤 일이 일어났나요?"; +"bug_crash_report_title" = "충돌 보고서"; +"bug_crash_report_description" = "충돌 이전에 어떤 일을 했는 지 설명해주세요:"; +"bug_report_logs_description" = "문제를 진단하기 위해, 이 클라이언트의 로그를 이 버그 보고서에 제출합니다. 위의 문자만 보내지길 원한다면, 선택을 해제해주세요:"; +"bug_report_send_logs" = "로그 보내기"; +"bug_report_send_screenshot" = "스크린샷 보내기"; +"bug_report_progress_zipping" = "로그 수집 중"; +"bug_report_progress_uploading" = "신고 업로드 중"; +"bug_report_send" = "보내기"; +// Widget +"widget_no_integrations_server_configured" = "설정된 통합 서버가 없음"; +"widget_integrations_server_failed_to_connect" = "통합 서버 연결에 실패함"; +"widget_no_power_to_manage" = "이 방에서 위젯을 관리할 권한이 없습니다"; +"widget_creation_failure" = "위젯 생성에 실패함"; +"widget_sticker_picker_no_stickerpacks_alert" = "현재 활성화된 스티커팩이 없습니다."; +"widget_sticker_picker_no_stickerpacks_alert_add_now" = "지금 추가할까요?"; +// Widget Integration Manager +"widget_integration_need_to_be_able_to_invite" = "그렇게 하려면 사용자를 초대할 수 있어야 합니다."; +"widget_integration_unable_to_create" = "위젯 생성에 실패했습니다."; +"widget_integration_failed_to_send_request" = "요청 보내기에 실패했습니다."; +"widget_integration_room_not_recognised" = "이 방은 인식하지 않습니다."; +"widget_integration_positive_power_level" = "권한 등급은 양의 정수이어야 합니다."; +"widget_integration_must_be_in_room" = "당신은 이 방에 없습니다."; +"widget_integration_no_permission_in_room" = "이 방에 그런 작업을 할 권한이 없습니다."; +"widget_integration_missing_room_id" = "요청에 room_id가 없습니다."; +"widget_integration_missing_user_id" = "요청에 user_id가 없습니다."; +"widget_integration_room_not_visible" = "방 %@이(가) 보이지 않습니다."; +// Share extension +"share_extension_auth_prompt" = "내용을 공유하려면 기본 앱에 로그인"; +"share_extension_failed_to_encrypt" = "보내기에 실패함. 기본 앱에서 이 방의 암호화 설정을 확인하세요"; +// Room key request dialog +"e2e_room_key_request_title" = "암호화 키 요청"; +"e2e_room_key_request_message_new_device" = "암호화 키를 요청한 새 기기 '%@'을(를) 추가했습니다."; +"e2e_room_key_request_message" = "확인하지 않은 기기 '%@'이(가) 암호화 키를 요청하고 있습니다."; +"e2e_room_key_request_start_verification" = "확인 시작..."; +"e2e_room_key_request_share_without_verifying" = "확인없이 공유"; +"e2e_room_key_request_ignore_request" = "요청 무시"; +// GDPR +"gdpr_consent_not_given_alert_message" = "%@ 홈서버를 계속 사용하려면 이용 약관을 검토하고 수락해야 합니다."; +"gdpr_consent_not_given_alert_review_now_action" = "지금 검토"; +// Service terms +"service_terms_modal_title" = "서비스 약관"; +"service_terms_modal_message" = "계속하려면 이 서비스 약관에 동의해야 합니다."; +"service_terms_modal_accept_button" = "수락"; +"service_terms_modal_description_for_identity_server" = "다른 사용자가 검색할 수 있음"; +"service_terms_modal_description_for_integration_manager" = "봇, 브릿지, 위젯과 스티커팩을 사용"; +"deactivate_account_title" = "계정 비활성화"; +"deactivate_account_informations_part1" = "이것으로 계정은 영구적으로 사용할 수 없게됩니다. 로그인할 수 없고 아무도 같은 사용자 ID로 로그인할 수 없게 돱니다. 참가한 모든 방에서 떠나게되고 계정 세부 사항도 ID 서버에서 지워집니다. "; +"deactivate_account_informations_part2_emphasize" = "이 행동은 돌이킬 수 없습니다."; +"deactivate_account_informations_part3" = "\n\n계정 비활성화하기 "; +"deactivate_account_informations_part4_emphasize" = "우리는 보낸 메시지는 기본적으로 지우지 않습니다. "; +"deactivate_account_informations_part5" = "메시지를 지우고 싶다면 아래 상자를 체크하시요\n\nMatrix에서 메시지 가시성은 이메일과 유사합니다. 메시지를 지운다는 것은 보낸 메시지를 더 이상 새로운 혹은 등록하지 않은 사용자와 공유하는 않는 다는 것입니다, 하지만 이미 이 메시지에 접근한 등록한 사용자라면 그 사본에 계속 접근할 수 있습니다."; +"deactivate_account_forget_messages_information_part1" = "계정을 비활성화하면 보낸 모든 메시지를 지워주세요 ("; +"deactivate_account_forget_messages_information_part2_emphasize" = "경고"; +"deactivate_account_forget_messages_information_part3" = ": 이것은 이후 사용자가 불완전한 대화를 보게 됩니다)"; +"deactivate_account_validate_action" = "계정 비활성화"; +"deactivate_account_password_alert_title" = "계정 비활성화"; +"deactivate_account_password_alert_message" = "계속하려면, 비밀번호를 입력해주세요"; +// Re-request confirmation dialog +"rerequest_keys_alert_title" = "요청을 보냈습니다"; +"rerequest_keys_alert_message" = "메시지를 해독해서 이 기기로 키를 보낼 수 있도록 Riot을 다른 기기에 설치해주세요."; +"key_backup_setup_title" = "키 백업"; +"key_backup_setup_skip_alert_title" = "확신합니까?"; +"key_backup_setup_skip_alert_message" = "로그아웃하거나 기기를 잃어버리면 보안 메시지를 잃게 됩니다."; +"key_backup_setup_skip_alert_skip_action" = "넘기기"; +"key_backup_setup_intro_title" = "절대 암호화된 메시지를 잃지 마세요"; +"key_backup_setup_intro_info" = "암호화된 방의 메시지는 종단간 암호화로 보호됩니다. 오직 당싱과 참가자만 키를 갖고 있어 메시지를 읽을 수 있습니다.\n\n키를 잃지 않도록 안전하게 백업하세요."; +"key_backup_setup_intro_setup_action_without_existing_backup" = "키 백업 시작"; +"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "이 기기를 키 백업에 연결"; +"key_backup_setup_intro_manual_export_info" = "(고급)"; +"key_backup_setup_intro_manual_export_action" = "수동으로 키 내보내기"; +"key_backup_setup_passphrase_title" = "백업을 암호로 보호하기"; +"key_backup_setup_passphrase_info" = "암호화된 키의 사본을 서버에 보관합니다. 암호로된 백업을 보호하며 안전하게 유지해줍니다.\n\n보안을 최대화하려면, 암호는 계정 비밀번호와 달라야 합니다."; +"key_backup_setup_passphrase_passphrase_title" = "입력"; +"key_backup_setup_passphrase_passphrase_placeholder" = "암호 입력"; +"key_backup_setup_passphrase_passphrase_valid" = "좋아요!"; +"key_backup_setup_passphrase_passphrase_invalid" = "단어를 추가해보세요"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "확인"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "암호 확인"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "좋아요!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "암호가 맞지 않습니다"; +"key_backup_setup_passphrase_set_passphrase_action" = "암호 설정"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "또는, 안전한 곳에 저장해 둘 복구 키로 백업을 보호합니다."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(고급) 복구 키로 설정"; +"key_backup_setup_success_title" = "성공!"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "키가 백업되었습니다.\n\n복구 키는 안전망입니다 - 이것으로 암호를 잊어버려도 암호화된 메시지에 접근할 수 있습니다.\n\n복구키를 비밀번호 관리자 (혹은 금고)같은 안전한 장소에 두세요."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "복구 키 저장"; +"key_backup_setup_success_from_passphrase_done_action" = "끝"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "키가 백업되었습니다.\n\n이 복구 키의 사본을 만들어 안전하게 보관하세요."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "복구 키"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "사본 만들기"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "사본을 만들었습니다"; +"key_backup_recover_title" = "보안 메시지"; +"key_backup_recover_invalid_passphrase_title" = "맞지 않는 복구 암호"; +"key_backup_recover_invalid_passphrase" = "이 암호로 백업을 해독할 수 없습니다: 올바른 복구 암호를 입력해서 확인해주세요."; +"key_backup_recover_invalid_recovery_key_title" = "복구 키가 맞지 않음"; +"key_backup_recover_invalid_recovery_key" = "이 키로 백업을 해독할 수 없습니다: 올바른 복구 키를 입력해서 확인해주세요."; +"key_backup_recover_from_passphrase_info" = "복구 암호를 사용해 보안 메시지 기록을 푸세요"; +"key_backup_recover_from_passphrase_passphrase_title" = "입력"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "암호 입력"; +"key_backup_recover_from_passphrase_recover_action" = "기록 풀기"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "복구 암호가 기억나지 않나요? "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "복구 키를 사용하세요"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "복구 키를 사용해 보안 메시지 기록을 풉니다"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "입력"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "복구 키 입력"; +"key_backup_recover_from_recovery_key_recover_action" = "기록 풀기"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "복구 키를 잃어버렸나요? 설정에서 새 것을 설정할 수 있어요."; +"key_backup_recover_success_info" = "백업이 복구되었습니다!"; +"key_backup_recover_done_action" = "끝"; +"key_backup_setup_banner_title" = "절대 암호화된 메시지를 잃지 마세요"; +"key_backup_setup_banner_subtitle" = "키 백업 시작"; +"key_backup_recover_banner_title" = "절대 암호화된 메시지를 잃지 마세요"; +"key_backup_recover_connent_banner_subtitle" = "이 기기를 키 백업에 연결"; +"sign_out_existing_key_backup_alert_title" = "로그아웃하겠습니까?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "로그아웃"; +"sign_out_non_existing_key_backup_alert_title" = "지금 로그아웃하면 암호화된 메시지에 접근할 수 없게 됩니다"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "키 백업 시작"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "제 암호화된 메시지는 필요 없습니다"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "암호화된 메시지를 잃게 됩니다"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "로그아웃하기 전에 키를 백업하지 않으면 암호화된 메시지에 접근할 수 없게 됩니다."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "로그아웃"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "백업"; +"sign_out_key_backup_in_progress_alert_title" = "키 백업이 진행 중입니다. 지금 로그아웃하면 암호화된 메시지에 접근할 수 없게 됩니다."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "제 암호화된 메시지는 필요 없습니다"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "기다릴게요"; +// MARK: - Device Verification +"device_verification_title" = "기기 확인"; +"device_verification_security_advice" = "보안을 최대화하려면, 직접 또는 다른 신뢰할만한 통신 수단으로 확인하기를 추천합니다"; +"device_verification_cancelled" = "상대방이 확인을 취소했습니다."; +"device_verification_cancelled_by_me" = "확인이 취소됬습니다. 이유: %@"; +"device_verification_error_cannot_load_device" = "기기 정보를 불러올 수 없습니다."; +// Mark: Incoming +"device_verification_incoming_title" = "오는 확인 요청"; +"device_verification_incoming_description_1" = "이 기기를 신뢰하도록 확인합니다. 상대방의 신뢰하는 기기는 종단간 암호화된 메시지를 사용할 때 더 마음에 안심을 줍니다."; +"device_verification_incoming_description_2" = "이 기기를 신뢰하도록 확인합니다, 그리고 상대방도 당신의 기기를 신뢰하도록 합니다."; +// MARK: Start +"device_verification_start_title" = "짧은 문장을 비교하여 확인"; +"device_verification_start_wait_partner" = "상대방이 수락하기를 기다리는 중..."; +"device_verification_start_use_legacy" = "아무것도 안 나타나나요? 일부 클라이언트는 아직 상호작용 확인을 지원하지 않습니다. 예전 확인 방식을 사용하세요."; +"device_verification_start_verify_button" = "확인 시작"; +"device_verification_start_use_legacy_action" = "예전 확인 방식 사용"; +// MARK: Verify +"device_verification_verify_title_emoji" = "상대방의 화면에 나타나는 다음 이모지를 확인하는 것으로 이 기기를 확인합니다"; +"device_verification_verify_title_number" = "상대방의 화면에 나타나는 다음 숫자를 확인하는 것으로 이 기기를 확인합니다"; +"device_verification_verify_wait_partner" = "상대방이 확인하기를 기다리는 중..."; +// MARK: Verified +"device_verification_verified_title" = "확인되었습니다!"; +"device_verification_verified_description_1" = "성공적으로 이 기기를 확인했습니다."; +"device_verification_verified_description_2" = "이 사용자와의 보안 메시지는 종단간 암호화되며 제 3자가 읽을 수 없습니다."; +"device_verification_verified_got_it_button" = "알겠습니다"; +// MARK: Emoji +"device_verification_emoji_dog" = "개"; +"device_verification_emoji_cat" = "고양이"; +"device_verification_emoji_lion" = "사자"; +"device_verification_emoji_horse" = "말"; +"device_verification_emoji_unicorn" = "유니콘"; +"device_verification_emoji_pig" = "돼지"; +"device_verification_emoji_elephant" = "코끼리"; +"device_verification_emoji_rabbit" = "토끼"; +"device_verification_emoji_panda" = "판다"; +"device_verification_emoji_rooster" = "수탉"; +"device_verification_emoji_penguin" = "펭귄"; +"device_verification_emoji_turtle" = "거북"; +"device_verification_emoji_fish" = "물고기"; +"device_verification_emoji_octopus" = "문어"; +"device_verification_emoji_butterfly" = "나비"; +"device_verification_emoji_flower" = "꽃"; +"device_verification_emoji_tree" = "나무"; +"device_verification_emoji_cactus" = "선인장"; +"device_verification_emoji_mushroom" = "버섯"; +"device_verification_emoji_globe" = "지구본"; +"device_verification_emoji_moon" = "달"; +"device_verification_emoji_cloud" = "구름"; +"device_verification_emoji_fire" = "불"; +"device_verification_emoji_banana" = "바나나"; +"device_verification_emoji_apple" = "사과"; +"device_verification_emoji_strawberry" = "딸기"; +"device_verification_emoji_corn" = "옥수수"; +"device_verification_emoji_pizza" = "피자"; +"device_verification_emoji_cake" = "케이크"; +"device_verification_emoji_heart" = "하트"; +"device_verification_emoji_smiley" = "웃음"; +"device_verification_emoji_robot" = "로봇"; +"device_verification_emoji_hat" = "모자"; +"device_verification_emoji_glasses" = "안경"; +"device_verification_emoji_spanner" = "스패너"; +"device_verification_emoji_santa" = "산타클로스"; +"device_verification_emoji_thumbs up" = "좋아요"; +"device_verification_emoji_umbrella" = "우산"; +"device_verification_emoji_hourglass" = "모래시계"; +"device_verification_emoji_clock" = "시계"; +"device_verification_emoji_gift" = "선물"; +"device_verification_emoji_light bulb" = "전구"; +"device_verification_emoji_book" = "책"; +"device_verification_emoji_pencil" = "연필"; +"device_verification_emoji_paperclip" = "클립"; +"device_verification_emoji_scissors" = "가위"; +"device_verification_emoji_lock" = "자물쇠"; +"device_verification_emoji_key" = "열쇠"; +"device_verification_emoji_hammer" = "망치"; +"device_verification_emoji_telephone" = "전화기"; +"device_verification_emoji_flag" = "깃발"; +"device_verification_emoji_train" = "기차"; +"device_verification_emoji_bicycle" = "자전거"; +"device_verification_emoji_aeroplane" = "비행기"; +"device_verification_emoji_rocket" = "로켓"; +"device_verification_emoji_trophy" = "트로피"; +"device_verification_emoji_ball" = "공"; +"device_verification_emoji_guitar" = "기타"; +"device_verification_emoji_trumpet" = "트럼펫"; +"device_verification_emoji_bell" = "종"; +"device_verification_emoji_anchor" = "닻"; +"device_verification_emoji_headphones" = "헤드폰"; +"device_verification_emoji_folder" = "폴더"; +"device_verification_emoji_pin" = "핀"; +// MARK: File upload +"file_upload_error_title" = "파일 업로드"; +"file_upload_error_unsupported_file_type_message" = "파일 형식을 지원하지 않습니다."; +// MARK: Emoji picker +"emoji_picker_title" = "리액션"; +"emoji_picker_people_category" = "표정 & 사람"; +"emoji_picker_nature_category" = "동물 & 자연"; +"emoji_picker_foods_category" = "음식 & 음료"; +"emoji_picker_activity_category" = "액티비티"; +"emoji_picker_places_category" = "여행 & 명소"; +"emoji_picker_objects_category" = "물건"; +"emoji_picker_symbols_category" = "기호"; +"emoji_picker_flags_category" = "깃발"; +// MARK: Reaction history +"reaction_history_title" = "리액션"; diff --git a/Riot/Assets/nl.lproj/InfoPlist.strings b/Riot/Assets/nl.lproj/InfoPlist.strings index 2f756c814..00a680698 100644 --- a/Riot/Assets/nl.lproj/InfoPlist.strings +++ b/Riot/Assets/nl.lproj/InfoPlist.strings @@ -19,3 +19,4 @@ "NSPhotoLibraryUsageDescription" = "De fotogalerij wordt gebruikt om foto’s en video’s te versturen."; "NSMicrophoneUsageDescription" = "De microfoon wordt gebruikt om video’s te maken, en voor spraakoproepen."; "NSContactsUsageDescription" = "Om u te kunnen tonen welke van uw contacten reeds Riot of Matrix gebruiken, kunnen we de e-mailadressen en telefoonnummers in uw adresboek naar uw Matrix-identiteitsserver sturen. New Vector bewaart deze gegevens niet en gebruikt ze niet voor andere doeleinden. Bekijk voor meer informatie de privacybeleidspagina in de instellingen van de app."; +"NSCalendarsUsageDescription" = "Bekijk uw geplande afspraken in de app."; diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 8a6aca06a..168ef66fa 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -24,7 +24,7 @@ "view" = "Weergeven"; "next" = "Volgende"; "back" = "Terug"; -"continue" = "Verder gaan"; +"continue" = "Verdergaan"; "create" = "Aanmaken"; "start" = "Starten"; "leave" = "Verlaten"; @@ -42,8 +42,8 @@ "camera" = "Camera"; "voice" = "Spraak"; "video" = "Video"; -"active_call" = "Actieve oproep"; -"active_call_details" = "Actieve oproep (%@)"; +"active_call" = "Oproep actief"; +"active_call_details" = "Oproep actief (%@)"; "later" = "Later"; "rename" = "Hernoemen"; // Authentication @@ -64,7 +64,7 @@ "auth_repeat_password_placeholder" = "Wachtwoord herhalen"; "auth_repeat_new_password_placeholder" = "Bevestig uw nieuwe wachtwoord"; "auth_invalid_login_param" = "Onjuiste gebruikersnaam en/of wachtwoord"; -"auth_invalid_user_name" = "Gebruikersnamen mogen alleen letters, cijfers, punten, afbreek- en lage streepjes bevatten"; +"auth_invalid_user_name" = "Gebruikersnamen mogen alleen letters, cijfers, punten, koppeltekens en underscores bevatten"; "auth_invalid_password" = "Het wachtwoord is te kort (min 6)"; "auth_invalid_email" = "Dit ziet er niet uit als een geldig e-mailadres"; "auth_invalid_phone" = "Dit ziet er niet uit als een geldig telefoonnummer"; @@ -829,3 +829,12 @@ "emoji_picker_flags_category" = "Vlaggen"; // MARK: Reaction history "reaction_history_title" = "Reacties"; +"auth_forgot_password_error_no_configured_identity_server" = "Er is geen identiteitsserver geconfigureerd: voeg er een toe om uw wachtwoord opnieuw in te stellen."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen deelnemers toevoegen via e-mail."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen gesprek beginnen met een contact via e-mail."; +// Service terms +"service_terms_modal_title" = "Dienstvoorwaarden"; +"service_terms_modal_message" = "Om door te gaan dient u de dienstvoorwaarden te aanvaarden."; +"service_terms_modal_accept_button" = "Aanvaarden"; +"service_terms_modal_description_for_identity_server" = "Wees vindbaar voor anderen"; +"service_terms_modal_description_for_integration_manager" = "Gebruik bots, bruggen, widgets en stickerpakketten"; diff --git a/Riot/Assets/pl.lproj/InfoPlist.strings b/Riot/Assets/pl.lproj/InfoPlist.strings index 2a477de54..c09415e82 100644 --- a/Riot/Assets/pl.lproj/InfoPlist.strings +++ b/Riot/Assets/pl.lproj/InfoPlist.strings @@ -2,3 +2,5 @@ "NSCameraUsageDescription" = "Aparat służy do robienia zdjęć i nagrywania filmów, prowadzenia rozmów wideo."; "NSPhotoLibraryUsageDescription" = "Biblioteka zdjęć służy do wysyłania zdjęć i filmów."; "NSMicrophoneUsageDescription" = "Mikrofon służy do robienia filmów, wykonywania połączeń."; +"NSContactsUsageDescription" = "Możemy pokazać Ci, które z Twoich kontaktów korzystają aktualnie z Riot, bądź Matrix. Możemy wysyłać adresy e-mail i numery telefonów z Twojej książki adresowej na Twój serwer Matrix. New Vector nie przechowuje Twoich danych, ani nie wykorzystuje ich w żadnym celu. Aby uzyskać dodatkowe informacje zajrzyj do zakładki \"polityka prywatności\" w ustawieniach aplikacji."; +"NSCalendarsUsageDescription" = "Zobacz swoje zaplanowane spotkania w aplikacji."; diff --git a/Riot/Assets/pl.lproj/Localizable.strings b/Riot/Assets/pl.lproj/Localizable.strings index 77a3fa5b0..756df1ce4 100644 --- a/Riot/Assets/pl.lproj/Localizable.strings +++ b/Riot/Assets/pl.lproj/Localizable.strings @@ -1,5 +1,5 @@ /* New message from a specific person, not referencing a room */ -"MSG_FROM_USER" = "Wiadomość od %@"; +"MSG_FROM_USER" = "%@ wysłał(a) wiadomość"; /* New message from a specific person, not referencing a room. Content included. */ "MSG_FROM_USER_WITH_CONTENT" = "%@: %@"; /* New message from a specific person in a named room. Content included. */ @@ -23,9 +23,9 @@ /* Look, stuff's happened, alright? Just open the app. */ "MSGS_IN_TWO_PLUS_ROOMS" = "%@ nowych wiadomości w %@, %@ i innych"; /* New action message from a specific person, not referencing a room. */ -"IMAGE_FROM_USER" = "%@ wysłał(a) Tobie zdjęcie %@"; +"IMAGE_FROM_USER" = "%@ wysłał(a) zdjęcie %@"; /* New action message from a specific person in a named room. */ -"IMAGE_FROM_USER_IN_ROOM" = "%@ wysłał(a) Tobie zdjęcie %@ w %@"; +"IMAGE_FROM_USER_IN_ROOM" = "%@ wysłał(a) zdjęcie %@ w %@"; /* Multiple unread messages from a specific person, not referencing a room */ "MSGS_FROM_USER" = "%@ nowych wiadomości w %@"; /* Multiple messages in two rooms */ @@ -36,3 +36,21 @@ "USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ zaprosił(a) Ciebie do rozmowy grupowej"; /* A user has invited you to a chat */ "USER_INVITE_TO_CHAT" = "%@ zaprosił(a) Ciebie do rozmowy"; +/* Message title for a specific person in a named room */ +"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ w %@"; +/* New message from a specific person in a named room */ +"MSG_FROM_USER_IN_ROOM" = "%@ opublikowany w %@"; +/* Sticker from a specific person, not referencing a room. */ +"STICKER_FROM_USER" = "%@ wysłał(a) naklejkę"; +/* Incoming one-to-one voice call */ +"VOICE_CALL_FROM_USER" = "Zadzwonił do Ciebie z %@"; +/* Incoming one-to-one video call */ +"VIDEO_CALL_FROM_USER" = "Połączenie wideo z %@"; +/* Incoming unnamed voice conference invite from a specific person */ +"VOICE_CONF_FROM_USER" = "Połączenie grupowe z %@"; +/* Incoming unnamed video conference invite from a specific person */ +"VIDEO_CONF_FROM_USER" = "Grupowe połączenie wideo z %@"; +/* Incoming named voice conference invite from a specific person */ +"VOICE_CONF_NAMED_FROM_USER" = "Połączenie grupowe z %@: '%@'"; +/* Incoming named video conference invite from a specific person */ +"VIDEO_CONF_NAMED_FROM_USER" = "Grupowe połączenie wideo z %@: '%@'"; diff --git a/Riot/Assets/pl.lproj/Vector.strings b/Riot/Assets/pl.lproj/Vector.strings index 1125c4dff..e6d549766 100644 --- a/Riot/Assets/pl.lproj/Vector.strings +++ b/Riot/Assets/pl.lproj/Vector.strings @@ -526,3 +526,259 @@ "settings_key_backup_info_progress_done" = "Utworzono kopię zapasową wszystkich kluczy"; "settings_key_backup_button_delete" = "Usuń kopię zapasową"; "settings_key_backup_delete_confirmation_prompt_title" = "Usuń kopię zapasową"; +"auth_login_single_sign_on" = "Zaloguj się za pomocą pojedynczego logowania"; +"auth_autodiscover_invalid_response" = "Nieprawidłowa odpowiedź na wykrycie serwera domowego"; +"settings_key_backup_button_create" = "Rozpocznij z użyciem klucza kopii zapasowej"; +"settings_key_backup_button_restore" = "Przywróć z kopii zapasowej"; +"room_details_fail_to_update_avatar" = "Nie udało się zaaktualizować zdjęcia pokoju"; +"room_details_fail_to_update_room_name" = "Nie udało się zaaktualizować nazwy pokoju"; +"room_details_fail_to_update_topic" = "Nie udało się zaaktualizować tematu"; +"room_details_fail_to_update_room_guest_access" = "Nie udało się zaaktualizować dostępu gościa do pokoju"; +"room_details_fail_to_update_room_join_rule" = "Nie udało się zaaktualizować reguły dołączania"; +"room_details_fail_to_update_room_directory_visibility" = "Nie udało się zaaktualizować widoczności pokoju"; +"room_details_fail_to_update_history_visibility" = "Nie udało się zaaktualizować historii widoczności"; +"room_details_fail_to_add_room_aliases" = "Nie udało się dodać nowych adresów pokoi"; +"room_details_fail_to_remove_room_aliases" = "Nie udało się usunąć adresów pokoi"; +"room_details_fail_to_update_room_canonical_alias" = "Nie udało się zaaktualizować głównego adresu pokoju"; +"room_details_fail_to_update_room_communities" = "Nie udało się zaaktualizować powiązanych społeczności"; +"room_details_fail_to_update_room_direct" = "Nie udało się zaaktualizować flagi tego pokoju"; +"room_details_fail_to_enable_encryption" = "Nie udało się włączyć szyfrowania w tym pokoju"; +"group_details_home" = "Strona domowa"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Zacznij korzystać z klucza bezpieczeństwa"; +"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Podłącz to urządzenie do klucza bezpieczeństwa"; +"key_backup_setup_intro_manual_export_info" = "(Zaawansowany)"; +"key_backup_setup_intro_manual_export_action" = "Ręcznie eksportuj klucze"; +"key_backup_setup_passphrase_title" = "Zabezpiecz swoją kopię zapasową hasłem"; +"key_backup_setup_passphrase_info" = "Będziemy przechowywać zaszyfrowaną kopię Twoich kluczy na naszym serwerze. Zabezpiecz swoją kopię zapasową przy pomocy hasła, aby zapewnić jej bezpieczeństwo.\n\nDla maksymalnego bezpieczeństwa - to powinno być inne hasło, niż hasło do konta."; +"key_backup_setup_passphrase_passphrase_title" = "Wejdź"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Wprowadź hasło"; +"key_backup_setup_passphrase_passphrase_valid" = "Świetnie!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Spróbuj dodać słowo"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Potwierdź"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Potwierdź hasło"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Świetnie!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Hasło nie pasuje"; +"key_backup_setup_passphrase_set_passphrase_action" = "Ustaw hasło"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Możesz też zabezpieczyć kopię zapasową przy pomocy klucza odzyskiwania, zapisując ją w bezpiecznym miejscu."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Zaawansowany) Konfiguruj za pomocą klucza odzyskiwania"; +"key_backup_setup_success_title" = "Sukces!"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Tworzone są kopie zapasowe kluczy.\n\nTwój klucz odzyskiwania to gwarant bezpieczeństwa - możesz użyć go, aby odzyskać dostęp do zaszyfrowanych wiadomości, jeśli zapomnisz hasła.\n\nTrzymaj ten klucz w bezpiecznym miejscu (np. w menedżerze haseł)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Zapisz klucz odzyskiwania"; +"key_backup_setup_success_from_passphrase_done_action" = "Zrobione"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Tworzone są kopie zapasowe kluczy.\n\nZrób kopię tego klucza i przechowuj ją w bezpiecznym miejscu."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Klucz odzyskiwania"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Zrób kopię"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Zrobiłem kopię"; +"key_backup_recover_title" = "Bezpieczne wiadomości"; +"key_backup_recover_invalid_passphrase_title" = "Niepoprawne hasło odzyskiwania"; +"key_backup_recover_invalid_passphrase" = "Nie można odszyfrować kopii zapasowej przy użyciu tego hasła: Proszę, sprawdź czy wprowadziłeś(aś) prawidłowe hasło odzyskiwania."; +"key_backup_recover_invalid_recovery_key_title" = "Klucz odzyskiwania nie pasuje"; +"key_backup_recover_invalid_recovery_key" = "Nie można odszyfrować kopii zapasowej przy użycia tego klucza: Proszę, sprawdź czy wpisałeś go poprawnie."; +"key_backup_recover_from_passphrase_info" = "Skorzystaj ze swojego hasła odzyskiwania, aby odblokować historię bezpiecznych wiadomości"; +"key_backup_recover_from_passphrase_passphrase_title" = "Wejdź"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Wprowadź hasło"; +"key_backup_recover_from_passphrase_recover_action" = "Odblokuj historię"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Nie znasz hasła odzyskiwania? Możesz "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "Użyj swojego klucza odzyskiwania"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Skorzystaj z klucza odzyskiwania, aby odblokować historię bezpiecznych wiadomości"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Wejdź"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Wpisz klucz odzyskiwania"; +"key_backup_recover_from_recovery_key_recover_action" = "Odblokuj historię"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Zgubiłeś swój klucz odzyskiwania? Możesz ustawić nowy w ustawieniach."; +"key_backup_recover_success_info" = "Kopia zapasowa została przywrócona!"; +"key_backup_recover_done_action" = "Zrobiono"; +"key_backup_setup_banner_title" = "Nigdy nie trać zaszyfrowanych wiadomości"; +"key_backup_setup_banner_subtitle" = "Zacznij korzystać z kopii zapasowej"; +"key_backup_recover_banner_title" = "Nigdy nie trać zaszyfrowanych wiadomości"; +"key_backup_recover_connent_banner_subtitle" = "Podłącz to urządzenie do kopii zapasowej"; +"sign_out_existing_key_backup_alert_title" = "Jesteś pewien, że chcesz się wylogować?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Wyloguj się"; +"sign_out_non_existing_key_backup_alert_title" = "Jeśli wylogujesz się teraz, stracisz dostęp do swoich zaszyfrowanych wiadomości"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Zacznij korzystać z kopii zapasowej"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Nie chcę swoich zaszyfrowanych wiadomości"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Utracisz zaszyfrowane wiadomości"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Utracisz dostęp do zaszyfrowanych wiadomości, jeżeli wylogujesz się przed utworzeniem kopii zapasowej."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Wylogowanie"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Kopia zapasowa"; +"sign_out_key_backup_in_progress_alert_title" = "Trwa tworzenie kopii zapasowej. Jeżeli wylogujesz się teraz - Stracisz dostęp do swoich zaszyfrowanych wiadomości."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Nie chcę moich zaszyfrowanych wiadomości"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Poczekam"; +// MARK: - Device Verification +"device_verification_title" = "Zweryfikuj urządzenie"; +"device_verification_security_advice" = "Dla zapewnienia maksymalnego bezpieczeństwa zalecamy zrobienie tego samemu, bądź skorzystanie z innego, zaufanego środka komunikacji"; +"device_verification_cancelled" = "Druga strona przerwała weryfikację."; +"device_verification_cancelled_by_me" = "Weryfikacja została przerwana. Powód: %@"; +"device_verification_error_cannot_load_device" = "Nie można załadować informacji o urządzeniu."; +// Mark: Incoming +"device_verification_incoming_title" = "Przyszła prośba o weryfikację"; +"device_verification_incoming_description_1" = "Zweryfikuj to urządzenie, aby oznaczyć je jako zaufane. Zaufane urządzenia dają Twoim rozmówcom dodatkowe poczucie spokoju, podczas konwersacji z włączonymi szyfrowanymi wiadomościami end-to-end."; +"device_verification_incoming_description_2" = "Weryfikacja tego urządzenia spowoduje oznaczenie go, jako zaufanego. Zostanie ono oznaczone jako zaufane również na urządzeniu Twojego rozmówcy."; +// MARK: Start +"device_verification_start_title" = "Zweryfikuj, porównując krótki tekst"; +"device_verification_start_wait_partner" = "Oczekiwanie na zaakceptowanie przez rozmówce..."; +"device_verification_start_use_legacy" = "Nic się nie pojawiło? Nie wszystkie wersje aplikacji obsługują jeszcze interaktywną weryfikację. Prosimy o skorzystanie ze starszej wersji."; +"device_verification_start_verify_button" = "Rozpocznij weryfikację"; +"device_verification_start_use_legacy_action" = "Użyj starszej wersji weryfikacji"; +// MARK: Verify +"device_verification_verify_title_emoji" = "Sprawdź to urządzenie potwierdzając, że następujące emotikony pojawiają się na ekranie rozmówcy"; +"device_verification_verify_title_number" = "Sprawdź to urządzenie potwierdzając, że następujące liczby pojawiają się na ekranie rozmówcy"; +"device_verification_verify_wait_partner" = "Oczekiwanie na rozmówce w celu potwierdzenia..."; +// MARK: Verified +"device_verification_verified_title" = "Zweryfikowano!"; +"device_verification_verified_description_1" = "Pomyślnie zweryfikowano to urządzenie."; +"device_verification_verified_description_2" = "Bezpieczne wiadomości z tym użytkownikiem są szyfrowane metodą end-to-end i nie mogą zostać odczytane przez osoby trzecie."; +"device_verification_verified_got_it_button" = "Zrobione"; +// MARK: Emoji +"device_verification_emoji_dog" = "Pies"; +"device_verification_emoji_cat" = "Kot"; +"device_verification_emoji_lion" = "Lew"; +"device_verification_emoji_horse" = "Koń"; +"device_verification_emoji_unicorn" = "Jednorożec"; +"device_verification_emoji_pig" = "Świnia"; +"device_verification_emoji_elephant" = "Słoń"; +"device_verification_emoji_rabbit" = "Królik"; +"device_verification_emoji_panda" = "Panda"; +"device_verification_emoji_rooster" = "Kogut"; +"device_verification_emoji_penguin" = "Pingwin"; +"device_verification_emoji_turtle" = "Żółw"; +"device_verification_emoji_fish" = "Ryba"; +"device_verification_emoji_octopus" = "Ośmiornica"; +"device_verification_emoji_butterfly" = "Motyl"; +"device_verification_emoji_flower" = "Kwiatek"; +"device_verification_emoji_tree" = "Drzewo"; +"device_verification_emoji_cactus" = "Kaktus"; +"device_verification_emoji_mushroom" = "Grzyb"; +"device_verification_emoji_globe" = "Kula ziemska"; +"device_verification_emoji_moon" = "Księżyc"; +"device_verification_emoji_cloud" = "Chmura"; +"device_verification_emoji_fire" = "Ogień"; +"device_verification_emoji_banana" = "Banan"; +"device_verification_emoji_apple" = "Jabłko"; +"device_verification_emoji_strawberry" = "Truskawka"; +"device_verification_emoji_corn" = "Kukurydza"; +"device_verification_emoji_pizza" = "Pizza"; +"device_verification_emoji_cake" = "Ciasto"; +"device_verification_emoji_heart" = "Serce"; +"device_verification_emoji_smiley" = "Uśmiech"; +"device_verification_emoji_robot" = "Robot"; +"device_verification_emoji_hat" = "Kapelusz"; +"device_verification_emoji_glasses" = "Okulary"; +"device_verification_emoji_spanner" = "Klucz"; +"device_verification_emoji_santa" = "Mikołaj"; +"device_verification_emoji_thumbs up" = "Kciuk w górę"; +"device_verification_emoji_umbrella" = "Parasolka"; +"device_verification_emoji_hourglass" = "Klepsydra"; +"device_verification_emoji_clock" = "Zegar"; +"device_verification_emoji_gift" = "Prezent"; +"device_verification_emoji_light bulb" = "Żarówka"; +"device_verification_emoji_book" = "Książka"; +"device_verification_emoji_pencil" = "Ołówek"; +"device_verification_emoji_paperclip" = "Spinacz"; +"device_verification_emoji_scissors" = "Nożyczki"; +"device_verification_emoji_lock" = "Zamek"; +"device_verification_emoji_key" = "Klucz"; +"device_verification_emoji_hammer" = "Młotek"; +"device_verification_emoji_telephone" = "Telefon"; +"device_verification_emoji_flag" = "Flaga"; +"device_verification_emoji_train" = "Pociąg"; +"device_verification_emoji_bicycle" = "Rower"; +"device_verification_emoji_aeroplane" = "Samolot"; +"device_verification_emoji_rocket" = "Rakieta"; +"device_verification_emoji_trophy" = "Trofeum"; +"device_verification_emoji_ball" = "Piłka"; +"device_verification_emoji_guitar" = "Gitara"; +"device_verification_emoji_trumpet" = "Trąbka"; +"device_verification_emoji_bell" = "Dzwon"; +"device_verification_emoji_anchor" = "Kotwica"; +"device_verification_emoji_headphones" = "Słuchawki"; +"device_verification_emoji_folder" = "Folder"; +"device_verification_emoji_pin" = "Przypnij"; +// MARK: File upload +"file_upload_error_title" = "Wyślij plik"; +"file_upload_error_unsupported_file_type_message" = "Typ pliku nie jest wspierany."; +// MARK: Emoji picker +"emoji_picker_title" = "Reakcje"; +"emoji_picker_people_category" = "Emotikony i ludzie"; +"emoji_picker_nature_category" = "Zwierzęta i przyroda"; +"emoji_picker_foods_category" = "Jedzenie i picie"; +"emoji_picker_activity_category" = "Aktywności"; +"emoji_picker_places_category" = "Podróże i miejsca"; +"emoji_picker_objects_category" = "Obiekty"; +"emoji_picker_symbols_category" = "Symbole"; +"emoji_picker_flags_category" = "Flagi"; +// MARK: Reaction history +"reaction_history_title" = "Reakcje"; +"auth_forgot_password_error_no_configured_identity_server" = "Brak skonfigurowanego serwera tożsamości: dodaj serwer tożsamości, aby zresetować hasło."; +"auth_softlogout_signed_out" = "Zostałeś wylogowany"; +"auth_softlogout_reason" = "Administrator serwera domowego (%1$@) wylogował Cię z Twojego konta %2$@ (%3$@)."; +"auth_softlogout_recover_encryption_keys" = "Zaloguj się aby odzyskać klucze szyfrujące zapisane na tym urządzeniu. Potrzebujesz ich aby odczytać wszystkie swoje zaszyfrowane wiadomości na którymkolwiek z Twoich urządzeń."; +"auth_softlogout_clear_data" = "Wyczyść prywatne dane"; +"auth_softlogout_clear_data_message_1" = "Uwaga: Twoje prywatne dane (z uwzględnieniem kluczy szyfrujących) nadal znajdują się na tym urządzeniu."; +"auth_softlogout_clear_data_message_2" = "Wyczyść je, jeżeli nie będziesz już używać tego urządzenia, lub jeśli planujesz zalogować się na inne konto."; +"auth_softlogout_clear_data_sign_out_title" = "Czy jesteś pewien?"; +"auth_softlogout_clear_data_sign_out_msg" = "Czy napewno chcesz wyczyścić wszystkie dane znajdujące się na tym urządzeniu? Zaloguj się ponownie, aby mieć dostęp do swojego konta, oraz wiadomości."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Serwer tożsamości nie został skonfigurowany, więc nie możesz dodać uczestnika przy użyciu adresu email."; +"room_participants_remove_third_party_invite_msg" = "Usuwanie zaproszeń nie jest wspierane przez obecną wersję API"; +"room_participants_invited_section" = "ZAPROSZENI"; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Serwer tożsamości nie został skonfigurowany, więc nie możesz rozpocząć rozmowy używając adresu email."; +"room_message_unable_open_link_error_message" = "Nie udało się otworzyć adresu."; +"room_conference_call_no_power" = "Nie masz uprawnień aby zarządzać konferencjami w tym pokoju."; +"room_event_action_reaction_history" = "Historia reakcji"; +"room_action_camera" = "Zrób zdjęcie lub nagraj wideo"; +"settings_config_no_build_info" = "Brak informacji o buildzie"; +"settings_labs_message_reaction" = "Odpowiadaj na wiadomości używając emoji"; +"settings_key_backup_info" = "Zaszyfrowane wiadomości są zabezpieczone przy użyciu szyfrowania end-to-end. Tylko Ty oraz ich adresaci posiadają klucze do ich rozszyfrowania."; +"settings_key_backup_info_none" = "Twoje klucze z tego urządzenia nie posiadają kopii zapasowej."; +"settings_key_backup_info_signout_warning" = "Utwórz kopię zapasową kluczy przed wylogowaniem się aby uniknąć ich utraty."; +"settings_key_backup_info_valid" = "Kopia zapasowa twoich kluczy jest tworzona."; +"settings_key_backup_info_trust_signature_unknown" = "Kopia zapasowa posiada podpis urządzenia o ID: %@"; +"settings_key_backup_info_trust_signature_valid" = "Kopia zapasowa posiada prawidłowy podpis tego urządzenia"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Kopia zapasowa posiada prawidłowy podpis urządzenia %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Kopia zapasowa posiada podpis urządzenia %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Kopia zapasowa posiada nieprawidłowy podpis urządzenia %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Kopia zapasowa posiada nieprawidłowy podpis urządzenia %@"; +"settings_key_backup_button_connect" = "Podłącz to urządzenie do kopii zapasowej kluczy"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Czy jesteś pewien? Stracisz dostęp do wszystkich swoich zaszyfrowanych wiadomości, jeżeli nie utworzyłeś poprawnej kopii zapasowej kluczy."; +"room_details_access_section" = "Kto może dołączyć do pokoju?"; +"room_details_history_section_prompt_msg" = "Zmiany dostępu do historii będą miały zastosowanie tylko do przyszłych wiadomości w tym pokoju. Widoczność obecnych wiadomości pozostanie bez zmian."; +"settings_key_backup_info_not_valid" = "To urządzenie nie tworzy kopii zapasowej Twoich kluczy. Ciągle jednak masz istniejącą kopię zapasową, którą możesz przywrócić i w przyszłości uzupełnić."; +"room_details_addresses_disable_main_address_prompt_title" = "Główny adres ostrzega"; +"room_details_addresses_disable_main_address_prompt_msg" = "Nie masz adresu głównego. Domyślny główny adres zostanie wybrany losowo"; +"room_details_flair_section" = "Pokaż talent społecznościom"; +"room_details_flair_invalid_id_prompt_msg" = "%@ nie jest prawidłowym identyfikatorem społeczności"; +"group_participants_leave_prompt_msg" = "Czy jesteś pewien, że chcesz opuścić te grupę?"; +"group_participants_remove_prompt_msg" = "Czy jesteś pewien, że chcesz usunąć %@ z tej grupy?"; +"group_participants_invite_prompt_msg" = "Czy jesteś pewien, że chcesz zaprosić %@ do tej grupy?"; +"group_participants_invite_malformed_id_title" = "Błąd. Nie udało się zaprosić"; +"group_participants_invited_section" = "ZAPROSZONY"; +"receipt_status_read" = "Czytaj: "; +// Media picker +"media_picker_title" = "Selektor mediów"; +// Image picker +"image_picker_action_camera" = "Zrób zdjęcie"; +"image_picker_action_library" = "Wybierz z biblioteki"; +"directory_server_all_native_rooms" = "Wszystkie rodzime pokoje Matrix"; +// Events formatter +"event_formatter_member_updates" = "%tu zmiany członkostwa"; +"event_formatter_jitsi_widget_added" = "Konferencja VoIP dodana przez %@"; +"event_formatter_jitsi_widget_removed" = "Konferencja VoIP usunięta przez %@"; +"event_formatter_message_edited_mention" = "(edytowano)"; +"network_offline_prompt" = "Wygląda na to, że nie masz połączenia z internetem."; +"homeserver_connection_lost" = "Nie można połączyć się z serwerem domowym."; +"public_room_section_title" = "Pokoje Publiczne (na %@):"; +"bug_report_prompt" = "Poprzednio aplikacja uległa awarii. Czy chcesz wysłać raport?"; +"rage_shake_prompt" = "Zauważyliśmy, że potrząsasz telefonem (czyżby ze zdenerwowania?). Chciałbyś nam zgłosić jakiś problem?"; +"camera_access_not_granted" = "%@ nie ma uprawnień do korzystania z aparatu, zmień ustawienia w ustawieniach prywatności"; +"camera_unavailable" = "Aparat jest niedostępny na Twoim urządzeniu"; +"photo_library_access_not_granted" = "%@ nie ma uprawnień dostępu do biblioteki zdjęć, możesz to zmienić w ustawieniach prywatności"; +"room_does_not_exist" = "%@ nie istnieje"; +"call_already_displayed" = "Rozmowa tutaj już trwa."; +"call_jitsi_error" = "Nie udało się dołączyć do rozmowy konferencyjnej."; +"no_voip" = "%@ dzwoni do Ciebie ale %@ nie obsługuje jeszcze połączeń\nMożesz zignorować to powiadomienie i odebrać rozmowę na innym urządzeniu, bądź odrzucić je."; +// Crash report +"google_analytics_use_prompt" = "Chcesz pomóc nam w ulepszaniu %@ przez automatyczne wysyłanie anonimowych raportów o błędach i danych użytkowania?"; +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Nowy Klucz Kopii Zapasowej"; diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index 2bfa610c9..836c7716f 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -685,3 +685,4 @@ "room_action_reply" = "Ответ"; "settings_labs_message_reaction" = "Реагировать на сообщения с Emoji"; "settings_key_backup_button_connect" = "Подключите это устройство к ключу резервного копирования"; +"close" = "Закрыть"; diff --git a/Riot/Assets/sq.lproj/InfoPlist.strings b/Riot/Assets/sq.lproj/InfoPlist.strings index 680c8399d..158f1edc4 100644 --- a/Riot/Assets/sq.lproj/InfoPlist.strings +++ b/Riot/Assets/sq.lproj/InfoPlist.strings @@ -2,4 +2,5 @@ "NSCameraUsageDescription" = "Kamera përdoret për të bërë foto dhe regjistruar video, dhe për të bërë thirrje video."; "NSPhotoLibraryUsageDescription" = "Fototeka përdoret për të dërguar foto dhe video."; "NSMicrophoneUsageDescription" = "Mikrofoni përdoret për të regjistruar video, dhe për të bërë thirrje."; -"NSContactsUsageDescription" = "Që të mund t’ju shfaqim se cilët prej kontakteve tuaj përdorin tashmë Riot ose Matrix, mund të dërgojmë adresat email dhe numrat e telefonave nga libri juaj i adresave te Shërbyesi Matrix i Identiteteve. Vektori i ri nuk i depoziton këto të dhëna, as i përdor për ndonjë qëllim tjetër. Për më tepër të dhëna, shihni faqen e rregullave të privatësisë, te rregullimet e aplikacionit."; +"NSContactsUsageDescription" = "Që të mund t’ju shfaqim se cilët prej kontakteve tuaj përdorin tashmë Riot ose Matrix, mund të dërgojmë adresat email dhe numrat e telefonave nga libri juaj i adresave te shërbyesi Matrix i identiteteve. Vektori i ri nuk i depoziton këto të dhëna, as i përdor për ndonjë qëllim tjetër. Për më tepër të dhëna, shihni faqen e rregullave të privatësisë, te rregullimet e aplikacionit."; +"NSCalendarsUsageDescription" = "Shihini te aplikacioni takimet tuaja të planifikuara."; diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index f1ba0864e..f69a10297 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -746,7 +746,7 @@ "device_verification_emoji_santa" = "Babagjyshi i Vitit të Ri"; "device_verification_emoji_umbrella" = "Ombrellë"; "device_verification_emoji_hourglass" = "Klepsidër"; -"device_verification_emoji_clock" = "Klasë"; +"device_verification_emoji_clock" = "Orë"; "device_verification_emoji_gift" = "Dhuratë"; "device_verification_emoji_light bulb" = "Llambë"; "device_verification_emoji_book" = "Libër"; @@ -770,7 +770,7 @@ "device_verification_emoji_anchor" = "Spirancë"; "device_verification_emoji_headphones" = "Kufje"; "device_verification_emoji_folder" = "Dosje"; -"event_formatter_message_edited_mention" = "(U përpunua)"; +"event_formatter_message_edited_mention" = "(u përpunua)"; // Widget "widget_no_integrations_server_configured" = "S’ka të formësuar shërbyes integrimesh"; "widget_integrations_server_failed_to_connect" = "S’u arrit të lidhej me shërbyes integrimesh"; @@ -778,3 +778,51 @@ "room_event_action_reaction_show_all" = "Shfaqi krejt"; "room_event_action_reaction_show_less" = "Shfaq më pak"; "room_message_edits_history_title" = "Përpunime mesazhi"; +"auth_softlogout_signed_out" = "Keni bërë dalje"; +"auth_softlogout_sign_in" = "Hyni"; +"auth_softlogout_reason" = "Përgjegjësi i shërbyesit tuaj Home (%1$@) ka bërë daljen tuaj nga llogaria juaj %2$@ (%3$@)."; +"auth_softlogout_recover_encryption_keys" = "Bëni hyrjen, që të rimerrni kyçe fshehtëzimi të depozituar përjashtimisht në këtë pajisje. Do t’ju duhen për të lexuar krejt mesazhet tuaj të siguruar në çfarëdo pajisje."; +"auth_softlogout_clear_data" = "Spastro të dhëna personale"; +"auth_softlogout_clear_data_message_1" = "Kujdes: Të dhënat tuaja personale (përfshi kyçe fshehtëzimi) janë ende të depozituara në këtë pajisje."; +"auth_softlogout_clear_data_message_2" = "Spastrojini, nëse keni përfunduar së përdoruri këtë pajisje, ose dëshironi të hyni në një llogari tjetër."; +"auth_softlogout_clear_data_button" = "Spastro krejt të dhënat"; +"auth_softlogout_clear_data_sign_out_title" = "Jeni i sigurt?"; +"auth_softlogout_clear_data_sign_out_msg" = "Jeni i sigurt se doni të spastrohen krejt të dhënat e depozituara në këtë pajisje? Që të mund të hyni te të dhëna të llogarisë tuaj dhe te mesazhe, bëni sërish hyrjen."; +"auth_softlogout_clear_data_sign_out" = "Dilni"; +"room_event_action_reaction_history" = "Historik reagimesh"; +"room_action_camera" = "Bëni foto ose video"; +"room_action_send_file" = "Dërgoni kartelë"; +// Media picker +"media_picker_title" = "Mediatekë"; +// Image picker +"image_picker_action_camera" = "Bëni një foto"; +"image_picker_action_library" = "Zgjidhni prej biblioteke"; +"camera_unavailable" = "Kamera në pajisjen tuaj s’është e përdorshme"; +"photo_library_access_not_granted" = "%@ s’ka leje të hyjë në fototekë, ju lutemi, ndryshoni rregullimet e privatësisë"; +"device_verification_emoji_spanner" = "Çelës"; +"device_verification_emoji_lock" = "Dry"; +"device_verification_emoji_pin" = "Fiksoje"; +// MARK: File upload +"file_upload_error_title" = "Ngarkim kartele"; +"file_upload_error_unsupported_file_type_message" = "Lloj i pambuluar kartele."; +// MARK: Emoji picker +"emoji_picker_title" = "Reagime"; +"emoji_picker_people_category" = "Emotikone & Njerëz"; +"emoji_picker_nature_category" = "Kafshë & Natyrë"; +"emoji_picker_foods_category" = "Ushqim & Pije"; +"emoji_picker_activity_category" = "Veprimtari"; +"emoji_picker_places_category" = "Udhëtim & Vende"; +"emoji_picker_objects_category" = "Objekte"; +"emoji_picker_symbols_category" = "Simbole"; +"emoji_picker_flags_category" = "Flamuj"; +// MARK: Reaction history +"reaction_history_title" = "Reagime"; +"auth_forgot_password_error_no_configured_identity_server" = "S’ka shërbyes identitetesh të formësuar: shtoni një të tillë që të ricaktoni fjalëkalimin tuaj."; +"room_creation_error_invite_user_by_email_without_identity_server" = "S’ka shërbyes identitetesh të formësua, ndaj s’mund të shtoni një pjesëmarrës me një email."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "S’ka shërbyes identitetesh të formësuar, ndaj s’mund të nisni një fjalosje me një kontakt duke përdorur një email."; +// Service terms +"service_terms_modal_title" = "Kushte Shërbimi"; +"service_terms_modal_message" = "Që të vazhdohet, lypset të pranoni Kushtet e këtij shërbimi."; +"service_terms_modal_accept_button" = "Pranoji"; +"service_terms_modal_description_for_identity_server" = "Jini i zbulueshëm nga të tjerët"; +"service_terms_modal_description_for_integration_manager" = "Përdorni Robotë, ura, widget-e dhe paketa ngjitësish"; diff --git a/Riot/Assets/vls.lproj/InfoPlist.strings b/Riot/Assets/vls.lproj/InfoPlist.strings index 8771d37a3..b2c4b0208 100644 --- a/Riot/Assets/vls.lproj/InfoPlist.strings +++ b/Riot/Assets/vls.lproj/InfoPlist.strings @@ -2,5 +2,5 @@ "NSCameraUsageDescription" = "De camera wor gebruukt vo fotootjes te trekkn en filmtjes te moakn, en vo videogesprekkn."; "NSPhotoLibraryUsageDescription" = "De fotogalerie wor gebruukt vo fotootjes en filmtjes te versteurn."; "NSMicrophoneUsageDescription" = "De microfoon wor gebruukt vo filmtjes te maken, en vo sproakiproepn."; -"NSContactsUsageDescription" = "Vo je te kunn toogn dewelkse van je contactn dat al Riot of Matrix gebruukn, kunn we d’e-mailadressn en telefongnumero’s in jen adresboek noa je Matrix-identiteitsserver steurn. New Vector bewoart deze gegevens nie en gebruukt ze ook nie voor andere doeleindn. Bekykt vo meer informoatie de privacybeleidspagina in d’instelliengn van den app."; +"NSContactsUsageDescription" = "Vo je te kunn toogn dewelkse van je contactn dat al Riot of Matrix gebruukn, kunn we d’e-mailadressn en telefongnumero’s in jen adresboek noa je Matrix-identiteitsserver steurn. New Vector bewoart deze gegevens nie en gebruukt ze ook nie voor andere doeleindn. Bekykt vo meer informoasje de privacybeleidspagina in d’instelliengn van den app."; "NSCalendarsUsageDescription" = "Bekykt je geplande afsproakn in den app."; diff --git a/Riot/Assets/vls.lproj/Vector.strings b/Riot/Assets/vls.lproj/Vector.strings index 0af4809f9..ce86d2ce3 100644 --- a/Riot/Assets/vls.lproj/Vector.strings +++ b/Riot/Assets/vls.lproj/Vector.strings @@ -10,3 +10,86 @@ // Actions "view" = "Toogn"; "next" = "Volgende"; +"store_full_description" = "Communiceert ip joun manier.\n\nE chat-app, onder joun controle en zeer flexibel. Riot lat je communiceern lyk of da je wilt. Gemakt vo [matrix] - de standoard voor open, gedecentraliseerde communicoasje.\n\nMakt e gratis account aan ip matrix.org, verkrygt jen eigen server ip https://modular.im, of gebruukt een andere Matrix-server.\n\nVowa zoun ’kik vo Riot.im kiezn?\n\n• VOLLEDIGE COMMUNICOASJE: makt gesprekkn an rond je teams, je moats, je gemeenschap - gelyk of da je gy ’t mo wilt! Chat, deelt bestandn, voegt widgets toe en makt stem- en video-iproepn - ollemoale volledig gratis.\n\n• KRACHTIGE INTEGROASJE: gebruukt Riot.im met de hulpmiddeln woamee da je vertrouwd zyt. Me Riot.im ku je zelfst chattn me gebrukers en groepn ip andere chat-apps.\n\n• PRIVÉ EN VEILIG: houdt je gesprekkn geheim. End-tout-end-versleuterienge van de bovenste plank zorgt dervoorn da je privécommunicoasje ook privé bluuft.\n\n• OPEN, NIE GESLOOTN: vrye software, gebouwd ip Matrix. Zy den boas over jen eigen gegeevns deur jen eigen server te gebruukn, of te kiezn voor een andere server da je vertrouwt.\n\n• WOA DA J’OOK ZYT: houdt contact woa da j’ook zyt me volledig gesynchroniseerde berichtgeschiedenisse ip al je toestelln, en online ip https://riot.im."; +"back" = "Weere"; +"continue" = "Verdergoan"; +"create" = "Anmoakn"; +"start" = "Beginn"; +"leave" = "Verloatn"; +"remove" = "Verwydern"; +"invite" = "Uutnodign"; +"retry" = "Herprobeern"; +"on" = "An"; +"off" = "Uut"; +"cancel" = "Annuleern"; +"save" = "Ipsloan"; +"join" = "Toetreedn"; +"decline" = "Afwyzn"; +"accept" = "Anveirdn"; +"preview" = "Voorvertoogn"; +"camera" = "Camera"; +"voice" = "Sproak"; +"video" = "Video"; +"active_call" = "Iproep actief"; +"active_call_details" = "Iproep actief (%@)"; +"later" = "Later"; +"rename" = "Hernoemn"; +"collapse" = "toeplooin"; +"send_to" = "Stuurt noa %@"; +"sending" = "Wor versteurd"; +"close" = "Sluutn"; +// Authentication +"auth_login" = "Anmeldn"; +"auth_register" = "Registreern"; +"auth_submit" = "Versteurn"; +"auth_skip" = "Oversloan"; +"auth_login_single_sign_on" = "Anmeldn met enkele anmeldienge"; +"auth_send_reset_email" = "Herstelmail versteurn"; +"auth_return_to_login" = "Weere noa ’t anmeldiengsscherm"; +"auth_user_id_placeholder" = "E-mailadresse of gebrukersnoame"; +"auth_password_placeholder" = "Paswoord"; +"auth_new_password_placeholder" = "Nieuw paswoord"; +"auth_user_name_placeholder" = "Gebrukersnoame"; +"auth_optional_email_placeholder" = "E-mailadresse (optioneel)"; +"auth_email_placeholder" = "E-mailadresse"; +"auth_optional_phone_placeholder" = "Telefongnumero (optioneel)"; +"auth_phone_placeholder" = "Telefongnumero"; +"auth_repeat_password_placeholder" = "Paswoord herhoaln"; +"auth_repeat_new_password_placeholder" = "Bevestigt je nieuw paswoord"; +"auth_home_server_placeholder" = "URL (bv. https://matrix.org)"; +"auth_identity_server_placeholder" = "URL (bv. https://matrix.org)"; +"auth_invalid_login_param" = "Verkeerd(e) gebrukersnoame en/of paswoord"; +"auth_invalid_user_name" = "Gebrukersnoamn meugn alleene mo letters, cyfers, puntn, koppelteekns en underscores bevattn"; +"auth_invalid_password" = "’t Paswoord is te kort (min 6)"; +"auth_invalid_email" = "Da ziet der hier nie uut gelyk e geldig e-mailadresse"; +"auth_invalid_phone" = "Da ziet der hier nie uut gelyk e geldige telefongnumero"; +"auth_missing_password" = "Paswoord mankeert"; +"auth_add_email_message" = "Voegt een e-mailadresse toe an jen account zoda gebrukers je kunn viendn en zoda je je paswoord kut herstelln."; +"auth_add_phone_message" = "Voegt e telefongnumero toe an jen account zoda gebrukers je kunn viendn."; +"auth_add_email_phone_message" = "Voegt een e-mailadresse en/of e telefongnumero toe an jen account zoda gebrukers je kunn viendn. Jen e-mailadresse mak et ook meuglik van je paswoord t’herstelln."; +"auth_add_email_and_phone_message" = "Voegt een e-mailadresse en e telefongnumero toe an jen account zoda gebrukers je kunn viendn. Jen e-mailadresse mak et ook meuglik van je paswoord t’herstelln."; +"auth_missing_email" = "E-mailadresse mankeert"; +"auth_missing_phone" = "Telefongnumero mankeert"; +"auth_missing_email_or_phone" = "E-mailadresse of telefongnumero mankeert"; +"auth_email_in_use" = "Dat e-mailadresse hier is al in gebruuk"; +"auth_phone_in_use" = "Dien telefongnumero hier is al in gebruuk"; +"auth_untrusted_id_server" = "Den identiteitsserver is nie vertrouwd"; +"auth_password_dont_match" = "De paswoordn kommn nie overeen"; +"auth_username_in_use" = "De gebrukersnoame is al in gebruuk"; +"auth_forgot_password" = "Paswoord vergeetn?"; +"auth_forgot_password_error_no_configured_identity_server" = "’t Is genen identiteitsserver geconfigureerd gewist: voegt der enen toe vo je paswoord herin te stelln."; +"auth_email_not_found" = "E-mail versteurn mislukt: dat e-mailadresse is hier nie gevoundn"; +"auth_use_server_options" = "Angepaste serverinstelliengn gebruukn (geavanceerd)"; +"auth_email_validation_message" = "Bekykt jen e-mail vo vorts te goan me de registroasje"; +"auth_msisdn_validation_title" = "Verificoasje in afwachtienge"; +"auth_msisdn_validation_message" = "M’èn een smse met een activoasjecode gesteurd ghed. Voert die code hieroundern in."; +"auth_msisdn_validation_error" = "Kostege den telefongnumero nie verifieern."; +"auth_recaptcha_message" = "Dezen thuusserver wilt der geern zeker van zyn da je gy geen robot zyt"; +"auth_reset_password_message" = "Gif ’t e-mailadresse da me jen account verbondn is in vo je paswoord herin te stelln:"; +"auth_reset_password_missing_email" = "’t E-mailadresse da men jen account verbondn is moet ingegeevn wordn."; +"auth_reset_password_missing_password" = "’t Moet e nieuw paswoord ingegeevn wordn."; +"auth_reset_password_email_validation_message" = "’t Is een e-mail noa %@ gesteurd gewist. Klikt hierounder van zodra da je de koppelienge derin geopend ghed èt."; +"auth_reset_password_next_step_button" = "’k Èn ik m’n e-mailadresse geverifieerd"; +"auth_reset_password_error_unauthorized" = "Verifieern van ’t e-mailadresse is mislukt: zorgt da j’ip de koppelienge in den e-mail geklikt ghed èt"; +"auth_reset_password_error_not_found" = "’t Ziet der nie noar uut da jen e-mailadresse met e Matrix-ID ip dezen thuusserver is verboundn."; +"auth_reset_password_success_message" = "Je paswoord is heringesteld gewist.\n\nJe zy nu ip alle toestelln afgemeld en je goa geen pushmeldiengn nie mi ontvangn. Vo meldiengn herin te schoakeln, meld je jen ip ieder toestel heran."; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 5d52392c0..6afce9f2b 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -994,10 +994,16 @@ internal enum VectorL10n { internal static var encryptedRoomMessageReplyToPlaceholder: String { return VectorL10n.tr("Vector", "encrypted_room_message_reply_to_placeholder") } + /// Add an identity server in your settings to invite by email. internal static var errorInvite3pidWithNoIdentityServer: String { return VectorL10n.tr("Vector", "error_invite_3pid_with_no_identity_server") + + /// It looks like you’re trying to connect to another homeserver. Do you want to sign out? + internal static var errorUserAlreadyLoggedIn: String { + return VectorL10n.tr("Vector", "error_user_already_logged_in") } + /// VoIP conference added by %@ internal static func eventFormatterJitsiWidgetAdded(_ p1: String) -> String { return VectorL10n.tr("Vector", "event_formatter_jitsi_widget_added", p1) @@ -1482,6 +1488,30 @@ internal enum VectorL10n { internal static var mediaPickerTitle: String { return VectorL10n.tr("Vector", "media_picker_title") } + /// Audio + internal static var mediaTypeAccessibilityAudio: String { + return VectorL10n.tr("Vector", "media_type_accessibility_audio") + } + /// File + internal static var mediaTypeAccessibilityFile: String { + return VectorL10n.tr("Vector", "media_type_accessibility_file") + } + /// Image + internal static var mediaTypeAccessibilityImage: String { + return VectorL10n.tr("Vector", "media_type_accessibility_image") + } + /// Location + internal static var mediaTypeAccessibilityLocation: String { + return VectorL10n.tr("Vector", "media_type_accessibility_location") + } + /// Sticker + internal static var mediaTypeAccessibilitySticker: String { + return VectorL10n.tr("Vector", "media_type_accessibility_sticker") + } + /// Video + internal static var mediaTypeAccessibilityVideo: String { + return VectorL10n.tr("Vector", "media_type_accessibility_video") + } /// The Internet connection appears to be offline. internal static var networkOfflinePrompt: String { return VectorL10n.tr("Vector", "network_offline_prompt") @@ -1570,6 +1600,30 @@ internal enum VectorL10n { internal static var retry: String { return VectorL10n.tr("Vector", "retry") } + /// Call + internal static var roomAccessibilityCall: String { + return VectorL10n.tr("Vector", "room_accessibility_call") + } + /// Hang up + internal static var roomAccessibilityHangup: String { + return VectorL10n.tr("Vector", "room_accessibility_hangup") + } + /// Integrations + internal static var roomAccessibilityIntegrations: String { + return VectorL10n.tr("Vector", "room_accessibility_integrations") + } + /// Search + internal static var roomAccessibilitySearch: String { + return VectorL10n.tr("Vector", "room_accessibility_search") + } + /// Upload + internal static var roomAccessibilityUpload: String { + return VectorL10n.tr("Vector", "room_accessibility_upload") + } + /// Scroll to bottom + internal static var roomAccessiblityScrollToBottom: String { + return VectorL10n.tr("Vector", "room_accessiblity_scroll_to_bottom") + } /// Take photo or video internal static var roomActionCamera: String { return VectorL10n.tr("Vector", "room_action_camera") @@ -3210,6 +3264,10 @@ internal enum VectorL10n { internal static var widgetNoPowerToManage: String { return VectorL10n.tr("Vector", "widget_no_power_to_manage") } + /// Integrations + internal static var widgetPickerTitle: String { + return VectorL10n.tr("Vector", "widget_picker_title") + } /// You don't currently have any stickerpacks enabled. internal static var widgetStickerPickerNoStickerpacksAlert: String { return VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert") diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index 9c24ea4f1..f854a0a1c 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -45,5 +45,7 @@ @property (weak, nonatomic) IBOutlet UILabel *softLogoutClearDataLabel; @property (weak, nonatomic) IBOutlet UIButton *softLogoutClearDataButton; +- (void)showCustomHomeserver:(NSString*)homeserver andIdentityServer:(NSString*)identityServer; + @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 98ce653c2..2ba421545 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -23,8 +23,9 @@ #import "AuthInputsView.h" #import "ForgotPasswordInputsView.h" +#import "AuthFallBackViewController.h" -@interface AuthenticationViewController () +@interface AuthenticationViewController () { /** Store the potential login error received by using a default homeserver different from matrix.org @@ -46,6 +47,8 @@ Server discovery. */ MXAutoDiscovery *autoDiscovery; + + AuthFallBackViewController *authFallBackViewController; } @property (nonatomic, readonly) BOOL isIdentityServerConfigured; @@ -420,6 +423,74 @@ } } + +#pragma mark - Fallback URL display + +- (void)showAuthenticationFallBackView:(NSString*)fallbackPage +{ + // Skip MatrixKit and use a VC instead + if (self.softLogoutCredentials) + { + // Add device_id as query param of the fallback + NSURLComponents *components = [[NSURLComponents alloc] initWithString:fallbackPage]; + + NSMutableArray *queryItems = [components.queryItems mutableCopy]; + if (!queryItems) + { + queryItems = [NSMutableArray array]; + } + + [queryItems addObject:[NSURLQueryItem queryItemWithName:@"device_id" + value:self.softLogoutCredentials.deviceId]]; + + components.queryItems = queryItems; + + fallbackPage = components.URL.absoluteString; + } + + [self showAuthenticationFallBackViewController:fallbackPage]; +} + +- (void)showAuthenticationFallBackViewController:(NSString*)fallbackPage +{ + authFallBackViewController = [[AuthFallBackViewController alloc] initWithURL:fallbackPage]; + authFallBackViewController.delegate = self; + + + authFallBackViewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(dismissFallBackViewController:)]; + + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:authFallBackViewController]; + [self presentViewController:navigationController animated:YES completion:nil]; +} + +- (void)dismissFallBackViewController:(id)sender +{ + [authFallBackViewController dismissViewControllerAnimated:YES completion:nil]; + authFallBackViewController = nil; +} + + +#pragma mark AuthFallBackViewControllerDelegate + +- (void)authFallBackViewController:(AuthFallBackViewController *)authFallBackViewController + didLoginWithLoginResponse:(MXLoginResponse *)loginResponse +{ + [authFallBackViewController dismissViewControllerAnimated:YES completion:^{ + + MXCredentials *credentials = [[MXCredentials alloc] initWithLoginResponse:loginResponse andDefaultCredentials:nil]; + [self onSuccessfulLogin:credentials]; + }]; + + authFallBackViewController = nil; +} + + +- (void)authFallBackViewControllerDidClose:(AuthFallBackViewController *)authFallBackViewController +{ + [self dismissFallBackViewController:nil]; +} + + - (void)setSoftLogoutCredentials:(MXCredentials *)softLogoutCredentials { [super setSoftLogoutCredentials:softLogoutCredentials]; @@ -509,9 +580,61 @@ }]; } +/** + Filter and prioritise flows supported by the app. + + @param authSession the auth session coming from the HS. + @return a new auth session + */ +- (MXAuthenticationSession*)handleSupportedFlowsInAuthenticationSession:(MXAuthenticationSession *)authSession +{ + MXLoginFlow *ssoFlow; + NSMutableArray *supportedFlows = [NSMutableArray array]; + + for (MXLoginFlow *flow in authSession.flows) + { + // Remove known flows we do not support + if (![flow.type isEqualToString:kMXLoginFlowTypeToken]) + { + NSLog(@"[AuthenticationVC] handleSupportedFlowsInAuthenticationSession: Filter out flow %@", flow.type); + [supportedFlows addObject:flow]; + } + + // Prioritise SSO over other flows + if ([flow.type isEqualToString:kMXLoginFlowTypeSSO] + || [flow.type isEqualToString:kMXLoginFlowTypeCAS]) + { + NSLog(@"[AuthenticationVC] handleSupportedFlowsInAuthenticationSession: Prioritise flow %@", flow.type); + ssoFlow = flow; + break; + } + } + + if (ssoFlow) + { + [supportedFlows removeAllObjects]; + [supportedFlows addObject:ssoFlow]; + } + + if (supportedFlows.count != authSession.flows.count) + { + MXAuthenticationSession *updatedAuthSession = [[MXAuthenticationSession alloc] init]; + updatedAuthSession.session = authSession.session; + updatedAuthSession.params = authSession.params; + updatedAuthSession.flows = supportedFlows; + return updatedAuthSession; + } + else + { + return authSession; + } +} - (void)handleAuthenticationSession:(MXAuthenticationSession *)authSession { + // Make some cleaning from the server response according to what the app supports + authSession = [self handleSupportedFlowsInAuthenticationSession:authSession]; + [super handleAuthenticationSession:authSession]; AuthInputsView *authInputsview; @@ -665,8 +788,6 @@ { // Do SSO using the fallback URL [self showAuthenticationFallBackView]; - - [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; } else if (sender == self.softLogoutClearDataButton) { diff --git a/Riot/Modules/Home/Fallback/AuthFallBackViewController.h b/Riot/Modules/Home/Fallback/AuthFallBackViewController.h new file mode 100644 index 000000000..97f868f1f --- /dev/null +++ b/Riot/Modules/Home/Fallback/AuthFallBackViewController.h @@ -0,0 +1,40 @@ +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "WebViewViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@class AuthFallBackViewController; +@protocol AuthFallBackViewControllerDelegate + +- (void)authFallBackViewController:(AuthFallBackViewController*)authFallBackViewController didLoginWithLoginResponse:(MXLoginResponse*)loginResponse; +- (void)authFallBackViewControllerDidClose:(AuthFallBackViewController*)authFallBackViewController; + +@end + + +/** + `AuthFallBackViewController` handles the display of a Matrix fallback URL for + login, registration and Single-Sign-On. + */ +@interface AuthFallBackViewController : WebViewViewController + +@property (nonatomic, weak, nullable) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Riot/Modules/Home/Fallback/AuthFallBackViewController.m b/Riot/Modules/Home/Fallback/AuthFallBackViewController.m new file mode 100644 index 000000000..b61b6361b --- /dev/null +++ b/Riot/Modules/Home/Fallback/AuthFallBackViewController.m @@ -0,0 +1,217 @@ +/* + Copyright 2019 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "AuthFallBackViewController.h" +#import "AppDelegate.h" + + +// Generic method to make a bridge between JS and the UIWebView +NSString *FallBackViewControllerJavascriptSendObjectMessage = @"window.sendObjectMessage = function(parameters) { \ + var iframe = document.createElement('iframe'); \ + iframe.setAttribute('src', 'js:' + JSON.stringify(parameters)); \ + \ + document.documentElement.appendChild(iframe); \ + iframe.parentNode.removeChild(iframe); \ + iframe = null; \ +};"; + +// The function the fallback page calls when the registration is complete +NSString *FallBackViewControllerJavascriptOnRegistered = @"window.matrixRegistration.onRegistered = function(homeserverUrl, userId, accessToken) { \ + sendObjectMessage({ \ + 'action': 'onRegistered', \ + 'homeServer': homeserverUrl, \ + 'userId': userId, \ + 'accessToken': accessToken \ + }); \ +};"; + +// The function the fallback page calls when the login is complete +NSString *FallBackViewControllerJavascriptOnLogin = @"window.matrixLogin.onLogin = function(response) { \ + sendObjectMessage({ \ + 'action': 'onLogin', \ + 'response': response \ + }); \ +};"; + +@interface AuthFallBackViewController () + +@end + +@implementation AuthFallBackViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Due to https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html, we hack + // the user agent to bypass the limitation of Google, as a quick fix (a proper solution will be to use the SSO SDK) + webView.customUserAgent = @"Mozilla/5.0"; + + [self clearCookies]; +} + +- (void)clearCookies +{ + // TODO: it would be better to do that at WKWebView init like below + // but this code is part of the kit + // WKWebViewConfiguration *config = [WKWebViewConfiguration new]; + // config.websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore]; + // webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:config]; + + WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore]; + [dateStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] + completionHandler:^(NSArray * __nonnull records) + { + for (WKWebsiteDataRecord *record in records) + { + [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes + forDataRecords:@[record] + completionHandler:^ + { + NSLog(@"[AuthFallBackViewController] clearCookies: Cookies for %@ deleted successfully", record.displayName); + }]; + } + }]; +} + +- (void)showErrorAsAlert:(NSError*)error +{ + NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey]; + NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey]; + if (!title) + { + if (msg) + { + title = msg; + msg = nil; + } + else + { + title = [NSBundle mxk_localizedStringForKey:@"error"]; + } + } + + MXWeakify(self); + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + + if (self.delegate) + { + [self.delegate authFallBackViewControllerDidClose:self]; + } + + }]]; + + [self presentViewController:alert animated:YES completion:nil]; +} + + +#pragma mark - WKNavigationDelegate + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation +{ + [super webView:webView didFinishNavigation:navigation]; + + // Set up JS <-> iOS bridge + [webView evaluateJavaScript:FallBackViewControllerJavascriptSendObjectMessage completionHandler:nil]; + [webView evaluateJavaScript:FallBackViewControllerJavascriptOnRegistered completionHandler:nil]; + [webView evaluateJavaScript:FallBackViewControllerJavascriptOnLogin completionHandler:nil]; + + // Check connectivity + if ([AppDelegate theDelegate].isOffline) + { + NSError *error = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorNotConnectedToInternet + userInfo:@{ + NSLocalizedDescriptionKey : NSLocalizedStringFromTable(@"network_offline_prompt", @"Vector", nil) + }]; + [self showErrorAsAlert:error]; + } +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler +{ + NSString *urlString = navigationAction.request.URL.absoluteString; + + // TODO: We should use the WebKit PostMessage API and the + // `didReceiveScriptMessage` delegate to manage the JS<->Native bridge + if ([urlString hasPrefix:@"js:"]) + { + // Listen only to scheme of the JS-UIWebView bridge + NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; + NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; + + NSError *error; + NSDictionary *parameters = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers + error:&error]; + + if (!error) + { + if ([@"onRegistered" isEqualToString:parameters[@"action"]]) + { + // Translate the JS registration event to MXLoginResponse + // We cannot use [MXLoginResponse modelFromJSON:] because of https://github.com/matrix-org/synapse/issues/4756 + // Because of this issue, we cannot get the device_id allocated by the homeserver + // TODO: Fix it once the homeserver issue is fixed (filed at https://github.com/vector-im/riot-meta/issues/273). + MXLoginResponse *loginResponse = [MXLoginResponse new]; + loginResponse.homeserver = parameters[@"homeServer"]; + loginResponse.userId = parameters[@"userId"]; + loginResponse.accessToken = parameters[@"accessToken"]; + + // Sanity check + if (self.delegate + && loginResponse.homeserver.length && loginResponse.userId.length && loginResponse.accessToken.length) + { + // And inform the client + [self.delegate authFallBackViewController:self didLoginWithLoginResponse:loginResponse]; + } + } + else if ([@"onLogin" isEqualToString:parameters[@"action"]]) + { + // Translate the JS login event to MXLoginResponse + MXLoginResponse *loginResponse; + MXJSONModelSetMXJSONModel(loginResponse, MXLoginResponse, parameters[@"response"]); + + // Sanity check + if (self.delegate + && loginResponse.homeserver.length && loginResponse.userId.length && loginResponse.accessToken.length) + { + // And inform the client + [self.delegate authFallBackViewController:self didLoginWithLoginResponse:loginResponse]; + } + } + } + + decisionHandler(WKNavigationActionPolicyCancel); + return; + } + + if (navigationAction.navigationType == WKNavigationTypeLinkActivated) + { + // Open links outside the app + [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{} completionHandler:nil]; + decisionHandler(WKNavigationActionPolicyCancel); + return; + } + + decisionHandler(WKNavigationActionPolicyAllow); +} + +@end diff --git a/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m b/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m index 4287370a3..d0077f87c 100644 --- a/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m +++ b/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m @@ -40,7 +40,7 @@ mxSession = theMXSession; roomId = theRoomId; - _alertController = [UIAlertController alertControllerWithTitle:@"Matrix Apps" + _alertController = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"widget_picker_title", @"Vector", nil) message:nil preferredStyle:UIAlertControllerStyleAlert]; } diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.h b/Riot/Modules/Room/CellData/RoomBubbleCellData.h index 777063a59..7c34278ff 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.h +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.h @@ -90,4 +90,9 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag) - (BOOL)showAllReactionsForEvent:(NSString*)eventId; - (void)setShowAllReactions:(BOOL)showAllReactions forEvent:(NSString*)eventId; + +#pragma mark - Accessibility + +- (NSString*)accessibilityLabel; + @end diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 5fda69f74..a89214ce4 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -698,4 +698,58 @@ static NSAttributedString *timestampVerticalWhitespace = nil; } } +- (NSString *)accessibilityLabel +{ + NSString *accessibilityLabel; + + // Only media require manual handling for accessibility + if (self.attachment) + { + NSString *mediaName = [self accessibilityLabelForAttachmentType:self.attachment.type]; + + MXJSONModelSetString(accessibilityLabel, self.events.firstObject.content[@"body"]); + if (accessibilityLabel) + { + accessibilityLabel = [NSString stringWithFormat:@"%@ %@", mediaName, accessibilityLabel]; + } + else + { + accessibilityLabel = mediaName; + } + } + + return accessibilityLabel; +} + +- (NSString*)accessibilityLabelForAttachmentType:(MXKAttachmentType)attachmentType +{ + NSString *accessibilityLabel; + switch (attachmentType) + { + case MXKAttachmentTypeImage: + accessibilityLabel = NSLocalizedStringFromTable(@"media_type_accessibility_image", @"Vector", nil); + break; + case MXKAttachmentTypeAudio: + accessibilityLabel = NSLocalizedStringFromTable(@"media_type_accessibility_audio", @"Vector", nil); + break; + case MXKAttachmentTypeVideo: + accessibilityLabel = NSLocalizedStringFromTable(@"media_type_accessibility_video", @"Vector", nil); + break; + case MXKAttachmentTypeLocation: + accessibilityLabel = NSLocalizedStringFromTable(@"media_type_accessibility_location", @"Vector", nil); + break; + case MXKAttachmentTypeFile: + accessibilityLabel = NSLocalizedStringFromTable(@"media_type_accessibility_file", @"Vector", nil); + break; + case MXKAttachmentTypeSticker: + accessibilityLabel = NSLocalizedStringFromTable(@"media_type_accessibility_sticker", @"Vector", nil); + break; + default: + accessibilityLabel = @""; + break; + } + + return accessibilityLabel; +} + @end diff --git a/Riot/Modules/Room/ContextualMenu/ContextualMenuItemView.swift b/Riot/Modules/Room/ContextualMenu/ContextualMenuItemView.swift index 8a0147e5f..2e95493d7 100644 --- a/Riot/Modules/Room/ContextualMenu/ContextualMenuItemView.swift +++ b/Riot/Modules/Room/ContextualMenu/ContextualMenuItemView.swift @@ -93,20 +93,30 @@ final class ContextualMenuItemView: UIView, NibOwnerLoadable { } // MARK: - Public - - func fill(title: String, image: UIImage?) { - self.originalImage = image?.withRenderingMode(.alwaysTemplate) - self.titleLabel.text = title - self.updateView() - } - + func fill(menuItem: RoomContextualMenuItem) { self.fill(title: menuItem.title, image: menuItem.image) + self.setupAccessibility(title: menuItem.title, isEnabled: menuItem.isEnabled) self.action = menuItem.action self.isEnabled = menuItem.isEnabled } // MARK: - Private + + private func fill(title: String, image: UIImage?) { + self.originalImage = image?.withRenderingMode(.alwaysTemplate) + self.titleLabel.text = title + self.updateView() + } + + private func setupAccessibility(title: String, isEnabled: Bool) { + self.isAccessibilityElement = true + self.accessibilityLabel = title + self.accessibilityTraits = .button + if !isEnabled { + self.accessibilityTraits.insert(.notEnabled) + } + } private func setupGestureRecognizer() { let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(buttonAction(_:))) diff --git a/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift b/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift index 874ac0466..32052dc06 100644 --- a/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift +++ b/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift @@ -117,11 +117,15 @@ final class RoomContextualMenuViewController: UIViewController, Themable { func showMenuToolbar() { self.menuToolbarViewBottomConstraint.constant = 0 self.menuToolbarView.alpha = 1 + + // Force VoiceOver to focus on the menu bar actions + UIAccessibility.post(notification: .screenChanged, argument: self.menuToolbarView) } func hideMenuToolbar() { self.menuToolbarViewBottomConstraint.constant = self.hiddenToolbarViewBottomConstant self.menuToolbarView.alpha = 0 + UIAccessibility.post(notification: .screenChanged, argument: nil) } func prepareReactionsMenuAnimations() { diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 3b05bc638..103fd0acc 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -196,6 +196,8 @@ if ([cell isKindOfClass:MXKRoomBubbleTableViewCell.class]) { MXKRoomBubbleTableViewCell *bubbleCell = (MXKRoomBubbleTableViewCell*)cell; + [self resetAccessibilityForCell:bubbleCell]; + RoomBubbleCellData *cellData = (RoomBubbleCellData*)bubbleCell.bubbleData; NSArray *bubbleComponents = cellData.bubbleComponents; @@ -507,6 +509,8 @@ // Auto animate the sticker in case of animated gif bubbleCell.isAutoAnimatedGif = (cellData.attachment && cellData.attachment.type == MXKAttachmentTypeSticker); + + [self setupAccessibilityForCell:bubbleCell withCellData:cellData]; } return cell; @@ -563,6 +567,35 @@ [self sendVideo:videoLocalURL withThumbnail:videoThumbnail success:success failure:failure]; } + +#pragma - Accessibility + +- (void)setupAccessibilityForCell:(MXKRoomBubbleTableViewCell *)cell withCellData:(RoomBubbleCellData*)cellData +{ + // Set accessibility only on media. Let VoiceOver automatically manages text messages + if (cellData.attachment) + { + NSString *accessibilityLabel = [cellData accessibilityLabel]; + if (cell.messageTextView.text.length) + { + // Files are presented as text with link + cell.messageTextView.accessibilityLabel = accessibilityLabel; + cell.messageTextView.isAccessibilityElement = YES; + } + else + { + cell.attachmentView.accessibilityLabel = accessibilityLabel; + cell.attachmentView.isAccessibilityElement = YES; + } + } +} + +- (void)resetAccessibilityForCell:(MXKRoomBubbleTableViewCell *)cell +{ + cell.messageTextView.accessibilityLabel = nil; + cell.attachmentView.accessibilityLabel = nil; +} + #pragma mark - BubbleReactionsViewModelDelegate - (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didAddReaction:(MXReactionCount *)reactionCount forEventId:(NSString *)eventId diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 84b9836e0..6944e0900 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -798,7 +798,9 @@ - (void)addRoomThirdPartyInviteToParticipants:(MXRoomThirdPartyInvite*)roomThirdPartyInvite roomState:(MXRoomState*)roomState { // If the homeserver has converted the 3pid invite into a room member, do no show it - if (![roomState memberWithThirdPartyInviteToken:roomThirdPartyInvite.token]) + // If the invite has been revoked (null display name), do not show it too. + if (![roomState memberWithThirdPartyInviteToken:roomThirdPartyInvite.token] + && roomThirdPartyInvite.displayname) { Contact *contact = [[Contact alloc] initMatrixContactWithDisplayName:roomThirdPartyInvite.displayname andMatrixID:nil]; contact.isThirdPartyInvite = YES; @@ -1373,8 +1375,6 @@ if (section == participantsSection || section == invitedSection) { - __weak typeof(self) weakSelf = self; - if (currentAlert) { [currentAlert dismissViewControllerAnimated:NO completion:nil]; @@ -1384,6 +1384,7 @@ if (section == participantsSection && userParticipant && (0 == row) && !currentSearchText.length) { // Leave ? + MXWeakify(self); currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_participants_leave_prompt_title", @"Vector", nil) message:NSLocalizedStringFromTable(@"room_participants_leave_prompt_msg", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert]; @@ -1392,11 +1393,8 @@ style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; }]]; @@ -1404,25 +1402,25 @@ style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + [self addPendingActionMask]; + MXWeakify(self); + [self.mxRoom leave:^{ - [self addPendingActionMask]; - [self.mxRoom leave:^{ - - [self withdrawViewControllerAnimated:YES completion:nil]; - - } failure:^(NSError *error) { - - [self removePendingActionMask]; - NSLog(@"[RoomParticipantsVC] Leave room %@ failed", self.mxRoom.roomId); - // Alert user - [[AppDelegate theDelegate] showErrorAsAlert:error]; - - }]; - } + MXStrongifyAndReturnIfNil(self); + [self withdrawViewControllerAnimated:YES completion:nil]; + + } failure:^(NSError *error) { + + MXStrongifyAndReturnIfNil(self); + [self removePendingActionMask]; + NSLog(@"[RoomParticipantsVC] Leave room %@ failed", self.mxRoom.roomId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; }]]; @@ -1464,6 +1462,7 @@ if (row < participants.count) { Contact *contact = participants[row]; + MXWeakify(self); if (contact.mxMember) { @@ -1479,11 +1478,8 @@ style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; }]]; @@ -1491,51 +1487,80 @@ style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - [self addPendingActionMask]; - [self.mxRoom kickUser:memberUserId - reason:nil - success:^{ - - [self removePendingActionMask]; - - [participants removeObjectAtIndex:row]; - - // Refresh display - [self.tableView reloadData]; - - } failure:^(NSError *error) { - - [self removePendingActionMask]; - NSLog(@"[RoomParticipantsVC] Kick %@ failed", memberUserId); - // Alert user - [[AppDelegate theDelegate] showErrorAsAlert:error]; - - }]; - } + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + [self addPendingActionMask]; + MXWeakify(self); + [self.mxRoom kickUser:memberUserId + reason:nil + success:^{ + + MXStrongifyAndReturnIfNil(self); + [self removePendingActionMask]; + + [participants removeObjectAtIndex:row]; + + // Refresh display + [self.tableView reloadData]; + + } failure:^(NSError *error) { + + MXStrongifyAndReturnIfNil(self); + [self removePendingActionMask]; + NSLog(@"[RoomParticipantsVC] Kick %@ failed", memberUserId); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; }]]; } - else + else if (contact.mxThirdPartyInvite) { - // This is a third-party invite, it could not be removed until the api exists + // This is a third-party invite currentAlert = [UIAlertController alertControllerWithTitle:nil - message:NSLocalizedStringFromTable(@"room_participants_remove_third_party_invite_msg", @"Vector", nil) + message:NSLocalizedStringFromTable(@"room_participants_remove_third_party_invite_prompt_msg", @"Vector", nil) preferredStyle:UIAlertControllerStyleAlert]; [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + }]]; + + [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"remove", @"Vector", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + [self addPendingActionMask]; + MXWeakify(self); + [self.mxRoom sendStateEventOfType:kMXEventTypeStringRoomThirdPartyInvite + content:@{} stateKey:contact.mxThirdPartyInvite.token success:^(NSString *eventId) { + + MXStrongifyAndReturnIfNil(self); + [self removePendingActionMask]; + + [participants removeObjectAtIndex:row]; + + // Refresh display + [self.tableView reloadData]; + + } failure:^(NSError *error) { + + MXStrongifyAndReturnIfNil(self); + [self removePendingActionMask]; + NSLog(@"[RoomParticipantsVC] Revoke 3pid invite failed"); + // Alert user + [[AppDelegate theDelegate] showErrorAsAlert:error]; + + }]; }]]; } diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 8b00b3441..601e12036 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -123,7 +123,7 @@ #import "Riot-Swift.h" -@interface RoomViewController () { @@ -813,6 +813,92 @@ [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; } +#pragma mark - Accessibility + +// Handle scrolling when VoiceOver is on because it does not work well if we let the system do: +// VoiceOver loses the focus on the tableview +- (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction +{ + BOOL canScroll = YES; + + // Scroll by one page + CGFloat tableViewHeight = self.bubblesTableView.frame.size.height; + + CGPoint offset = self.bubblesTableView.contentOffset; + switch (direction) + { + case UIAccessibilityScrollDirectionUp: + offset.y -= tableViewHeight; + break; + + case UIAccessibilityScrollDirectionDown: + offset.y += tableViewHeight; + break; + + default: + break; + } + + if (offset.y < 0 && ![self.roomDataSource.timeline canPaginate:MXTimelineDirectionBackwards]) + { + // Can't paginate more. Let's stick on the first item + UIView *focusedView = [self firstCellWithAccessibilityDataInCells:self.bubblesTableView.visibleCells.objectEnumerator]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, focusedView); + canScroll = NO; + } + else if (offset.y > self.bubblesTableView.contentSize.height - tableViewHeight + && ![self.roomDataSource.timeline canPaginate:MXTimelineDirectionForwards]) + { + // Can't paginate more. Let's stick on the last item with accessibility + UIView *focusedView = [self firstCellWithAccessibilityDataInCells:self.bubblesTableView.visibleCells.reverseObjectEnumerator]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, focusedView); + canScroll = NO; + } + else + { + // Disable VoiceOver while scrolling + self.bubblesTableView.accessibilityElementsHidden = YES; + + [self.bubblesTableView setContentOffset:offset animated:NO]; + + NSEnumerator *cells; + if (direction == UIAccessibilityScrollDirectionUp) + { + cells = self.bubblesTableView.visibleCells.objectEnumerator; + } + else + { + cells = self.bubblesTableView.visibleCells.reverseObjectEnumerator; + } + UIView *cell = [self firstCellWithAccessibilityDataInCells:cells]; + + self.bubblesTableView.accessibilityElementsHidden = NO; + + // Force VoiceOver to focus on a visible item + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, cell); + } + + // If we cannot scroll, let VoiceOver indicates the border + return canScroll; +} + +- (UIView*)firstCellWithAccessibilityDataInCells:(NSEnumerator*)cells +{ + UIView *view; + + for (UITableViewCell *cell in cells) + { + if (![cell isKindOfClass:[RoomEmptyBubbleCell class]]) + { + view = cell; + break; + } + } + + return view; +} + + #pragma mark - Override MXKRoomViewController - (void)onMatrixSessionChange @@ -1372,12 +1458,16 @@ icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; self.navigationItem.rightBarButtonItems[1].image = icon; + self.navigationItem.rightBarButtonItems[1].accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_integrations", @"Vector", nil); } else { // Reset original icon self.navigationItem.rightBarButtonItems[1].image = [UIImage imageNamed:@"apps-icon"]; + self.navigationItem.rightBarButtonItems[1].accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_integrations", @"Vector", nil); } + + self.navigationItem.rightBarButtonItems.firstObject.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_search", @"Vector", nil); } // Do not change title view class here if the expanded header is visible. diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 6648db9b1..1baaf2079 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -307,6 +307,11 @@ self.iconImageView.image = [UIImage imageNamed:@"scrolldown"]; } self.iconImageView.hidden = NO; + + // Make VoiceOver consider it as a button + self.iconImageView.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessiblity_scroll_to_bottom", @"Vector", nil); + self.iconImageView.isAccessibilityElement = YES; + self.iconImageView.accessibilityTraits = UIAccessibilityTraitButton; if (onIconTapGesture) { diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 577e89544..855c21454 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -92,6 +92,10 @@ growingTextView.tintColor = ThemeService.shared.theme.tintColor; growingTextView.internalTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance; + + self.attachMediaButton.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_upload", @"Vector", nil); + self.voiceCallButton.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_call", @"Vector", nil); + self.hangupCallButton.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessibility_hangup", @"Vector", nil); } #pragma mark - diff --git a/Riot/SupportingFiles/Info.plist b/Riot/SupportingFiles/Info.plist index 2ee99817e..5a0c589e5 100644 --- a/Riot/SupportingFiles/Info.plist +++ b/Riot/SupportingFiles/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.9.2 + 0.9.5 CFBundleSignature ???? CFBundleVersion - 0.9.2 + 0.9.5 ITSAppUsesNonExemptEncryption ITSEncryptionExportComplianceCode diff --git a/RiotShareExtension/SupportingFiles/Info.plist b/RiotShareExtension/SupportingFiles/Info.plist index 4cc7b7bb6..ba2f5a2e1 100644 --- a/RiotShareExtension/SupportingFiles/Info.plist +++ b/RiotShareExtension/SupportingFiles/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 0.9.2 + 0.9.5 CFBundleVersion - 0.9.2 + 0.9.5 NSExtension NSExtensionAttributes diff --git a/SiriIntents/Info.plist b/SiriIntents/Info.plist index 804ac1c8f..b39ef1a68 100644 --- a/SiriIntents/Info.plist +++ b/SiriIntents/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 0.9.2 + 0.9.5 CFBundleVersion - 0.9.2 + 0.9.5 NSExtension NSExtensionAttributes