From 42ce2f73813453fb5d0865138d5f67755255ce07 Mon Sep 17 00:00:00 2001 From: Martin Sirringhaus Date: Wed, 9 Sep 2026 10:26:22 +0200 Subject: [PATCH 1/3] Only send restart-signals to the UI, if the device was actively used --- credentialsd/src/credential_service/hybrid.rs | 40 +++++++-- credentialsd/src/credential_service/mod.rs | 80 ++++++++++++++++++ credentialsd/src/credential_service/nfc.rs | 83 +++++++++++++----- credentialsd/src/credential_service/usb.rs | 84 ++++++++++++++----- 4 files changed, 236 insertions(+), 51 deletions(-) diff --git a/credentialsd/src/credential_service/hybrid.rs b/credentialsd/src/credential_service/hybrid.rs index c5094e9..f5b1536 100644 --- a/credentialsd/src/credential_service/hybrid.rs +++ b/credentialsd/src/credential_service/hybrid.rs @@ -73,6 +73,11 @@ impl HybridHandler for InternalHybridHandler { // Each iteration creates a fresh CableQrCodeDevice (the previous one // is consumed by channel()), so the old QR secret is discarded. loop { + // Reset the active flag for each ceremony attempt. It will be set to + // true inside run_hybrid_ceremony once the phone establishes a channel + // (i.e. the QR has been consumed and the BLE handshake succeeded). + let mut active = false; + let mut device = match CableQrCodeDevice::new_transient(hint, hybrid_transports) { Ok(device) => device, Err(err) => { @@ -98,8 +103,14 @@ impl HybridHandler for InternalHybridHandler { // Run the ceremony awaited directly (not in a nested spawn) so that // the retry loop is sequential and no orphaned tasks can arise. - let response = - run_hybrid_ceremony(&mut device, &request, &tx, cancellation.clone()).await; + let response = run_hybrid_ceremony( + &mut device, + &request, + &tx, + cancellation.clone(), + &mut active, + ) + .await; match response { Ok(auth_response) => { @@ -107,8 +118,7 @@ impl HybridHandler for InternalHybridHandler { break; } Err(err) if super::is_ceremony_terminating(&err) => { - // Terminating errors (CredentialExcluded, NonTerminatingCancellation - // from a winning transport, etc.) stop the loop. + // Terminating errors stop the loop. // NonTerminatingCancellation exits silently; others surface as Failed. if !matches!(err, CredentialServiceError::NonTerminatingCancellation) { let _ = tx.send(HybridStateInternal::Failed(err)).await; @@ -118,11 +128,17 @@ impl HybridHandler for InternalHybridHandler { break; } Err(err) => { - // Non-terminating: notify the UI that a restart is in progress - // so it can navigate back to the start page, then reissue a - // fresh QR on the next iteration. - tracing::warn!(?err, "Hybrid error, reissuing QR"); - let _ = tx.send(HybridStateInternal::Restarting).await; + if active { + // Post-active: the phone was engaged — surface the error + // via the Restarting signal so the UI navigates back to + // start_page, then reissue a fresh QR. + tracing::warn!(?err, "Hybrid post-active error, reissuing QR"); + let _ = tx.send(HybridStateInternal::Restarting).await; + } else { + // Pre-active: the QR was never consumed or the BLE channel + // failed before the phone responded. Reissue silently. + tracing::debug!(?err, "Hybrid pre-active error, reissuing QR silently"); + } continue; } } @@ -254,6 +270,7 @@ async fn run_hybrid_ceremony( request: &CredentialRequest, tx: &Sender, cancellation: CancellationToken, + active: &mut bool, ) -> Result { let mut channel = match device.channel(ChannelSettings::default()).await { Ok(channel) => channel, @@ -263,6 +280,11 @@ async fn run_hybrid_ceremony( } }; + // The BLE channel is open, which means the phone has consumed the QR code + // and completed the handshake. Mark this attempt as active so that any + // subsequent error is surfaced to the user rather than silenced. + *active = true; + let state_sender_clone = tx.clone(); let ux_updates_rx = channel.get_ux_update_receiver(); tokio::spawn(async move { diff --git a/credentialsd/src/credential_service/mod.rs b/credentialsd/src/credential_service/mod.rs index fd8189b..54d1dfb 100644 --- a/credentialsd/src/credential_service/mod.rs +++ b/credentialsd/src/credential_service/mod.rs @@ -1628,4 +1628,84 @@ mod tests { service.cancel_request(id).await; } + + /// A non-terminating USB failure after a user-input state (post-active) + /// must surface to the UI. + #[tokio::test] + async fn test_usb_post_active_error_surfaces() { + let usb_handler = CancellationTrackingHandler::::new(); + let usb_ref = usb_handler.get_handler_ref(); + + let service = CredentialService::new(MockHybridHandler, MockNfcHandler, usb_handler); + let request = create_test_request().await; + let (tx, _rx) = oneshot::channel(); + let (id, token) = service.init_request(&request, tx).await.unwrap(); + let mut usb_stream = service.get_usb_credential().await; + + // Activate: user-input required + usb_ref.shift_state(UsbStateInternal::NeedsUserPresence); + assert!(matches!( + usb_stream.next().await, + Some(UsbState::NeedsUserPresence) + )); + + // Non-terminating error after activation — must surface + usb_ref.shift_state(UsbStateInternal::Failed( + CredentialServiceError::AuthenticatorError, + )); + assert!( + matches!( + usb_stream.next().await, + Some(UsbState::Failed(CredentialServiceError::AuthenticatorError)) + ), + "post-active Failed must be forwarded to UI" + ); + assert!(!token.is_cancelled()); + + service.cancel_request(id).await; + } + + /// A non-terminating hybrid failure after Connecting (post-active, phone has + /// consumed the QR) must surface to the UI. + #[tokio::test] + async fn test_hybrid_post_active_error_surfaces() { + let hybrid_handler = CancellationTrackingHandler::::new(); + let hybrid_ref = hybrid_handler.get_handler_ref(); + + let service = CredentialService::new(hybrid_handler, MockNfcHandler, MockUsbHandler); + let request = create_test_request().await; + let (tx, _rx) = oneshot::channel(); + let (id, token) = service.init_request(&request, tx).await.unwrap(); + let mut hybrid_stream = service.get_hybrid_credential().await; + + hybrid_ref.shift_state(HybridStateInternal::Init("qr".to_string())); + assert!(matches!( + hybrid_stream.next().await, + Some(HybridState::Init(_)) + )); + + // Connecting = phone consumed the QR = active + hybrid_ref.shift_state(HybridStateInternal::Connecting); + assert!(matches!( + hybrid_stream.next().await, + Some(HybridState::Connecting) + )); + + // Post-active failure must surface + hybrid_ref.shift_state(HybridStateInternal::Failed( + CredentialServiceError::AuthenticatorError, + )); + assert!( + matches!( + hybrid_stream.next().await, + Some(HybridState::Failed( + CredentialServiceError::AuthenticatorError + )) + ), + "post-active Failed must be forwarded to UI" + ); + assert!(!token.is_cancelled()); + + service.cancel_request(id).await; + } } diff --git a/credentialsd/src/credential_service/nfc.rs b/credentialsd/src/credential_service/nfc.rs index f3ae821..a9a6e42 100644 --- a/credentialsd/src/credential_service/nfc.rs +++ b/credentialsd/src/credential_service/nfc.rs @@ -171,6 +171,7 @@ impl InProcessNfcHandler { cancellation: CancellationToken, ) -> Result<(), CredentialServiceError> { let mut state = NfcStateInternal::Idle; + let mut active = false; let (signal_tx, mut signal_rx) = mpsc::channel(256); let (cred_tx, mut cred_rx) = mpsc::channel(1); debug!("polling for NFC status"); @@ -246,35 +247,75 @@ impl InProcessNfcHandler { std::mem::discriminant(new_state) != std::mem::discriminant(old_state) } }; - // Suppress forwarding a non-terminating Failed state to the UI directly: - // the Restarting state emitted below takes its place with cleaner semantics. - let is_non_terminating_failure = matches!( - &state, - NfcStateInternal::Failed(err) if !super::is_ceremony_terminating(err) - ); - if state_changed && !is_non_terminating_failure { - tracing::debug!("NFC current state: {state:?}"); - tx.send(state.clone()).await.map_err(|_| { - CredentialServiceError::Internal( - "NFC state channel receiver closed prematurely".to_string(), - ) - })?; + // Activate when libwebauthn signals it is waiting for user input. + // The flag is monotonic within a single ceremony attempt; it is reset + // to false when the transport restarts below. + match &state { + NfcStateInternal::NeedsPin { .. } + | NfcStateInternal::PinNotSet { .. } + | NfcStateInternal::NeedsUserVerification { .. } => { + active = true; + } + _ => {} } - // Check for terminal states AFTER sending match state { - NfcStateInternal::Completed(_) => break Ok(()), - NfcStateInternal::Failed(ref err) => { - if super::is_ceremony_terminating(err) { - break Err(err.clone()); + NfcStateInternal::Completed(_) => { + tracing::debug!("NFC current state: {state:?}"); + tx.send(state.clone()).await.map_err(|_| { + CredentialServiceError::Internal( + "NFC state channel receiver closed prematurely".to_string(), + ) + })?; + break Ok(()); + } + + // Catch terminating errors first. Doesn't matter if the user was already engaged + // or not. We have to terminate either way. + NfcStateInternal::Failed(ref err) if super::is_ceremony_terminating(err) => { + if state_changed { + tracing::debug!("NFC current state: {state:?}"); + tx.send(NfcStateInternal::Failed(err.clone())) + .await + .map_err(|_| { + CredentialServiceError::Internal( + "NFC state channel receiver closed prematurely".to_string(), + ) + })?; } - // Non-terminating: notify the UI that a restart is in progress so - // it can navigate back to the start page, then restart polling. + break Err(err.clone()); + } + + // Active non-terminating failure: the user was already engaged, surface + // the error via the Restarting signal so the UI navigates back to + // start_page. + // Reset active here only: the other Failed arms either break + // (so active is moot) or reach this arm with active already false. + NfcStateInternal::Failed(err) if active => { tracing::warn!(?err, "NFC authenticator error, restarting transport"); let _ = tx.send(NfcStateInternal::Restarting).await; + active = false; state = NfcStateInternal::Idle; } - _ => {} + + // Pre-active non-terminating failure: the device errored before the user + // tapped it. Restart silently without any UI notification. + NfcStateInternal::Failed(err) => { + tracing::debug!(?err, "NFC pre-active error, restarting silently"); + state = NfcStateInternal::Idle; + } + + // All other state changes are sent, if they are 'new' + _ => { + if state_changed { + tracing::debug!("NFC current state: {state:?}"); + tx.send(state.clone()).await.map_err(|_| { + CredentialServiceError::Internal( + "NFC state channel receiver closed prematurely".to_string(), + ) + })?; + } + } } } } diff --git a/credentialsd/src/credential_service/usb.rs b/credentialsd/src/credential_service/usb.rs index 1207833..e9f0da1 100644 --- a/credentialsd/src/credential_service/usb.rs +++ b/credentialsd/src/credential_service/usb.rs @@ -275,6 +275,7 @@ impl InProcessUsbHandler { cancellation: CancellationToken, ) -> Result<(), CredentialServiceError> { let mut state = UsbStateInternal::Idle; + let mut active = false; let (signal_tx, mut signal_rx) = mpsc::channel(256); let (cred_tx, mut cred_rx) = mpsc::channel(1); debug!("polling for USB status"); @@ -355,35 +356,76 @@ impl InProcessUsbHandler { std::mem::discriminant(new_state) != std::mem::discriminant(old_state) } }; - // Suppress forwarding a non-terminating Failed state to the UI directly: - // the Restarting state emitted below takes its place with cleaner semantics. - let is_non_terminating_failure = matches!( - &state, - UsbStateInternal::Failed(err) if !super::is_ceremony_terminating(err) - ); - if state_changed && !is_non_terminating_failure { - tracing::debug!("USB current state: {state:?}"); - tx.send(state.clone()).await.map_err(|_| { - CredentialServiceError::Internal( - "USB state channel receiver closed prematurely".to_string(), - ) - })?; + // Activate when libwebauthn signals it is waiting for user input. + // The flag is monotonic within a single ceremony attempt; it is reset + // to false when the transport restarts below. + match &state { + UsbStateInternal::NeedsPin { .. } + | UsbStateInternal::PinNotSet { .. } + | UsbStateInternal::NeedsUserVerification { .. } + | UsbStateInternal::NeedsUserPresence => { + active = true; + } + _ => {} } - // Check for terminal states AFTER sending match state { - UsbStateInternal::Completed(_) => break Ok(()), - UsbStateInternal::Failed(ref err) => { - if super::is_ceremony_terminating(err) { - break Err(err.clone()); + UsbStateInternal::Completed(_) => { + tracing::debug!("USB current state: {state:?}"); + tx.send(state.clone()).await.map_err(|_| { + CredentialServiceError::Internal( + "USB state channel receiver closed prematurely".to_string(), + ) + })?; + break Ok(()); + } + + // Catch terminating errors first. Doesn't matter if the user was already engaged + // or not. We have to terminate either way. + UsbStateInternal::Failed(ref err) if super::is_ceremony_terminating(err) => { + if state_changed { + tracing::debug!("USB current state: {state:?}"); + tx.send(UsbStateInternal::Failed(err.clone())) + .await + .map_err(|_| { + CredentialServiceError::Internal( + "USB state channel receiver closed prematurely".to_string(), + ) + })?; } - // Non-terminating: notify the UI that a restart is in progress so - // it can navigate back to the start page, then restart polling. + break Err(err.clone()); + } + + // Active non-terminating failure: the user was already engaged, surface + // the error via the Restarting signal so the UI navigates back to + // start_page. + // Reset active here only: the other Failed arms either break + // (so active is moot) or reach this arm with active already false. + UsbStateInternal::Failed(err) if active => { tracing::warn!(?err, "USB authenticator error, restarting transport"); let _ = tx.send(UsbStateInternal::Restarting).await; + active = false; state = UsbStateInternal::Idle; } - _ => {} + + // Pre-active non-terminating failure: the device errored before the user + // touched it. Restart silently without any UI notification. + UsbStateInternal::Failed(err) => { + tracing::debug!(?err, "USB pre-active error, restarting silently"); + state = UsbStateInternal::Idle; + } + + // All other state changes are sent, if they are 'new' + _ => { + if state_changed { + tracing::debug!("USB current state: {state:?}"); + tx.send(state.clone()).await.map_err(|_| { + CredentialServiceError::Internal( + "USB state channel receiver closed prematurely".to_string(), + ) + })?; + } + } } } } From b9e8425d9d0dbdab611c84f10bd015844a004dd4 Mon Sep 17 00:00:00 2001 From: Martin Sirringhaus Date: Wed, 9 Sep 2026 16:13:47 +0200 Subject: [PATCH 2/3] Display restart reason as an error message to the user --- CHANGELOG.md | 1 + credentialsd-common/src/model.rs | 59 ++++++++++++++++--- credentialsd-ui/data/resources/ui/window.blp | 11 ++++ credentialsd-ui/src/dbus.rs | 37 ++++++------ credentialsd-ui/src/gui/mod.rs | 7 ++- credentialsd-ui/src/gui/view_model/gtk/mod.rs | 10 +++- credentialsd-ui/src/gui/view_model/mod.rs | 51 +++++++--------- credentialsd/src/credential_service/hybrid.rs | 36 +++++++---- credentialsd/src/credential_service/mod.rs | 19 ++++-- credentialsd/src/credential_service/nfc.rs | 37 +++++++----- credentialsd/src/credential_service/usb.rs | 37 +++++++----- credentialsd/src/dbus/ui_control.rs | 47 ++++++--------- 12 files changed, 218 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e191945..8864b12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - ui: Add Bulgarian translation (Thank you, @salif!) - webext: Try to read app ID from associated desktop entry (Thank you, @michaelbeaumont!) - ui: Basic recovery from failed attempts to use devices (e.g. flaky bluetooth) +- ui: Display restart reason in case of premature failure # 0.3.1 [2026-09-05] diff --git a/credentialsd-common/src/model.rs b/credentialsd-common/src/model.rs index 1c74184..6c43deb 100644 --- a/credentialsd-common/src/model.rs +++ b/credentialsd-common/src/model.rs @@ -8,10 +8,48 @@ pub const BACKGROUND_EVENT_ERROR_INTERNAL: u32 = 0x80000001; pub const BACKGROUND_EVENT_ERROR_TIMED_OUT: u32 = 0x80000002; pub const BACKGROUND_EVENT_ERROR_CANCELLED: u32 = 0x80000003; pub const BACKGROUND_EVENT_ERROR_AUTHENTICATOR: u32 = 0x80000004; -pub const BACKGROUND_EVENT_ERROR_NO_CREDENTIALS: u32 = 0x80000005; pub const BACKGROUND_EVENT_ERROR_CREDENTIAL_EXCLUDED: u32 = 0x80000006; -pub const BACKGROUND_EVENT_ERROR_PIN_ATTEMPTS_EXHAUSTED: u32 = 0x80000007; -pub const BACKGROUND_EVENT_ERROR_PIN_NOT_SET: u32 = 0x80000008; + +/// Machine-readable reason for a transport restart. Shared across all transports. +/// Human-readable strings are built by the UI (gettext). +/// +/// The `#[repr(u8)]` layout doubles as the D-Bus wire format via `From for u8` +/// and `TryFrom for Self`. Discriminants must remain stable across releases. +/// Discriminant 0 is deliberately unused so that an all-zeroed message is recognisable +/// as invalid by `TryFrom`. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TransportRestartReason { + /// The ceremony was interrupted before completing — transport error, + /// user cancelled on their phone/device, or an unrecoverable authenticator + /// error. The user should follow the new prompts to retry. + Interrupted = 1, + /// No matching credentials were found on the device. The user should try + /// a different authenticator. + NoCredentials = 2, + /// Too many incorrect PIN attempts on this device — it is now locked. The + /// user should remove and reinsert the device, or use a different authenticator. + PinAttemptsExhausted = 3, +} + +impl From for u8 { + fn from(value: TransportRestartReason) -> Self { + value as u8 + } +} + +impl TryFrom for TransportRestartReason { + type Error = u8; + + fn try_from(value: u8) -> Result { + match value { + 1 => Ok(Self::Interrupted), + 2 => Ok(Self::NoCredentials), + 3 => Ok(Self::PinAttemptsExhausted), + other => Err(other), + } + } +} /// Credential service events intended to inform the UI. #[derive(Debug, PartialEq)] @@ -38,7 +76,9 @@ pub enum BackgroundEvent { /// The hybrid ceremony was interrupted by a non-terminating error and a new /// QR code is about to be issued. The UI should navigate back to the start /// page so the new QR becomes visible. - HybridRestarting, + HybridRestarting { + reason: TransportRestartReason, + }, NfcIdle, NfcWaiting, @@ -46,7 +86,9 @@ pub enum BackgroundEvent { /// The NFC ceremony was interrupted by a non-terminating error and the /// transport is polling for a new device tap. The UI should navigate back /// to the start page. - NfcRestarting, + NfcRestarting { + reason: TransportRestartReason, + }, UsbIdle, UsbWaiting, @@ -55,16 +97,15 @@ pub enum BackgroundEvent { /// The USB ceremony was interrupted by a non-terminating error and the /// transport is polling for a device. The UI should navigate back to the /// start page. - UsbRestarting, + UsbRestarting { + reason: TransportRestartReason, + }, ErrorInternal, ErrorTimedOut, ErrorCancelled, ErrorAuthenticator, - ErrorNoCredentials, ErrorCredentialExcluded, - ErrorPinAttemptsExhausted, - ErrorPinNotSet, } /// Emitted when a client enters a PIN for the selected authenticator. diff --git a/credentialsd-ui/data/resources/ui/window.blp b/credentialsd-ui/data/resources/ui/window.blp index 70f62de..c4601aa 100644 --- a/credentialsd-ui/data/resources/ui/window.blp +++ b/credentialsd-ui/data/resources/ui/window.blp @@ -154,6 +154,17 @@ template $CredentialsUiWindow: ApplicationWindow { wrap: true; } } + + Label { + label: bind template.view-model as <$CredentialManagerViewModel>.restart_message; + visible: bind template.view-model as <$CredentialManagerViewModel>.restart_message_visible; + margin-top: 16; + margin-start: 24; + margin-end: 24; + margin-bottom: 8; + wrap: true; + styles ["error"] + } }; } diff --git a/credentialsd-ui/src/dbus.rs b/credentialsd-ui/src/dbus.rs index 7f10823..cce23ce 100644 --- a/credentialsd-ui/src/dbus.rs +++ b/credentialsd-ui/src/dbus.rs @@ -25,15 +25,14 @@ use zbus::{ use credentialsd_common::model::{ BACKGROUND_EVENT_ERROR_AUTHENTICATOR, BACKGROUND_EVENT_ERROR_CANCELLED, BACKGROUND_EVENT_ERROR_CREDENTIAL_EXCLUDED, BACKGROUND_EVENT_ERROR_INTERNAL, - BACKGROUND_EVENT_ERROR_NO_CREDENTIALS, BACKGROUND_EVENT_ERROR_PIN_ATTEMPTS_EXHAUSTED, - BACKGROUND_EVENT_ERROR_PIN_NOT_SET, BACKGROUND_EVENT_ERROR_TIMED_OUT, BackgroundEvent, - ClientPinEnteredOptions, Credential, CredentialSelectedOptions, Device, - DiscoveryRequestedOptions, NotifyHybridConnectedOptions, NotifyHybridConnectingOptions, - NotifyHybridRestartingOptions, NotifyHybridStartedOptions, NotifyNeedsPinOptions, - NotifyNeedsUserPresenceOptions, NotifyNeedsUserVerificationOptions, NotifyNfcConnectedOptions, - NotifyNfcRestartingOptions, NotifyPinNotSetOptions, NotifySelectingCredentialOptions, - NotifyUsbConnectedOptions, NotifyUsbRestartingOptions, Operation, PinNotSetError, - PortalBackendOptions, SetDevicePinOptions, UserInteractedEvent, WindowHandle, + BACKGROUND_EVENT_ERROR_TIMED_OUT, BackgroundEvent, ClientPinEnteredOptions, Credential, + CredentialSelectedOptions, Device, DiscoveryRequestedOptions, NotifyHybridConnectedOptions, + NotifyHybridConnectingOptions, NotifyHybridRestartingOptions, NotifyHybridStartedOptions, + NotifyNeedsPinOptions, NotifyNeedsUserPresenceOptions, NotifyNeedsUserVerificationOptions, + NotifyNfcConnectedOptions, NotifyNfcRestartingOptions, NotifyPinNotSetOptions, + NotifySelectingCredentialOptions, NotifyUsbConnectedOptions, NotifyUsbRestartingOptions, + Operation, PinNotSetError, PortalBackendOptions, SetDevicePinOptions, TransportRestartReason, + UserInteractedEvent, WindowHandle, }; use crate::{RequestingApplication, ViewRequest, client::FlowControlClient}; @@ -312,12 +311,15 @@ impl CredentialPortalBackend { &self, #[zbus(object_server)] object_server: &ObjectServer, session_handle: ObjectPath<'_>, + reason: u8, _options: NotifyHybridRestartingOptions, ) -> fdo::Result<()> { + let reason = + TransportRestartReason::try_from(reason).unwrap_or(TransportRestartReason::Interrupted); self.notify_state_changed( object_server, session_handle, - BackgroundEvent::HybridRestarting, + BackgroundEvent::HybridRestarting { reason }, ) .await } @@ -326,12 +328,15 @@ impl CredentialPortalBackend { &self, #[zbus(object_server)] object_server: &ObjectServer, session_handle: ObjectPath<'_>, + reason: u8, _options: NotifyUsbRestartingOptions, ) -> fdo::Result<()> { + let reason = + TransportRestartReason::try_from(reason).unwrap_or(TransportRestartReason::Interrupted); self.notify_state_changed( object_server, session_handle, - BackgroundEvent::UsbRestarting, + BackgroundEvent::UsbRestarting { reason }, ) .await } @@ -340,12 +345,15 @@ impl CredentialPortalBackend { &self, #[zbus(object_server)] object_server: &ObjectServer, session_handle: ObjectPath<'_>, + reason: u8, _options: NotifyNfcRestartingOptions, ) -> fdo::Result<()> { + let reason = + TransportRestartReason::try_from(reason).unwrap_or(TransportRestartReason::Interrupted); self.notify_state_changed( object_server, session_handle, - BackgroundEvent::NfcRestarting, + BackgroundEvent::NfcRestarting { reason }, ) .await } @@ -376,14 +384,9 @@ impl CredentialPortalBackend { BACKGROUND_EVENT_ERROR_TIMED_OUT => Ok(BackgroundEvent::ErrorTimedOut), BACKGROUND_EVENT_ERROR_CANCELLED => Ok(BackgroundEvent::ErrorCancelled), BACKGROUND_EVENT_ERROR_AUTHENTICATOR => Ok(BackgroundEvent::ErrorAuthenticator), - BACKGROUND_EVENT_ERROR_NO_CREDENTIALS => Ok(BackgroundEvent::ErrorNoCredentials), BACKGROUND_EVENT_ERROR_CREDENTIAL_EXCLUDED => { Ok(BackgroundEvent::ErrorCredentialExcluded) } - BACKGROUND_EVENT_ERROR_PIN_ATTEMPTS_EXHAUSTED => { - Ok(BackgroundEvent::ErrorPinAttemptsExhausted) - } - BACKGROUND_EVENT_ERROR_PIN_NOT_SET => Ok(BackgroundEvent::ErrorPinNotSet), _ => Err(fdo::Error::Failed("Unknown error code".to_string())), }?; self.notify_state_changed(object_server, session_handle, error_event) diff --git a/credentialsd-ui/src/gui/mod.rs b/credentialsd-ui/src/gui/mod.rs index e55ada9..b3bc3e3 100644 --- a/credentialsd-ui/src/gui/mod.rs +++ b/credentialsd-ui/src/gui/mod.rs @@ -96,8 +96,11 @@ pub enum ViewUpdate { HybridConnected, /// A transport ceremony was interrupted by a non-terminating error and - /// is restarting. The UI should navigate back to the start page. - TransportRestarting, + /// is restarting. The UI should navigate back to the start page and display + /// the provided localized message. + TransportRestarting { + message: String, + }, Completed, Cancelled, diff --git a/credentialsd-ui/src/gui/view_model/gtk/mod.rs b/credentialsd-ui/src/gui/view_model/gtk/mod.rs index 76afc9e..c8dd76c 100644 --- a/credentialsd-ui/src/gui/view_model/gtk/mod.rs +++ b/credentialsd-ui/src/gui/view_model/gtk/mod.rs @@ -87,6 +87,12 @@ mod imp { #[property(get, set)] pub transport_restarting: RefCell, + #[property(get, set)] + pub restart_message: RefCell, + + #[property(get, set)] + pub restart_message_visible: RefCell, + #[property(get, set)] pub start_setting_new_pin_visible: RefCell, @@ -243,12 +249,14 @@ impl ViewModel { )); view_model.set_qr_spinner_visible(false); } - ViewUpdate::TransportRestarting => { + ViewUpdate::TransportRestarting { message } => { // Signal the window to navigate back to start_page. // The transport will emit a fresh Init/Connected state // next, which will update the prompt and show the new // QR code or device-waiting UI from start_page. view_model.set_qr_spinner_visible(false); + view_model.set_restart_message(message); + view_model.set_restart_message_visible(true); view_model.set_transport_restarting(true); } ViewUpdate::Completed => { diff --git a/credentialsd-ui/src/gui/view_model/mod.rs b/credentialsd-ui/src/gui/view_model/mod.rs index 6cf331b..c216c3c 100644 --- a/credentialsd-ui/src/gui/view_model/mod.rs +++ b/credentialsd-ui/src/gui/view_model/mod.rs @@ -8,7 +8,7 @@ use async_std::{ sync::Mutex as AsyncMutex, }; use credentialsd_common::memfd::read_secret; -use credentialsd_common::model::{BackgroundEvent, Credential}; +use credentialsd_common::model::{BackgroundEvent, Credential, TransportRestartReason}; use gettextrs::gettext; use serde::{Deserialize, Serialize}; use tracing::{error, info}; @@ -252,31 +252,7 @@ impl ViewModel { .await .unwrap(); } - Event::Background(BackgroundEvent::ErrorNoCredentials) => { - let error_msg = gettext("No matching credentials found on this authenticator."); - self.tx_update - .send(ViewUpdate::Failed(error_msg)) - .await - .unwrap() - } - Event::Background(BackgroundEvent::ErrorPinAttemptsExhausted) => { - let error_msg = gettext( - "No more PIN attempts allowed. Try removing your device and plugging it back in.", - ); - self.tx_update - .send(ViewUpdate::Failed(error_msg)) - .await - .unwrap() - } - Event::Background(BackgroundEvent::ErrorPinNotSet) => { - let error_msg = gettext( - "This server requires your device to have additional protection like a PIN, which is not set. Please set a PIN for this device and try again.", - ); - self.tx_update - .send(ViewUpdate::Failed(error_msg)) - .await - .unwrap() - } + Event::Background(BackgroundEvent::ErrorTimedOut) => { let error_msg = gettext("The credential request timed out. Please try again."); self.tx_update @@ -349,13 +325,14 @@ impl ViewModel { .unwrap(); } Event::Background( - BackgroundEvent::HybridRestarting - | BackgroundEvent::UsbRestarting - | BackgroundEvent::NfcRestarting, + BackgroundEvent::HybridRestarting { reason } + | BackgroundEvent::UsbRestarting { reason } + | BackgroundEvent::NfcRestarting { reason }, ) => { self.hybrid_qr_code_data = None; + let message = localized_transport_restart_reason(&reason); self.tx_update - .send(ViewUpdate::TransportRestarting) + .send(ViewUpdate::TransportRestarting { message }) .await .unwrap(); } @@ -391,6 +368,20 @@ impl Debug for ViewEvent { } } +fn localized_transport_restart_reason(reason: &TransportRestartReason) -> String { + match reason { + TransportRestartReason::Interrupted => gettext( + "The previous attempt was interrupted. Please follow the new prompts to try again.", + ), + TransportRestartReason::NoCredentials => { + gettext("No matching credentials on this authenticator. Please try a different one.") + } + TransportRestartReason::PinAttemptsExhausted => gettext( + "No more PIN attempts allowed. Remove and reinsert your device, or use a different authenticator.", + ), + } +} + #[derive(Debug)] pub enum Event { Background(BackgroundEvent), diff --git a/credentialsd/src/credential_service/hybrid.rs b/credentialsd/src/credential_service/hybrid.rs index f5b1536..96eca9a 100644 --- a/credentialsd/src/credential_service/hybrid.rs +++ b/credentialsd/src/credential_service/hybrid.rs @@ -22,7 +22,10 @@ use tokio_util::sync::CancellationToken; use tracing::{debug, error}; use super::CredentialServiceError; -use credentialsd_common::{memfd::write_secret, model::BackgroundEvent}; +use credentialsd_common::{ + memfd::write_secret, + model::{BackgroundEvent, TransportRestartReason}, +}; use crate::model::{CredentialRequest, CredentialResponse}; @@ -132,8 +135,17 @@ impl HybridHandler for InternalHybridHandler { // Post-active: the phone was engaged — surface the error // via the Restarting signal so the UI navigates back to // start_page, then reissue a fresh QR. + let reason = match err { + CredentialServiceError::NoCredentials => { + TransportRestartReason::NoCredentials + } + CredentialServiceError::PinAttemptsExhausted => { + TransportRestartReason::PinAttemptsExhausted + } + _ => TransportRestartReason::Interrupted, + }; tracing::warn!(?err, "Hybrid post-active error, reissuing QR"); - let _ = tx.send(HybridStateInternal::Restarting).await; + let _ = tx.send(HybridStateInternal::Restarting(reason)).await; } else { // Pre-active: the QR was never consumed or the BLE channel // failed before the phone responded. Reissue silently. @@ -172,7 +184,7 @@ pub(super) enum HybridStateInternal { /// The ceremony was interrupted by a non-terminating error. A fresh QR code /// is about to be issued on the next iteration. - Restarting, + Restarting(TransportRestartReason), } // this is here to prevent making HybridStateInternal public to the whole crate. @@ -202,7 +214,7 @@ pub enum HybridState { /// The ceremony was interrupted by a non-terminating error and a new QR /// code is being issued. The UI should navigate back to the start page. - Restarting, + Restarting(TransportRestartReason), } impl From for HybridState { @@ -213,7 +225,7 @@ impl From for HybridState { HybridStateInternal::Connected => HybridState::Connected, HybridStateInternal::Completed(_) => HybridState::Completed, HybridStateInternal::Failed(err) => HybridState::Failed(err), - HybridStateInternal::Restarting => HybridState::Restarting, + HybridStateInternal::Restarting(reason) => HybridState::Restarting(reason), } } } @@ -235,24 +247,22 @@ impl From<&HybridState> for BackgroundEvent { HybridState::Connecting => BackgroundEvent::HybridConnecting, HybridState::Connected => BackgroundEvent::HybridConnected, HybridState::Completed => BackgroundEvent::CeremonyCompleted, - HybridState::Restarting => BackgroundEvent::HybridRestarting, + HybridState::Restarting(reason) => { + BackgroundEvent::HybridRestarting { reason: *reason } + } HybridState::Failed(CredentialServiceError::AuthenticatorError) => { BackgroundEvent::ErrorAuthenticator } - HybridState::Failed(CredentialServiceError::NoCredentials) => { - BackgroundEvent::ErrorNoCredentials - } HybridState::Failed(CredentialServiceError::CredentialExcluded) => { BackgroundEvent::ErrorCredentialExcluded } - HybridState::Failed(CredentialServiceError::PinAttemptsExhausted) => { - BackgroundEvent::ErrorAuthenticator - } // This should currently never be reached, but we'll likely use it in future refactoring HybridState::Failed(CredentialServiceError::NonTerminatingCancellation) => { BackgroundEvent::ErrorCancelled } - HybridState::Failed(CredentialServiceError::Internal(_)) => { + HybridState::Failed(CredentialServiceError::Internal(_)) + | HybridState::Failed(CredentialServiceError::NoCredentials) + | HybridState::Failed(CredentialServiceError::PinAttemptsExhausted) => { BackgroundEvent::ErrorInternal } } diff --git a/credentialsd/src/credential_service/mod.rs b/credentialsd/src/credential_service/mod.rs index 54d1dfb..ac30c89 100644 --- a/credentialsd/src/credential_service/mod.rs +++ b/credentialsd/src/credential_service/mod.rs @@ -621,6 +621,7 @@ impl From for AuthenticatorResponse { #[cfg(test)] mod tests { use super::*; + use credentialsd_common::model::TransportRestartReason; use std::time::Duration; // Mock handlers for testing @@ -1590,9 +1591,14 @@ mod tests { let (id, token) = service.init_request(&request, tx).await.unwrap(); let mut hybrid_stream = service.get_hybrid_credential().await; - hybrid_ref.shift_state(HybridStateInternal::Restarting); + hybrid_ref.shift_state(HybridStateInternal::Restarting( + TransportRestartReason::Interrupted, + )); assert!( - matches!(hybrid_stream.next().await, Some(HybridState::Restarting)), + matches!( + hybrid_stream.next().await, + Some(HybridState::Restarting(TransportRestartReason::Interrupted)) + ), "Restarting state must be forwarded to the UI stream" ); assert!( @@ -1616,9 +1622,14 @@ mod tests { let (id, token) = service.init_request(&request, tx).await.unwrap(); let mut usb_stream = service.get_usb_credential().await; - usb_ref.shift_state(UsbStateInternal::Restarting); + usb_ref.shift_state(UsbStateInternal::Restarting( + TransportRestartReason::Interrupted, + )); assert!( - matches!(usb_stream.next().await, Some(UsbState::Restarting)), + matches!( + usb_stream.next().await, + Some(UsbState::Restarting(TransportRestartReason::Interrupted)) + ), "Restarting state must be forwarded to the UI stream" ); assert!( diff --git a/credentialsd/src/credential_service/nfc.rs b/credentialsd/src/credential_service/nfc.rs index a9a6e42..00b835b 100644 --- a/credentialsd/src/credential_service/nfc.rs +++ b/credentialsd/src/credential_service/nfc.rs @@ -16,7 +16,9 @@ use tokio::sync::mpsc::{self, Receiver, Sender, WeakSender}; use tokio_util::sync::CancellationToken; use tracing::{debug, warn}; -use credentialsd_common::model::{BackgroundEvent, Credential, PinNotSetError}; +use credentialsd_common::model::{ + BackgroundEvent, Credential, PinNotSetError, TransportRestartReason, +}; use crate::model::{CredentialRequest, GetAssertionResponseInternal}; @@ -213,7 +215,7 @@ impl InProcessNfcHandler { // state, but we cover it here for exhaustiveness. NfcStateInternal::Completed(_) | NfcStateInternal::Failed(_) - | NfcStateInternal::Restarting => Ok(prev_nfc_state.clone()), + | NfcStateInternal::Restarting(_) => Ok(prev_nfc_state.clone()), } }; @@ -292,8 +294,17 @@ impl InProcessNfcHandler { // Reset active here only: the other Failed arms either break // (so active is moot) or reach this arm with active already false. NfcStateInternal::Failed(err) if active => { + let reason = match err { + CredentialServiceError::NoCredentials => { + TransportRestartReason::NoCredentials + } + CredentialServiceError::PinAttemptsExhausted => { + TransportRestartReason::PinAttemptsExhausted + } + _ => TransportRestartReason::Interrupted, + }; tracing::warn!(?err, "NFC authenticator error, restarting transport"); - let _ = tx.send(NfcStateInternal::Restarting).await; + let _ = tx.send(NfcStateInternal::Restarting(reason)).await; active = false; state = NfcStateInternal::Idle; } @@ -502,7 +513,7 @@ pub(super) enum NfcStateInternal { /// The ceremony was interrupted by a non-terminating error and the transport /// is restarting. The UI should navigate back to the start page. - Restarting, + Restarting(TransportRestartReason), } /// Used to share public state between credential service and UI. @@ -548,7 +559,7 @@ pub enum NfcState { /// The ceremony was interrupted by a non-terminating error and the transport /// is restarting. The UI should navigate back to the start page. - Restarting, + Restarting(TransportRestartReason), } impl From for NfcState { @@ -571,7 +582,7 @@ impl From for NfcState { NfcState::NeedsUserVerification { attempts_left } } NfcStateInternal::Completed(_) => NfcState::Completed, - NfcStateInternal::Restarting => NfcState::Restarting, + NfcStateInternal::Restarting(reason) => NfcState::Restarting(reason), NfcStateInternal::SelectCredential { response, cred_tx } => { NfcState::SelectingCredential { creds: response @@ -640,20 +651,18 @@ impl From<&NfcState> for BackgroundEvent { NfcState::Failed(CredentialServiceError::AuthenticatorError) => { BackgroundEvent::ErrorAuthenticator } - NfcState::Failed(CredentialServiceError::NoCredentials) => { - BackgroundEvent::ErrorNoCredentials - } NfcState::Failed(CredentialServiceError::CredentialExcluded) => { BackgroundEvent::ErrorCredentialExcluded } - NfcState::Failed(CredentialServiceError::PinAttemptsExhausted) => { - BackgroundEvent::ErrorAuthenticator - } NfcState::Failed(CredentialServiceError::NonTerminatingCancellation) => { BackgroundEvent::ErrorCancelled } - NfcState::Failed(CredentialServiceError::Internal(_)) => BackgroundEvent::ErrorInternal, - NfcState::Restarting => BackgroundEvent::NfcRestarting, + NfcState::Failed(CredentialServiceError::Internal(_)) + | NfcState::Failed(CredentialServiceError::NoCredentials) + | NfcState::Failed(CredentialServiceError::PinAttemptsExhausted) => { + BackgroundEvent::ErrorInternal + } + NfcState::Restarting(reason) => BackgroundEvent::NfcRestarting { reason: *reason }, } } } diff --git a/credentialsd/src/credential_service/usb.rs b/credentialsd/src/credential_service/usb.rs index e9f0da1..a9a8c3a 100644 --- a/credentialsd/src/credential_service/usb.rs +++ b/credentialsd/src/credential_service/usb.rs @@ -21,7 +21,9 @@ use tokio::sync::{ use tokio_util::sync::CancellationToken; use tracing::{debug, warn}; -use credentialsd_common::model::{BackgroundEvent, Credential, PinNotSetError}; +use credentialsd_common::model::{ + BackgroundEvent, Credential, PinNotSetError, TransportRestartReason, +}; use crate::model::{CredentialRequest, GetAssertionResponseInternal}; @@ -321,7 +323,7 @@ impl InProcessUsbHandler { // state, but we cover it here for exhaustiveness. UsbStateInternal::Completed(_) | UsbStateInternal::Failed(_) - | UsbStateInternal::Restarting => Ok(prev_usb_state.clone()), + | UsbStateInternal::Restarting(_) => Ok(prev_usb_state.clone()), } }; @@ -402,8 +404,17 @@ impl InProcessUsbHandler { // Reset active here only: the other Failed arms either break // (so active is moot) or reach this arm with active already false. UsbStateInternal::Failed(err) if active => { + let reason = match err { + CredentialServiceError::NoCredentials => { + TransportRestartReason::NoCredentials + } + CredentialServiceError::PinAttemptsExhausted => { + TransportRestartReason::PinAttemptsExhausted + } + _ => TransportRestartReason::Interrupted, + }; tracing::warn!(?err, "USB authenticator error, restarting transport"); - let _ = tx.send(UsbStateInternal::Restarting).await; + let _ = tx.send(UsbStateInternal::Restarting(reason)).await; active = false; state = UsbStateInternal::Idle; } @@ -614,7 +625,7 @@ pub(super) enum UsbStateInternal { /// The ceremony was interrupted by a non-terminating error and the transport /// is restarting. The UI should navigate back to the start page. - Restarting, + Restarting(TransportRestartReason), } /// Used to share public state between credential service and UI. @@ -669,7 +680,7 @@ pub enum UsbState { /// The ceremony was interrupted by a non-terminating error and the transport /// is restarting. The UI should navigate back to the start page. - Restarting, + Restarting(TransportRestartReason), } impl From for UsbState { @@ -727,7 +738,7 @@ impl From for UsbState { } } UsbStateInternal::Failed(err) => UsbState::Failed(err), - UsbStateInternal::Restarting => UsbState::Restarting, + UsbStateInternal::Restarting(reason) => UsbState::Restarting(reason), } } } @@ -765,20 +776,18 @@ impl From<&UsbState> for BackgroundEvent { UsbState::Failed(CredentialServiceError::AuthenticatorError) => { BackgroundEvent::ErrorAuthenticator } - UsbState::Failed(CredentialServiceError::NoCredentials) => { - BackgroundEvent::ErrorNoCredentials - } UsbState::Failed(CredentialServiceError::CredentialExcluded) => { BackgroundEvent::ErrorCredentialExcluded } - UsbState::Failed(CredentialServiceError::PinAttemptsExhausted) => { - BackgroundEvent::ErrorAuthenticator - } UsbState::Failed(CredentialServiceError::NonTerminatingCancellation) => { BackgroundEvent::ErrorCancelled } - UsbState::Failed(CredentialServiceError::Internal(_)) => BackgroundEvent::ErrorInternal, - UsbState::Restarting => BackgroundEvent::UsbRestarting, + UsbState::Failed(CredentialServiceError::Internal(_)) + | UsbState::Failed(CredentialServiceError::NoCredentials) + | UsbState::Failed(CredentialServiceError::PinAttemptsExhausted) => { + BackgroundEvent::ErrorInternal + } + UsbState::Restarting(reason) => BackgroundEvent::UsbRestarting { reason: *reason }, } } } diff --git a/credentialsd/src/dbus/ui_control.rs b/credentialsd/src/dbus/ui_control.rs index 921ef61..dcde77a 100644 --- a/credentialsd/src/dbus/ui_control.rs +++ b/credentialsd/src/dbus/ui_control.rs @@ -18,15 +18,14 @@ use zbus::{ use credentialsd_common::model::{ BACKGROUND_EVENT_ERROR_AUTHENTICATOR, BACKGROUND_EVENT_ERROR_CANCELLED, BACKGROUND_EVENT_ERROR_CREDENTIAL_EXCLUDED, BACKGROUND_EVENT_ERROR_INTERNAL, - BACKGROUND_EVENT_ERROR_NO_CREDENTIALS, BACKGROUND_EVENT_ERROR_PIN_ATTEMPTS_EXHAUSTED, - BACKGROUND_EVENT_ERROR_PIN_NOT_SET, BACKGROUND_EVENT_ERROR_TIMED_OUT, BackgroundEvent, - ClientPinEnteredOptions, Credential, CredentialSelectedOptions, Device, - DiscoveryRequestedOptions, NotifyHybridConnectedOptions, NotifyHybridConnectingOptions, - NotifyHybridRestartingOptions, NotifyHybridStartedOptions, NotifyNeedsPinOptions, - NotifyNeedsUserPresenceOptions, NotifyNeedsUserVerificationOptions, NotifyNfcConnectedOptions, - NotifyNfcRestartingOptions, NotifyPinNotSetOptions, NotifySelectingCredentialOptions, - NotifyUsbConnectedOptions, NotifyUsbRestartingOptions, Operation, PinNotSetError, - PortalBackendOptions, SetDevicePinOptions, UserInteractedEvent, WindowHandle, + BACKGROUND_EVENT_ERROR_TIMED_OUT, BackgroundEvent, ClientPinEnteredOptions, Credential, + CredentialSelectedOptions, Device, DiscoveryRequestedOptions, NotifyHybridConnectedOptions, + NotifyHybridConnectingOptions, NotifyHybridRestartingOptions, NotifyHybridStartedOptions, + NotifyNeedsPinOptions, NotifyNeedsUserPresenceOptions, NotifyNeedsUserVerificationOptions, + NotifyNfcConnectedOptions, NotifyNfcRestartingOptions, NotifyPinNotSetOptions, + NotifySelectingCredentialOptions, NotifyUsbConnectedOptions, NotifyUsbRestartingOptions, + Operation, PinNotSetError, PortalBackendOptions, SetDevicePinOptions, UserInteractedEvent, + WindowHandle, }; /// Used by the credential service to control the UI. @@ -153,6 +152,7 @@ trait UiControlService { async fn notify_hybrid_restarting( &self, session_handle: ObjectPath<'_>, + reason: u8, _options: NotifyHybridRestartingOptions, ) -> fdo::Result<()>; @@ -160,6 +160,7 @@ trait UiControlService { async fn notify_usb_restarting( &self, session_handle: ObjectPath<'_>, + reason: u8, _options: NotifyUsbRestartingOptions, ) -> fdo::Result<()>; @@ -167,6 +168,7 @@ trait UiControlService { async fn notify_nfc_restarting( &self, session_handle: ObjectPath<'_>, + reason: u8, _options: NotifyNfcRestartingOptions, ) -> fdo::Result<()>; @@ -321,26 +323,29 @@ impl Ceremony { ) .await } - BackgroundEvent::HybridRestarting => { + BackgroundEvent::HybridRestarting { reason } => { self.proxy .notify_hybrid_restarting( self.session_handle.as_ref(), + u8::from(reason), NotifyHybridRestartingOptions {}, ) .await } - BackgroundEvent::UsbRestarting => { + BackgroundEvent::UsbRestarting { reason } => { self.proxy .notify_usb_restarting( self.session_handle.as_ref(), + u8::from(reason), NotifyUsbRestartingOptions {}, ) .await } - BackgroundEvent::NfcRestarting => { + BackgroundEvent::NfcRestarting { reason } => { self.proxy .notify_nfc_restarting( self.session_handle.as_ref(), + u8::from(reason), NotifyNfcRestartingOptions {}, ) .await @@ -370,30 +375,12 @@ impl Ceremony { .notify_error_occurred(self.session_handle.as_ref(), error) .await } - BackgroundEvent::ErrorNoCredentials => { - let error = BACKGROUND_EVENT_ERROR_NO_CREDENTIALS; - self.proxy - .notify_error_occurred(self.session_handle.as_ref(), error) - .await - } BackgroundEvent::ErrorCredentialExcluded => { let error = BACKGROUND_EVENT_ERROR_CREDENTIAL_EXCLUDED; self.proxy .notify_error_occurred(self.session_handle.as_ref(), error) .await } - BackgroundEvent::ErrorPinAttemptsExhausted => { - let error = BACKGROUND_EVENT_ERROR_PIN_ATTEMPTS_EXHAUSTED; - self.proxy - .notify_error_occurred(self.session_handle.as_ref(), error) - .await - } - BackgroundEvent::ErrorPinNotSet => { - let error = BACKGROUND_EVENT_ERROR_PIN_NOT_SET; - self.proxy - .notify_error_occurred(self.session_handle.as_ref(), error) - .await - } BackgroundEvent::CeremonyCompleted => { self.proxy .notify_ceremony_completed(self.session_handle.as_ref()) From 852e47b9ff2e391f0287ceeff4a397386c27afb4 Mon Sep 17 00:00:00 2001 From: Martin Sirringhaus Date: Wed, 9 Sep 2026 16:36:11 +0200 Subject: [PATCH 3/3] Update language files --- credentialsd-ui/po/credentialsd-ui.pot | 157 +++++++++++++-------- credentialsd-ui/po/de_DE.po | 180 ++++++++++++++++--------- credentialsd-ui/po/en_US.po | 177 +++++++++++++++--------- credentialsd-ui/po/ka_GE.po | 178 +++++++++++++++--------- 4 files changed, 453 insertions(+), 239 deletions(-) diff --git a/credentialsd-ui/po/credentialsd-ui.pot b/credentialsd-ui/po/credentialsd-ui.pot index 5ed55b7..d1a35fc 100644 --- a/credentialsd-ui/po/credentialsd-ui.pot +++ b/credentialsd-ui/po/credentialsd-ui.pot @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: credentialsd-ui\n" "Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/" "issues\"\n" -"POT-Creation-Date: 2026-06-18 07:18-0500\n" +"POT-Creation-Date: 2026-09-09 15:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -37,8 +37,7 @@ msgid "Registering a credential" msgstr "" #. developer_name tag deprecated with Appstream 1.0 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:36 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:39 +#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:38 msgid "Isaiah Inuwa" msgstr "" @@ -54,82 +53,133 @@ msgstr "" msgid "Use your security key" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:162 +#: credentialsd-ui/data/resources/ui/window.blp:173 msgid "Connect a security key" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:197 +#: credentialsd-ui/data/resources/ui/window.blp:208 msgid "Enter your device PIN" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:205 +#: credentialsd-ui/data/resources/ui/window.blp:217 msgid "Scan the QR code to connect your device" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:247 -#: credentialsd-ui/data/resources/ui/window.blp:253 +#: credentialsd-ui/data/resources/ui/window.blp:259 +#: credentialsd-ui/data/resources/ui/window.blp:265 msgid "Choose credential" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:266 +#: credentialsd-ui/data/resources/ui/window.blp:278 +msgid "Set a PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:301 +msgid "Please choose a new PIN for your device." +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:314 +msgid "New PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:321 +msgid "Confirm PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:333 +#: credentialsd-ui/data/resources/ui/window.blp:404 +msgid "Close" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:338 +msgid "Continue" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:353 msgid "Complete" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:288 +#: credentialsd-ui/data/resources/ui/window.blp:375 msgid "Done!" msgstr "" -#: credentialsd-ui/data/resources/ui/window.blp:299 +#: credentialsd-ui/data/resources/ui/window.blp:386 msgid "Something went wrong." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:159 +#: credentialsd-ui/data/resources/ui/window.blp:409 +msgid "Set PIN on device" +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:177 msgid "Enter your PIN. One attempt remaining." msgid_plural "Enter your PIN. %d attempts remaining." msgstr[0] "" msgstr[1] "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:165 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:183 msgid "Enter your PIN." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:174 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:192 msgid "Touch your device again. One attempt remaining." msgid_plural "Touch your device again. %d attempts remaining." msgstr[0] "" msgstr[1] "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:180 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:198 msgid "Touch your device." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:185 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:203 msgid "Touch your device" msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:188 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:210 +msgid "" +"This server requires your device to have additional protection like a PIN, " +"which is not set. Please set a PIN for this device and try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:214 +msgid "" +"The entered PIN violates the PIN-policy of this device (likely too short). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:217 +msgid "" +"The entered PIN violates the PIN-policy of this device (PIN too long). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:220 +msgid "A PIN change is required by your device to continue." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:227 msgid "Scan the QR code with your device to begin authentication." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:201 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:240 msgid "" "Connecting to your device. Make sure both devices are near each other and " "have Bluetooth enabled." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:209 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:248 msgid "Device connected. Follow the instructions on your device" msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:298 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:347 msgid "Insert your security key." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:317 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:366 msgid "Multiple devices found. Please select with which to proceed." msgstr "" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:362 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:415 msgid "Credential Manager" msgstr "" @@ -157,81 +207,80 @@ msgstr "" msgid "A security key (USB)" msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:64 +#: credentialsd-ui/src/gui/view_model/mod.rs:62 msgid "unknown application" msgstr "" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:80 +#: credentialsd-ui/src/gui/view_model/mod.rs:76 msgid "Create a passkey for %s1" msgstr "" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:84 +#: credentialsd-ui/src/gui/view_model/mod.rs:80 msgid "Use a passkey for %s1" msgstr "" #. TRANSLATORS: %s1 is the "relying party" (e.g.: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:96 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:91 msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to create a " -"credential to register at \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to create a credential to register at " +"\"%s1\". Only proceed if you trust this process." msgstr "" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:103 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:97 msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to use a credential " -"to sign in to \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to use a credential to sign in to \"%s1\". " +"Only proceed if you trust this process." msgstr "" #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:115 +#: credentialsd-ui/src/gui/view_model/mod.rs:108 msgid "" "Scan the QR code using the camera on the device that has the passkey for %s1" msgstr "" #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:118 +#: credentialsd-ui/src/gui/view_model/mod.rs:111 msgid "Insert and activate your security key to use it for %s1" msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:181 +#: credentialsd-ui/src/gui/view_model/mod.rs:193 msgid "Failed to select credential from device." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:237 -msgid "No matching credentials found on this authenticator." +#: credentialsd-ui/src/gui/view_model/mod.rs:257 +msgid "The credential request timed out. Please try again." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:245 +#: credentialsd-ui/src/gui/view_model/mod.rs:267 msgid "" -"No more PIN attempts allowed. Try removing your device and plugging it back " -"in." +"Something went wrong while retrieving a credential. Please try again later " +"or use a different authenticator." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:254 -msgid "" -"This server requires your device to have additional protection like a PIN, " -"which is not set. Please set a PIN for this device and try again." +#: credentialsd-ui/src/gui/view_model/mod.rs:276 +msgid "This credential is already registered on this authenticator." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:262 -msgid "The credential request timed out. Please try again." +#: credentialsd-ui/src/gui/view_model/mod.rs:374 +msgid "" +"The previous attempt was interrupted. Please follow the new prompts to try " +"again." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:272 +#: credentialsd-ui/src/gui/view_model/mod.rs:377 msgid "" -"Something went wrong while retrieving a credential. Please try again later " -"or use a different authenticator." +"No matching credentials on this authenticator. Please try a different one." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:281 -msgid "This credential is already registered on this authenticator." +#: credentialsd-ui/src/gui/view_model/mod.rs:380 +msgid "" +"No more PIN attempts allowed. Remove and reinsert your device, or use a " +"different authenticator." msgstr "" diff --git a/credentialsd-ui/po/de_DE.po b/credentialsd-ui/po/de_DE.po index 7243f73..86ca6f6 100644 --- a/credentialsd-ui/po/de_DE.po +++ b/credentialsd-ui/po/de_DE.po @@ -3,7 +3,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/" "issues\"\n" -"POT-Creation-Date: 2026-06-18 07:18-0500\n" +"POT-Creation-Date: 2026-09-09 15:53+0200\n" "PO-Revision-Date: 2025-10-10 14:45+0200\n" "Last-Translator: Martin Sirringhaus \n" "Language: de_DE\n" @@ -32,8 +32,7 @@ msgid "Registering a credential" msgstr "Zugangsdaten registrieren" #. developer_name tag deprecated with Appstream 1.0 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:36 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:39 +#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:38 msgid "Isaiah Inuwa" msgstr "" @@ -51,66 +50,122 @@ msgstr "Ein mobiles Gerät" msgid "Use your security key" msgstr "Stecken Sie Ihren Security-Token ein." -#: credentialsd-ui/data/resources/ui/window.blp:162 +#: credentialsd-ui/data/resources/ui/window.blp:173 msgid "Connect a security key" msgstr "Stecken Sie Ihren Security-Token ein." -#: credentialsd-ui/data/resources/ui/window.blp:197 +#: credentialsd-ui/data/resources/ui/window.blp:208 #, fuzzy msgid "Enter your device PIN" msgstr "Geben Sie Ihren PIN ein." -#: credentialsd-ui/data/resources/ui/window.blp:205 +#: credentialsd-ui/data/resources/ui/window.blp:217 msgid "Scan the QR code to connect your device" msgstr "Scannen Sie den QR-Code, um Ihr Gerät zu verbinden" -#: credentialsd-ui/data/resources/ui/window.blp:247 -#: credentialsd-ui/data/resources/ui/window.blp:253 +#: credentialsd-ui/data/resources/ui/window.blp:259 +#: credentialsd-ui/data/resources/ui/window.blp:265 msgid "Choose credential" msgstr "Wählen Sie Zugangsdaten aus" -#: credentialsd-ui/data/resources/ui/window.blp:266 + +#: credentialsd-ui/data/resources/ui/window.blp:278 +msgid "Set a PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:301 +msgid "Please choose a new PIN for your device." +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:314 +msgid "New PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:321 +msgid "Confirm PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:333 +#: credentialsd-ui/data/resources/ui/window.blp:404 +msgid "Close" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:338 +msgid "Continue" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:353 msgid "Complete" msgstr "Abgeschlossen" -#: credentialsd-ui/data/resources/ui/window.blp:288 +#: credentialsd-ui/data/resources/ui/window.blp:375 msgid "Done!" msgstr "Fertig!" -#: credentialsd-ui/data/resources/ui/window.blp:299 +#: credentialsd-ui/data/resources/ui/window.blp:386 msgid "Something went wrong." msgstr "Etwas ist schief gegangen." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:159 +#: credentialsd-ui/data/resources/ui/window.blp:409 +#, fuzzy +msgid "Set PIN on device" +msgstr "Ein mobiles Gerät" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:177 #, fuzzy msgid "Enter your PIN. One attempt remaining." msgid_plural "Enter your PIN. %d attempts remaining." msgstr[0] "Geben Sie Ihren PIN ein. Sie haben nur noch einen Versuch." msgstr[1] "Geben Sie Ihren PIN ein. Sie haben noch %d Versuche." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:165 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:183 msgid "Enter your PIN." msgstr "Geben Sie Ihren PIN ein." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:174 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:192 msgid "Touch your device again. One attempt remaining." msgid_plural "Touch your device again. %d attempts remaining." msgstr[0] "Berühren Sie Ihr Gerät. Sie haben nur noch einen Versuch." msgstr[1] "Berühren Sie nochmal Ihr Gerät. Sie haben nur noch %d Versuche." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:180 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:198 msgid "Touch your device." msgstr "Berühren Sie Ihr Gerät." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:185 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:203 msgid "Touch your device" msgstr "Berühren Sie Ihr Gerät." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:188 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:210 +msgid "" +"This server requires your device to have additional protection like a PIN, " +"which is not set. Please set a PIN for this device and try again." +msgstr "" +"Für diesen Server benötigt ihr Gerät eine zusätzliche Absicherung, z.B. " +"einen PIN. Bitte setzen Sie einen PIN für ihr Gerät und versuchen Sie es " +"erneut." + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:214 +msgid "" +"The entered PIN violates the PIN-policy of this device (likely too short). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:217 +msgid "" +"The entered PIN violates the PIN-policy of this device (PIN too long). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:220 +msgid "A PIN change is required by your device to continue." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:227 msgid "Scan the QR code with your device to begin authentication." msgstr "" "Scannen Sie den QR code mit ihrem Gerät um die Authentifizierung zu beginnen." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:201 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:240 msgid "" "Connecting to your device. Make sure both devices are near each other and " "have Bluetooth enabled." @@ -118,19 +173,19 @@ msgstr "" "Verbindung zu Ihrem Gerät wird aufgebaut. Stellen Sie sicher, dass beide " "Geräte nah beieinander sind und Bluetooth aktiviert haben." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:209 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:248 msgid "Device connected. Follow the instructions on your device" msgstr "Verbindung hergestellt. Folgen Sie den Anweisungen auf Ihrem Gerät." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:298 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:347 msgid "Insert your security key." msgstr "Stecken Sie Ihren Security-Token ein." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:317 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:366 msgid "Multiple devices found. Please select with which to proceed." msgstr "Mehrere Geräte gefunden. Bitte wählen Sie einen aus, um fortzufahren." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:362 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:415 msgid "Credential Manager" msgstr "Zugangsdatenmanager" @@ -158,28 +213,28 @@ msgstr "Ein NFC-Gerät" msgid "A security key (USB)" msgstr "Ein Security-Token" -#: credentialsd-ui/src/gui/view_model/mod.rs:64 +#: credentialsd-ui/src/gui/view_model/mod.rs:62 msgid "unknown application" msgstr "unbekannter Applikation" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:80 +#: credentialsd-ui/src/gui/view_model/mod.rs:76 msgid "Create a passkey for %s1" msgstr "Neuen Passkey für %s1 erstellen" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:84 +#: credentialsd-ui/src/gui/view_model/mod.rs:80 msgid "Use a passkey for %s1" msgstr "Passkey für %s1 abrufen" #. TRANSLATORS: %s1 is the "relying party" (e.g.: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:96 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:91 +#, fuzzy msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to create a " -"credential to register at \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to create a credential to register at " +"\"%s1\". Only proceed if you trust this process." msgstr "" "\"%s2\" (Prozess-ID: %i1, ausführbare Datei: %s3) möchte neue " "Zugangsdaten erstellen, um Sie bei \"%s1\" zu registrieren. Fahren Sie nur " @@ -187,59 +242,38 @@ msgstr "" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:103 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:97 +#, fuzzy msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to use a credential " -"to sign in to \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to use a credential to sign in to \"%s1\". " +"Only proceed if you trust this process." msgstr "" "\"%s2\" (Prozess-ID: %i1, ausführbare Datei: %s3) möchte Zugangsdaten " "abrufen, um Sie bei \"%s1\" anzumelden. Fahren Sie nur fort, wenn Sie diesem " "Prozess vertrauen." #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:115 +#: credentialsd-ui/src/gui/view_model/mod.rs:108 msgid "" "Scan the QR code using the camera on the device that has the passkey for %s1" msgstr "" #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:118 +#: credentialsd-ui/src/gui/view_model/mod.rs:111 #, fuzzy msgid "Insert and activate your security key to use it for %s1" msgstr "Stecken Sie Ihren Security-Token ein." -#: credentialsd-ui/src/gui/view_model/mod.rs:181 +#: credentialsd-ui/src/gui/view_model/mod.rs:193 msgid "Failed to select credential from device." msgstr "Zugangsdaten vom Gerät konnten nicht ausgewählt werden." -#: credentialsd-ui/src/gui/view_model/mod.rs:237 -msgid "No matching credentials found on this authenticator." -msgstr "Keine passenden Zugangsdaten auf diesem Gerät gefunden." - -#: credentialsd-ui/src/gui/view_model/mod.rs:245 -msgid "" -"No more PIN attempts allowed. Try removing your device and plugging it back " -"in." -msgstr "" -"Keine weiteren PIN-Eingaben erlaubt. Versuchen Sie ihr Gerät aus- und wieder " -"einzustecken." - -#: credentialsd-ui/src/gui/view_model/mod.rs:254 -msgid "" -"This server requires your device to have additional protection like a PIN, " -"which is not set. Please set a PIN for this device and try again." -msgstr "" -"Für diesen Server benötigt ihr Gerät eine zusätzliche Absicherung, z.B. " -"einen PIN. Bitte setzen Sie einen PIN für ihr Gerät und versuchen Sie es " -"erneut." - -#: credentialsd-ui/src/gui/view_model/mod.rs:262 +#: credentialsd-ui/src/gui/view_model/mod.rs:257 msgid "The credential request timed out. Please try again." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:272 +#: credentialsd-ui/src/gui/view_model/mod.rs:267 msgid "" "Something went wrong while retrieving a credential. Please try again later " "or use a different authenticator." @@ -247,10 +281,32 @@ msgstr "" "Beim Abrufen Ihrer Zugangsdaten ist ein Fehler aufgetreten. Versuchen Sie es " "später wieder, oder verwenden Sie einen anderen Security-Token." -#: credentialsd-ui/src/gui/view_model/mod.rs:281 +#: credentialsd-ui/src/gui/view_model/mod.rs:276 msgid "This credential is already registered on this authenticator." msgstr "Diese Zugangsdaten sind bereits auf diesem Gerät registriert." +#: credentialsd-ui/src/gui/view_model/mod.rs:374 +msgid "" +"The previous attempt was interrupted. Please follow the new prompts to try " +"again." +msgstr "" +"Der Versuch wurde abgebrochen. Bitte versuchen Sie es erneut." + +#: credentialsd-ui/src/gui/view_model/mod.rs:377 +msgid "" +"No matching credentials on this authenticator. Please try a different one." +msgstr "" +"Keine passenden Zugangsdaten auf diesem Gerät. Bitte versuchen Sie es mit " +"einem anderen." + +#: credentialsd-ui/src/gui/view_model/mod.rs:380 +msgid "" +"No more PIN attempts allowed. Remove and reinsert your device, or use a " +"different authenticator." +msgstr "" +"Keine weiteren PIN-Eingaben erlaubt. Versuchen Sie ihr Gerät aus- und wieder " +"einzustecken, oder verwenden Sie ein anderes Gerät." + #~ msgid "Devices" #~ msgstr "Geräte" diff --git a/credentialsd-ui/po/en_US.po b/credentialsd-ui/po/en_US.po index f9eda4a..f5f12eb 100644 --- a/credentialsd-ui/po/en_US.po +++ b/credentialsd-ui/po/en_US.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/" "issues\"\n" -"POT-Creation-Date: 2026-06-18 07:18-0500\n" +"POT-Creation-Date: 2026-09-09 15:53+0200\n" "PO-Revision-Date: 2025-10-10 14:45+0200\n" "Last-Translator: Martin Sirringhaus \n" "Language: en_US\n" @@ -31,8 +31,7 @@ msgid "Registering a credential" msgstr "Registering a credential" #. developer_name tag deprecated with Appstream 1.0 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:36 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:39 +#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:38 msgid "Isaiah Inuwa" msgstr "" @@ -50,65 +49,119 @@ msgstr "A mobile device" msgid "Use your security key" msgstr "Insert your security key." -#: credentialsd-ui/data/resources/ui/window.blp:162 +#: credentialsd-ui/data/resources/ui/window.blp:173 msgid "Connect a security key" msgstr "Connect a security key" -#: credentialsd-ui/data/resources/ui/window.blp:197 +#: credentialsd-ui/data/resources/ui/window.blp:208 #, fuzzy msgid "Enter your device PIN" msgstr "Enter your PIN." -#: credentialsd-ui/data/resources/ui/window.blp:205 +#: credentialsd-ui/data/resources/ui/window.blp:217 msgid "Scan the QR code to connect your device" msgstr "Scan the QR code to connect your device" -#: credentialsd-ui/data/resources/ui/window.blp:247 -#: credentialsd-ui/data/resources/ui/window.blp:253 +#: credentialsd-ui/data/resources/ui/window.blp:259 +#: credentialsd-ui/data/resources/ui/window.blp:265 msgid "Choose credential" msgstr "Choose credential" -#: credentialsd-ui/data/resources/ui/window.blp:266 +#: credentialsd-ui/data/resources/ui/window.blp:278 +msgid "Set a PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:301 +msgid "Please choose a new PIN for your device." +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:314 +msgid "New PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:321 +msgid "Confirm PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:333 +#: credentialsd-ui/data/resources/ui/window.blp:404 +msgid "Close" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:338 +msgid "Continue" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:353 msgid "Complete" msgstr "Complete" -#: credentialsd-ui/data/resources/ui/window.blp:288 +#: credentialsd-ui/data/resources/ui/window.blp:375 msgid "Done!" msgstr "Done!" -#: credentialsd-ui/data/resources/ui/window.blp:299 +#: credentialsd-ui/data/resources/ui/window.blp:386 msgid "Something went wrong." msgstr "Something went wrong." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:159 +#: credentialsd-ui/data/resources/ui/window.blp:409 +#, fuzzy +msgid "Set PIN on device" +msgstr "A mobile device" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:177 msgid "Enter your PIN. One attempt remaining." msgid_plural "Enter your PIN. %d attempts remaining." msgstr[0] "Enter your PIN. One attempt remaining." msgstr[1] "Enter your PIN. %d attempts remaining." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:165 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:183 msgid "Enter your PIN." msgstr "Enter your PIN." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:174 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:192 msgid "Touch your device again. One attempt remaining." msgid_plural "Touch your device again. %d attempts remaining." msgstr[0] "Touch your device again. One attempt remaining." msgstr[1] "Touch your device again. %d attempts remaining." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:180 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:198 msgid "Touch your device." msgstr "Touch your device." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:185 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:203 msgid "Touch your device" msgstr "Touch your device" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:188 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:210 +msgid "" +"This server requires your device to have additional protection like a PIN, " +"which is not set. Please set a PIN for this device and try again." +msgstr "" +"This server requires your device to have additional protection like a PIN, " +"which is not set. Please set a PIN for this device and try again." + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:214 +msgid "" +"The entered PIN violates the PIN-policy of this device (likely too short). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:217 +msgid "" +"The entered PIN violates the PIN-policy of this device (PIN too long). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:220 +msgid "A PIN change is required by your device to continue." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:227 msgid "Scan the QR code with your device to begin authentication." msgstr "Scan the QR code with your device to begin authentication." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:201 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:240 msgid "" "Connecting to your device. Make sure both devices are near each other and " "have Bluetooth enabled." @@ -116,19 +169,19 @@ msgstr "" "Connecting to your device. Make sure both devices are near each other and " "have Bluetooth enabled." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:209 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:248 msgid "Device connected. Follow the instructions on your device" msgstr "Device connected. Follow the instructions on your device" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:298 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:347 msgid "Insert your security key." msgstr "Insert your security key." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:317 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:366 msgid "Multiple devices found. Please select with which to proceed." msgstr "Multiple devices found. Please select with which to proceed." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:362 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:415 msgid "Credential Manager" msgstr "Credential Manager" @@ -156,85 +209,65 @@ msgstr "A security key or card (NFC)" msgid "A security key (USB)" msgstr "A security key (USB)" -#: credentialsd-ui/src/gui/view_model/mod.rs:64 +#: credentialsd-ui/src/gui/view_model/mod.rs:62 msgid "unknown application" msgstr "unknown application" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:80 +#: credentialsd-ui/src/gui/view_model/mod.rs:76 msgid "Create a passkey for %s1" msgstr "Create a passkey for %s1" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:84 +#: credentialsd-ui/src/gui/view_model/mod.rs:80 msgid "Use a passkey for %s1" msgstr "Use a passkey for %s1" #. TRANSLATORS: %s1 is the "relying party" (e.g.: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:96 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:91 +#, fuzzy msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to create a " -"credential to register at \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to create a credential to register at " +"\"%s1\". Only proceed if you trust this process." msgstr "" "\"%s2\" (process ID: %i1, binary: %s3) is asking to create a " "credential to register at \"%s1\". Only proceed if you trust this process." #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:103 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:97 +#, fuzzy msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to use a credential " -"to sign in to \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to use a credential to sign in to \"%s1\". " +"Only proceed if you trust this process." msgstr "" "\"%s2\" (process ID: %i1, binary: %s3) is asking to use a credential " "to sign in to \"%s1\". Only proceed if you trust this process." #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:115 +#: credentialsd-ui/src/gui/view_model/mod.rs:108 msgid "" "Scan the QR code using the camera on the device that has the passkey for %s1" msgstr "" #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:118 +#: credentialsd-ui/src/gui/view_model/mod.rs:111 #, fuzzy msgid "Insert and activate your security key to use it for %s1" msgstr "Insert your security key." -#: credentialsd-ui/src/gui/view_model/mod.rs:181 +#: credentialsd-ui/src/gui/view_model/mod.rs:193 msgid "Failed to select credential from device." msgstr "Failed to select credential from device." -#: credentialsd-ui/src/gui/view_model/mod.rs:237 -msgid "No matching credentials found on this authenticator." -msgstr "No matching credentials found on this authenticator." - -#: credentialsd-ui/src/gui/view_model/mod.rs:245 -msgid "" -"No more PIN attempts allowed. Try removing your device and plugging it back " -"in." -msgstr "" -"No more PIN attempts allowed. Try removing your device and plugging it back " -"in." - -#: credentialsd-ui/src/gui/view_model/mod.rs:254 -msgid "" -"This server requires your device to have additional protection like a PIN, " -"which is not set. Please set a PIN for this device and try again." -msgstr "" -"This server requires your device to have additional protection like a PIN, " -"which is not set. Please set a PIN for this device and try again." - -#: credentialsd-ui/src/gui/view_model/mod.rs:262 +#: credentialsd-ui/src/gui/view_model/mod.rs:257 msgid "The credential request timed out. Please try again." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:272 +#: credentialsd-ui/src/gui/view_model/mod.rs:267 msgid "" "Something went wrong while retrieving a credential. Please try again later " "or use a different authenticator." @@ -242,10 +275,32 @@ msgstr "" "Something went wrong while retrieving a credential. Please try again later " "or use a different authenticator." -#: credentialsd-ui/src/gui/view_model/mod.rs:281 +#: credentialsd-ui/src/gui/view_model/mod.rs:276 msgid "This credential is already registered on this authenticator." msgstr "This credential is already registered on this authenticator." +#: credentialsd-ui/src/gui/view_model/mod.rs:374 +msgid "" +"The previous attempt was interrupted. Please follow the new prompts to try " +"again." +msgstr "" +"The previous attempt was interrupted. Please follow the new prompts to try " +"again." + +#: credentialsd-ui/src/gui/view_model/mod.rs:377 +msgid "" +"No matching credentials on this authenticator. Please try a different one." +msgstr "" +"No matching credentials on this authenticator. Please try a different one." + +#: credentialsd-ui/src/gui/view_model/mod.rs:380 +msgid "" +"No more PIN attempts allowed. Remove and reinsert your device, or use a " +"different authenticator." +msgstr "" +"No more PIN attempts allowed. Remove and reinsert your device, or use a " +"different authenticator." + #~ msgid "Devices" #~ msgstr "Devices" diff --git a/credentialsd-ui/po/ka_GE.po b/credentialsd-ui/po/ka_GE.po index 8fcf676..9ee9abf 100644 --- a/credentialsd-ui/po/ka_GE.po +++ b/credentialsd-ui/po/ka_GE.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: credentialsd-ui\n" "Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/" "issues\"\n" -"POT-Creation-Date: 2026-06-18 07:18-0500\n" +"POT-Creation-Date: 2026-09-09 15:53+0200\n" "PO-Revision-Date: 2026-04-20 07:16+0200\n" "Last-Translator: Ekaterine Papava \n" "Language-Team: \n" @@ -39,8 +39,7 @@ msgid "Registering a credential" msgstr "ავტორიზაციის დეტალების რეგისტრაცია" #. developer_name tag deprecated with Appstream 1.0 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:36 -#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:39 +#: credentialsd-ui/data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:38 msgid "Isaiah Inuwa" msgstr "Isaiah Inuwa" @@ -58,65 +57,120 @@ msgstr "მობილური მოწყობილობა" msgid "Use your security key" msgstr "შეერთეთ თქვენი უსაფრთხოების გასაღები." -#: credentialsd-ui/data/resources/ui/window.blp:162 +#: credentialsd-ui/data/resources/ui/window.blp:173 msgid "Connect a security key" msgstr "უსაფრთხოების გასაღების დაკავშირება" -#: credentialsd-ui/data/resources/ui/window.blp:197 +#: credentialsd-ui/data/resources/ui/window.blp:208 #, fuzzy msgid "Enter your device PIN" msgstr "შეიყვანეთ PIN-კოდი." -#: credentialsd-ui/data/resources/ui/window.blp:205 +#: credentialsd-ui/data/resources/ui/window.blp:217 msgid "Scan the QR code to connect your device" msgstr "დაასკანირეთ QR კოდი თქვენი მოწყობილობის დასაკავშირებლად" -#: credentialsd-ui/data/resources/ui/window.blp:247 -#: credentialsd-ui/data/resources/ui/window.blp:253 +#: credentialsd-ui/data/resources/ui/window.blp:259 +#: credentialsd-ui/data/resources/ui/window.blp:265 msgid "Choose credential" msgstr "ავტორიზაციის დეტალების არჩევა" -#: credentialsd-ui/data/resources/ui/window.blp:266 +#: credentialsd-ui/data/resources/ui/window.blp:278 +msgid "Set a PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:301 +msgid "Please choose a new PIN for your device." +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:314 +msgid "New PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:321 +msgid "Confirm PIN" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:333 +#: credentialsd-ui/data/resources/ui/window.blp:404 +msgid "Close" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:338 +msgid "Continue" +msgstr "" + +#: credentialsd-ui/data/resources/ui/window.blp:353 msgid "Complete" msgstr "დასრულება" -#: credentialsd-ui/data/resources/ui/window.blp:288 +#: credentialsd-ui/data/resources/ui/window.blp:375 msgid "Done!" msgstr "მზადაა!" -#: credentialsd-ui/data/resources/ui/window.blp:299 +#: credentialsd-ui/data/resources/ui/window.blp:386 msgid "Something went wrong." msgstr "რაღაც მოხდა." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:159 +#: credentialsd-ui/data/resources/ui/window.blp:409 +#, fuzzy +msgid "Set PIN on device" +msgstr "მობილური მოწყობილობა" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:177 msgid "Enter your PIN. One attempt remaining." msgid_plural "Enter your PIN. %d attempts remaining." msgstr[0] "შეიყვანეთ თქვენი PIN-კოდი. დარჩენილია ერთი მცდელობა." msgstr[1] "შეიყვანეთ თქვენი PIN-კოდი. დარჩენილია %d მცდელობა." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:165 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:183 msgid "Enter your PIN." msgstr "შეიყვანეთ PIN-კოდი." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:174 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:192 msgid "Touch your device again. One attempt remaining." msgid_plural "Touch your device again. %d attempts remaining." msgstr[0] "შეეხეთ თქვენს მოწყობილობას კიდევ ერთხელ. დარჩენილია ერთი მცდელობა." msgstr[1] "შეეხეთ თქვენს მოწყობილობას კიდევ ერთხელ. დარჩენილია %d მცდელობა." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:180 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:198 msgid "Touch your device." msgstr "შეეხეთ თქვენს მოწყობილობას." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:185 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:203 msgid "Touch your device" msgstr "შეეხეთ თქვენს მოწყობილობას" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:188 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:210 +msgid "" +"This server requires your device to have additional protection like a PIN, " +"which is not set. Please set a PIN for this device and try again." +msgstr "" +"ეს სერვერი ითხოვს, რომ თქვენს მოწყობილობას ჰქონდეს დამატებითი დაცვა, " +"როგორიცაა PIN-კოდი, რომელიც დაყენებული არაა. დააყენეთ PIN-კოდი ამ " +"მოწყობილობისთვის და თავიდან სცადეთ." + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:214 +msgid "" +"The entered PIN violates the PIN-policy of this device (likely too short). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:217 +msgid "" +"The entered PIN violates the PIN-policy of this device (PIN too long). " +"Please try again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:220 +msgid "A PIN change is required by your device to continue." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:227 msgid "Scan the QR code with your device to begin authentication." msgstr "ავთენტიკაციის დასაწყებად დაასკანერეთ QR კოდი თქვენი მოწყობილობით." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:201 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:240 msgid "" "Connecting to your device. Make sure both devices are near each other and " "have Bluetooth enabled." @@ -124,20 +178,20 @@ msgstr "" "მიმდინარეობს თქვენს მოწყობილობასთან დაკავშირება. დარწმუნდით, რომ ორივე " "მოწყობილობა ახლოსაა ერთმანეთთან და რომ ბლუთუზი ჩართულია." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:209 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:248 msgid "Device connected. Follow the instructions on your device" msgstr "მოწყობილობა დაკავშირებულია. მიჰყევით ინსტრუქციებს თქვენს მოწყობილობაზე" -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:298 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:347 msgid "Insert your security key." msgstr "შეერთეთ თქვენი უსაფრთხოების გასაღები." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:317 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:366 msgid "Multiple devices found. Please select with which to proceed." msgstr "" "აღმოჩენილია ერთზე მეტი მოწყობილობა. აირჩიეთ, რომელი გნებავთ, გამოიყენოთ." -#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:362 +#: credentialsd-ui/src/gui/view_model/gtk/mod.rs:415 msgid "Credential Manager" msgstr "ავტორიზაციის დეტალების მმართველი" @@ -165,28 +219,28 @@ msgstr "უსაფრთხოების გასაღები, ან msgid "A security key (USB)" msgstr "უსაფრთხოების გასაღები (USB)" -#: credentialsd-ui/src/gui/view_model/mod.rs:64 +#: credentialsd-ui/src/gui/view_model/mod.rs:62 msgid "unknown application" msgstr "უცნობი აპლიკაცია" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:80 +#: credentialsd-ui/src/gui/view_model/mod.rs:76 msgid "Create a passkey for %s1" msgstr "საკვანძო გასაღების შექმნა %1-ისთვის" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:84 +#: credentialsd-ui/src/gui/view_model/mod.rs:80 msgid "Use a passkey for %s1" msgstr "საკვანძო გასაღების გამოყენება %1-ისთვის" #. TRANSLATORS: %s1 is the "relying party" (e.g.: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:96 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:91 +#, fuzzy msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to create a " -"credential to register at \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to create a credential to register at " +"\"%s1\". Only proceed if you trust this process." msgstr "" "\"%s2\" (პროცესის ID: %i1, გამშვები ფაილი: %s3) ითხოვს ავტორიზაციის " "დეტალების შექმნას \"%s1\"-ზე რეგისტრაციისთვის. გააგრძელეთ, მხოლოდ, მაშინ, თუ " @@ -194,59 +248,38 @@ msgstr "" #. TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from #. TRANSLATORS: %s2 is the application name (e.g.: firefox) where the request is coming from, must be left untouched to make the name bold -#. TRANSLATORS: %i1 is the process ID of the requesting application -#. TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application -#: credentialsd-ui/src/gui/view_model/mod.rs:103 +#. TRANSLATORS: %s3 is the app ID (think: org.mozilla.firefox) of the requesting application +#: credentialsd-ui/src/gui/view_model/mod.rs:97 +#, fuzzy msgid "" -"\"%s2\" (process ID: %i1, binary: %s3) is asking to use a credential " -"to sign in to \"%s1\". Only proceed if you trust this process." +"\"%s2\" (%s3) is asking to use a credential to sign in to \"%s1\". " +"Only proceed if you trust this process." msgstr "" "\"%s2\" (პროცესის ID: %i1, გამშვები ფაილი: %s3) ითხოვს ავტორიზაციის " "დეტალების გამოყენებას \"%s1\"-ზე შესასვლელად. გააგრძელეთ, მხოლოდ, მაშინ, თუ " "ენდობით ამ პროცესს." #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:115 +#: credentialsd-ui/src/gui/view_model/mod.rs:108 msgid "" "Scan the QR code using the camera on the device that has the passkey for %s1" msgstr "" #. TRANSLATORS: %s1 is the relying party (think: domain name) where the request is coming from -#: credentialsd-ui/src/gui/view_model/mod.rs:118 +#: credentialsd-ui/src/gui/view_model/mod.rs:111 #, fuzzy msgid "Insert and activate your security key to use it for %s1" msgstr "შეერთეთ თქვენი უსაფრთხოების გასაღები." -#: credentialsd-ui/src/gui/view_model/mod.rs:181 +#: credentialsd-ui/src/gui/view_model/mod.rs:193 msgid "Failed to select credential from device." msgstr "ავტორიზაციის დეტალების არჩევა მოწყობილობიდან ჩავარდა." -#: credentialsd-ui/src/gui/view_model/mod.rs:237 -msgid "No matching credentials found on this authenticator." -msgstr "ამ ავთენტიკატორში შესაბამისი ავტორიზაციის დეტალები აღმოჩენილი არაა." - -#: credentialsd-ui/src/gui/view_model/mod.rs:245 -msgid "" -"No more PIN attempts allowed. Try removing your device and plugging it back " -"in." -msgstr "" -"მეტი PIN-კოდი დაშვებული აღარაა. სცადეთ, გამოაძროთ თქვენი მოწყობილობა და ისევ " -"შეაერთოთ." - -#: credentialsd-ui/src/gui/view_model/mod.rs:254 -msgid "" -"This server requires your device to have additional protection like a PIN, " -"which is not set. Please set a PIN for this device and try again." -msgstr "" -"ეს სერვერი ითხოვს, რომ თქვენს მოწყობილობას ჰქონდეს დამატებითი დაცვა, " -"როგორიცაა PIN-კოდი, რომელიც დაყენებული არაა. დააყენეთ PIN-კოდი ამ " -"მოწყობილობისთვის და თავიდან სცადეთ." - -#: credentialsd-ui/src/gui/view_model/mod.rs:262 +#: credentialsd-ui/src/gui/view_model/mod.rs:257 msgid "The credential request timed out. Please try again." msgstr "" -#: credentialsd-ui/src/gui/view_model/mod.rs:272 +#: credentialsd-ui/src/gui/view_model/mod.rs:267 msgid "" "Something went wrong while retrieving a credential. Please try again later " "or use a different authenticator." @@ -254,10 +287,31 @@ msgstr "" "ავტორიზაციის დეტალების მიღებისას რაღაც არასწორად წავიდა. სცადეთ თავიდან " "მოგვიანებით, ან გამოიყენეთ სხვა ავთენტიკატორი." -#: credentialsd-ui/src/gui/view_model/mod.rs:281 +#: credentialsd-ui/src/gui/view_model/mod.rs:276 msgid "This credential is already registered on this authenticator." msgstr "ეს ავტორიზაციის დეტალი უკვე რეგისტრირებულია ამ ავთენტიკატორზე." +#: credentialsd-ui/src/gui/view_model/mod.rs:374 +msgid "" +"The previous attempt was interrupted. Please follow the new prompts to try " +"again." +msgstr "" + +#: credentialsd-ui/src/gui/view_model/mod.rs:377 +#, fuzzy +msgid "" +"No matching credentials on this authenticator. Please try a different one." +msgstr "ამ ავთენტიკატორში შესაბამისი ავტორიზაციის დეტალები აღმოჩენილი არაა." + +#: credentialsd-ui/src/gui/view_model/mod.rs:380 +#, fuzzy +msgid "" +"No more PIN attempts allowed. Remove and reinsert your device, or use a " +"different authenticator." +msgstr "" +"მეტი PIN-კოდი დაშვებული აღარაა. სცადეთ, გამოაძროთ თქვენი მოწყობილობა და ისევ " +"შეაერთოთ." + #~ msgid "Devices" #~ msgstr "მოწყობილობები"