Add basic TOTP support with mocked creation.

This commit is contained in:
Greyson Parrelli
2026-09-02 16:11:32 -03:00
committed by Alex Hart
parent 6a032e4f27
commit 62897a309c
163 changed files with 6688 additions and 5119 deletions
@@ -75,7 +75,7 @@ class AccountSettingsFragment : ComposeFragment() {
AccountSettingsAction.LaunchChangePinFlow -> pinFlowLauncher.launch(CreateSvrPinActivity.getIntentForPinChangeFromSettings(requireContext()))
AccountSettingsAction.ShowPinCreatedConfirmation -> Snackbar.make(requireView(), R.string.ConfirmKbsPinFragment__pin_created, Snackbar.LENGTH_LONG).show()
AccountSettingsAction.NavigateToSignalLoginDetails -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_signalLoginViewDetailsFragment)
AccountSettingsAction.NavigateToAuthenticatorApps -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_authenticatorAppsFragment)
AccountSettingsAction.NavigateToTotpAppList -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_authenticatorAppsFragment)
AccountSettingsAction.NavigateToPasskeys -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_passkeysFragment)
AccountSettingsAction.NavigateToAdvancedPinSettings -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_advancedPinSettingsActivity)
AccountSettingsAction.NavigateToChangePhoneNumber -> findNavController().safeNavigate(R.id.action_accountSettingsFragment_to_changePhoneNumberFragment)
@@ -8,7 +8,7 @@ package org.thoughtcrime.securesms.components.settings.app.account
import kotlinx.coroutines.withContext
import org.signal.core.util.concurrent.SignalDispatchers
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.AuthenticatorRepository
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpRepository
import org.thoughtcrime.securesms.components.settings.app.account.passkeys.AppPasskeysRepository
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -27,7 +27,7 @@ class AccountSettingsRepository {
private val TAG = Log.tag(AccountSettingsRepository::class)
}
private val authenticatorRepository = AuthenticatorRepository()
private val totpRepository = TotpRepository()
private val passkeysRepository = AppPasskeysRepository()
fun hasPin(): Boolean = SignalStore.svr.hasPin() && !SignalStore.svr.hasOptedOut()
@@ -48,7 +48,12 @@ class AccountSettingsRepository {
fun isPhoneNumberless(): Boolean = SignalStore.account.isPhoneNumberless
fun getAuthenticatorAppCount(): Int = authenticatorRepository.getAuthenticatorApps().size
/**
* How many authenticator apps are on the account, or null if we couldn't find out.
*/
suspend fun getTotpAppCount(): Int? {
return (totpRepository.getTotpApps() as? TotpRepository.AppsResult.Success)?.apps?.size
}
fun getPasskeyCount(): Int = passkeysRepository.getPasskeys().size
@@ -5,6 +5,7 @@
package org.thoughtcrime.securesms.components.settings.app.account
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -12,6 +13,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.signal.appsettings.account.AccountSettingsAction
import org.signal.appsettings.account.AccountSettingsEvent
import org.signal.appsettings.account.AccountSettingsState
@@ -40,7 +42,7 @@ class AccountSettingsViewModel(
val actions: Flow<AccountSettingsAction> = _actions.receiveAsFlow()
init {
refresh()
viewModelScope.launch { refresh() }
}
override suspend fun processEvent(event: AccountSettingsEvent) {
@@ -104,8 +106,8 @@ class AccountSettingsViewModel(
AccountSettingsEvent.AccountAndRecoveryClicked -> {
_actions.send(AccountSettingsAction.NavigateToSignalLoginDetails)
}
AccountSettingsEvent.AuthenticatorAppClicked -> {
_actions.send(AccountSettingsAction.NavigateToAuthenticatorApps)
AccountSettingsEvent.TotpAppClicked -> {
_actions.send(AccountSettingsAction.NavigateToTotpAppList)
}
AccountSettingsEvent.PasskeysClicked -> {
_actions.send(AccountSettingsAction.NavigateToPasskeys)
@@ -147,8 +149,9 @@ class AccountSettingsViewModel(
}
}
private fun refresh() {
private suspend fun refresh() {
val isPhoneNumberless = repository.isPhoneNumberless()
val totpAppCount = repository.getTotpAppCount()
_state.update {
it.copy(
@@ -161,7 +164,7 @@ class AccountSettingsViewModel(
isPhoneNumberless = isPhoneNumberless,
signalLogin = if (isPhoneNumberless) {
AccountSettingsState.SignalLogin(
authenticatorAppCount = repository.getAuthenticatorAppCount(),
totpAppCount = totpAppCount,
passkeyCount = repository.getPasskeyCount()
)
} else {
@@ -1,46 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import org.signal.appsettings.authenticatorapps.AuthenticatorApp
/**
* Stand-in for wherever authenticator app state will eventually live. Nothing is persisted or sent to the service yet,
* so all of this is mocked up and lasts only as long as the process does.
*/
object AuthenticatorAppStore {
/** The key we'd hand off to an authenticator app, which the service will supply for real later on. */
const val MOCK_SETUP_KEY = "KVZ7WL3FDDWJZMTOB7PLZPKVRFD4LYSX"
/** How many authenticator apps an account is allowed, which the service will decide for real later on. */
const val MAX_APPS = 2
private val lock = Any()
private val apps = mutableListOf<AuthenticatorApp>()
private var nextId = 1L
fun getApps(): List<AuthenticatorApp> = synchronized(lock) { apps.toList() }
fun addApp(name: String, createdAt: Long): Long = synchronized(lock) {
val id = nextId++
apps += AuthenticatorApp(id = id, name = name, createdAt = createdAt)
id
}
fun renameApp(id: Long, name: String) = synchronized(lock) {
val index = apps.indexOfFirst { it.id == id }
if (index >= 0) {
apps[index] = apps[index].copy(name = name)
}
}
fun removeApp(id: Long) = synchronized(lock) {
apps.removeAll { it.id == id }
}
fun getApp(id: Long): AuthenticatorApp? = synchronized(lock) { apps.firstOrNull { it.id == id } }
}
@@ -1,75 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsAction
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsEvent
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.navigation.safeNavigate
/**
* Lists the authenticator apps on the account. Carries out the [AuthenticatorAppsAction]s that need the nav graph.
*/
class AuthenticatorAppsFragment : ComposeFragment() {
companion object {
private val TAG = Log.tag(AuthenticatorAppsFragment::class)
}
private val viewModel: AuthenticatorAppsViewModel by viewModels()
@Composable
override fun FragmentContent() {
val state by viewModel.state.collectAsStateWithLifecycle()
CollectActions(viewModel.actions) { action -> handleAction(action) }
AuthenticatorAppsScreen(
state = state,
onEvent = viewModel::onEvent
)
}
override fun onResume() {
super.onResume()
viewModel.onEvent(AuthenticatorAppsEvent.ScreenResumed)
}
private fun handleAction(action: AuthenticatorAppsAction) {
when (action) {
AuthenticatorAppsAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
AuthenticatorAppsAction.NavigateToSetup -> {
findNavController().safeNavigate(R.id.action_authenticatorAppsFragment_to_authenticatorSetupFragment)
}
is AuthenticatorAppsAction.NavigateToRename -> {
findNavController().safeNavigate(
R.id.action_authenticatorAppsFragment_to_authenticatorNameFragment,
Bundle().apply { putLong(AuthenticatorNavArgs.ARG_APP_ID, action.appId) }
)
}
is AuthenticatorAppsAction.NavigateToRemovalCodeEntry -> {
findNavController().safeNavigate(
R.id.action_authenticatorAppsFragment_to_authenticatorCodeEntryFragment,
Bundle().apply {
putString(AuthenticatorNavArgs.ARG_PURPOSE, AuthenticatorNavArgs.PURPOSE_REMOVE)
putLong(AuthenticatorNavArgs.ARG_APP_ID, action.appId)
}
)
}
AuthenticatorAppsAction.OpenLearnMore -> Log.w(TAG, "There's no support article to open yet.")
}
}
}
@@ -1,81 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsAction
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsEvent
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsState
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsState.Dialog
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
/**
* Drives the screen that lists the authenticator apps on the account.
*/
class AuthenticatorAppsViewModel(
private val repository: AuthenticatorRepository = AuthenticatorRepository()
) : EventDrivenViewModel<AuthenticatorAppsEvent>(TAG) {
companion object {
private val TAG = Log.tag(AuthenticatorAppsViewModel::class)
}
private val _state = MutableStateFlow(AuthenticatorAppsState(maxApps = repository.getMaxApps()))
private val _actions = Channel<AuthenticatorAppsAction>(Channel.BUFFERED)
val state: StateFlow<AuthenticatorAppsState> = _state.asStateFlow()
val actions: Flow<AuthenticatorAppsAction> = _actions.receiveAsFlow()
init {
refresh()
}
override suspend fun processEvent(event: AuthenticatorAppsEvent) {
when (event) {
AuthenticatorAppsEvent.ScreenResumed -> {
refresh()
}
AuthenticatorAppsEvent.NavigateBackClicked -> {
_actions.send(AuthenticatorAppsAction.NavigateBack)
}
AuthenticatorAppsEvent.AddAuthenticatorAppClicked -> {
if (_state.value.atMaxApps) {
_state.update { it.copy(dialog = Dialog.MaxAppsReached) }
} else {
_actions.send(AuthenticatorAppsAction.NavigateToSetup)
}
}
AuthenticatorAppsEvent.LearnMoreClicked -> {
_actions.send(AuthenticatorAppsAction.OpenLearnMore)
}
is AuthenticatorAppsEvent.RenameAppClicked -> {
_actions.send(AuthenticatorAppsAction.NavigateToRename(event.appId))
}
is AuthenticatorAppsEvent.RemoveAppClicked -> {
_state.update { it.copy(dialog = Dialog.ConfirmRemove(event.appId)) }
}
AuthenticatorAppsEvent.RemoveAppConfirmed -> {
val dialog = _state.value.dialog as? Dialog.ConfirmRemove ?: return
_state.update { it.copy(dialog = Dialog.None) }
_actions.send(AuthenticatorAppsAction.NavigateToRemovalCodeEntry(dialog.appId))
}
AuthenticatorAppsEvent.DialogDismissed -> {
_state.update { it.copy(dialog = Dialog.None) }
}
}
}
private fun refresh() {
_state.update { it.copy(apps = repository.getAuthenticatorApps()) }
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.widget.Toast
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryAction
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.navigation.safeNavigate
import org.thoughtcrime.securesms.util.viewModel
import org.signal.appsettings.R as AppSettingsR
/**
* Collects the code from the user's authenticator app, either to confirm a newly paired one or to authorize removing
* one. Carries out the [AuthenticatorCodeEntryAction]s that need the nav graph.
*/
class AuthenticatorCodeEntryFragment : ComposeFragment() {
private val viewModel: AuthenticatorCodeEntryViewModel by viewModel {
AuthenticatorCodeEntryViewModel(AuthenticatorNavArgs.purpose(arguments))
}
@Composable
override fun FragmentContent() {
val state by viewModel.state.collectAsStateWithLifecycle()
CollectActions(viewModel.actions) { action -> handleAction(action) }
AuthenticatorCodeEntryScreen(
state = state,
onEvent = viewModel::onEvent
)
}
private fun handleAction(action: AuthenticatorCodeEntryAction) {
when (action) {
AuthenticatorCodeEntryAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
AuthenticatorCodeEntryAction.NavigateToNaming -> {
findNavController().safeNavigate(R.id.action_authenticatorCodeEntryFragment_to_authenticatorNameFragment)
}
AuthenticatorCodeEntryAction.NavigateToAuthenticatorApps -> findNavController().popBackStack(R.id.authenticatorAppsFragment, false)
AuthenticatorCodeEntryAction.ShowAuthenticatorAppRemoved -> {
Toast.makeText(requireContext(), AppSettingsR.string.AuthenticatorAppsScreen__authenticator_app_removed, Toast.LENGTH_SHORT).show()
}
}
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryAction
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryEvent
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryState
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryState.Purpose
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
/**
* Drives the screen that collects a code from the user's authenticator app, which is required both to confirm a newly
* paired app and to remove one that already exists. There's nothing to verify the code against yet, so any code of the
* right length is treated as correct.
*/
class AuthenticatorCodeEntryViewModel(
purpose: Purpose = Purpose.Add,
private val repository: AuthenticatorRepository = AuthenticatorRepository()
) : EventDrivenViewModel<AuthenticatorCodeEntryEvent>(TAG) {
companion object {
private val TAG = Log.tag(AuthenticatorCodeEntryViewModel::class)
}
private val _state = MutableStateFlow(AuthenticatorCodeEntryState(purpose = purpose))
private val _actions = Channel<AuthenticatorCodeEntryAction>(Channel.BUFFERED)
val state: StateFlow<AuthenticatorCodeEntryState> = _state.asStateFlow()
val actions: Flow<AuthenticatorCodeEntryAction> = _actions.receiveAsFlow()
override suspend fun processEvent(event: AuthenticatorCodeEntryEvent) {
when (event) {
AuthenticatorCodeEntryEvent.NavigateBackClicked -> {
_actions.send(AuthenticatorCodeEntryAction.NavigateBack)
}
is AuthenticatorCodeEntryEvent.CodeChanged -> {
val digits = event.code.filter { it.isDigit() }.take(AuthenticatorCodeEntryState.CODE_LENGTH)
_state.update { it.copy(code = digits) }
}
AuthenticatorCodeEntryEvent.DoneClicked -> {
if (!_state.value.canSubmit) {
return
}
Log.i(TAG, "Accepting the entered code without verifying it, which is all we can do until this is wired up.")
_state.update { it.copy(submitting = true) }
when (val purpose = _state.value.purpose) {
Purpose.Add -> {
_actions.send(AuthenticatorCodeEntryAction.NavigateToNaming)
}
is Purpose.Remove -> {
repository.removeAuthenticatorApp(purpose.appId)
_actions.send(AuthenticatorCodeEntryAction.ShowAuthenticatorAppRemoved)
_actions.send(AuthenticatorCodeEntryAction.NavigateToAuthenticatorApps)
}
}
}
}
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.authenticatorname.AuthenticatorNameAction
import org.signal.appsettings.authenticatorname.AuthenticatorNameScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.viewModel
import org.signal.appsettings.R as AppSettingsR
/**
* Names an authenticator app, either a newly paired one or one being renamed. Carries out the
* [AuthenticatorNameAction]s that need the nav graph.
*/
class AuthenticatorNameFragment : ComposeFragment() {
private val viewModel: AuthenticatorNameViewModel by viewModel {
AuthenticatorNameViewModel(AuthenticatorNavArgs.appId(arguments))
}
@Composable
override fun FragmentContent() {
val state by viewModel.state.collectAsStateWithLifecycle()
CollectActions(viewModel.actions) { action -> handleAction(action) }
AuthenticatorNameScreen(
state = state,
onEvent = viewModel::onEvent
)
}
private fun handleAction(action: AuthenticatorNameAction) {
when (action) {
AuthenticatorNameAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
AuthenticatorNameAction.NavigateToAuthenticatorApps -> findNavController().popBackStack(R.id.authenticatorAppsFragment, false)
AuthenticatorNameAction.ShowAuthenticatorAppSetUp -> toast(AppSettingsR.string.AuthenticatorNameScreen__authenticator_app_set_up)
AuthenticatorNameAction.ShowAuthenticatorAppRenamed -> toast(AppSettingsR.string.AuthenticatorNameScreen__authenticator_app_renamed)
}
}
private fun toast(@StringRes message: Int) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
}
@@ -1,73 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import org.signal.appsettings.authenticatorname.AuthenticatorNameAction
import org.signal.appsettings.authenticatorname.AuthenticatorNameEvent
import org.signal.appsettings.authenticatorname.AuthenticatorNameState
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
/**
* Drives the screen that names an authenticator app. [appId] is null when a newly paired app is being named for the
* first time, and set when an existing one is being renamed.
*/
class AuthenticatorNameViewModel(
private val appId: Long?,
private val repository: AuthenticatorRepository = AuthenticatorRepository()
) : EventDrivenViewModel<AuthenticatorNameEvent>(TAG) {
companion object {
private val TAG = Log.tag(AuthenticatorNameViewModel::class)
}
private val _state = MutableStateFlow(
AuthenticatorNameState(
name = appId?.let { repository.getAuthenticatorApp(it)?.name } ?: "",
renaming = appId != null
)
)
private val _actions = Channel<AuthenticatorNameAction>(Channel.BUFFERED)
val state: StateFlow<AuthenticatorNameState> = _state.asStateFlow()
val actions: Flow<AuthenticatorNameAction> = _actions.receiveAsFlow()
override suspend fun processEvent(event: AuthenticatorNameEvent) {
when (event) {
AuthenticatorNameEvent.NavigateBackClicked -> {
_actions.send(AuthenticatorNameAction.NavigateBack)
}
is AuthenticatorNameEvent.NameChanged -> {
_state.update { it.copy(name = event.name) }
}
AuthenticatorNameEvent.NextClicked -> {
if (!_state.value.canSubmit) {
return
}
val name = _state.value.name.trim()
_state.update { it.copy(submitting = true) }
if (appId != null) {
repository.renameAuthenticatorApp(appId, name)
_actions.send(AuthenticatorNameAction.ShowAuthenticatorAppRenamed)
} else {
repository.addAuthenticatorApp(name)
_actions.send(AuthenticatorNameAction.ShowAuthenticatorAppSetUp)
}
_actions.send(AuthenticatorNameAction.NavigateToAuthenticatorApps)
}
}
}
}
@@ -1,47 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.os.Bundle
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryState.Purpose
import org.signal.core.util.logging.Log
/**
* The nav arguments the authenticator app screens pass between each other, and the parsing that turns them back into
* something typed. Keep the values in sync with the argument defaults declared for these destinations in
* app_settings_with_change_number.xml.
*/
object AuthenticatorNavArgs {
private val TAG = Log.tag(AuthenticatorNavArgs::class)
/** Which of [PURPOSE_ADD]/[PURPOSE_REMOVE] a code is being collected for. */
const val ARG_PURPOSE = "purpose"
const val PURPOSE_ADD = "ADD"
const val PURPOSE_REMOVE = "REMOVE"
/** The app being removed or renamed, or [NO_APP_ID] when the screen is acting on a newly paired app. */
const val ARG_APP_ID = "app_id"
const val NO_APP_ID = -1L
/** The app id in [arguments], or null when the screen is acting on a newly paired app. */
fun appId(arguments: Bundle?): Long? = arguments?.getLong(ARG_APP_ID, NO_APP_ID)?.takeIf { it != NO_APP_ID }
/** The purpose in [arguments], falling back to [Purpose.Add] rather than removing an app we can't identify. */
fun purpose(arguments: Bundle?): Purpose {
if (arguments?.getString(ARG_PURPOSE) != PURPOSE_REMOVE) {
return Purpose.Add
}
val appId = appId(arguments)
if (appId == null) {
Log.w(TAG, "Asked to remove an authenticator app without an id. Collecting a code to add one instead.")
return Purpose.Add
}
return Purpose.Remove(appId)
}
}
@@ -1,25 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import org.signal.appsettings.authenticatorapps.AuthenticatorApp
class AuthenticatorRepository {
fun getSetupKey(): String = AuthenticatorAppStore.MOCK_SETUP_KEY
fun getMaxApps(): Int = AuthenticatorAppStore.MAX_APPS
fun getAuthenticatorApps(): List<AuthenticatorApp> = AuthenticatorAppStore.getApps()
fun getAuthenticatorApp(id: Long): AuthenticatorApp? = AuthenticatorAppStore.getApp(id)
fun addAuthenticatorApp(name: String): Long = AuthenticatorAppStore.addApp(name, System.currentTimeMillis())
fun renameAuthenticatorApp(id: Long, name: String) = AuthenticatorAppStore.renameApp(id, name)
fun removeAuthenticatorApp(id: Long) = AuthenticatorAppStore.removeApp(id)
}
@@ -1,71 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.net.Uri
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupAction
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupEvent
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupState
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
/**
* Drives the screen that walks the user through pairing an authenticator app. The setup key is mocked up for now,
* since there's nothing to fetch it from yet.
*/
class AuthenticatorSetupViewModel(
repository: AuthenticatorRepository = AuthenticatorRepository()
) : EventDrivenViewModel<AuthenticatorSetupEvent>(TAG) {
companion object {
private val TAG = Log.tag(AuthenticatorSetupViewModel::class)
private const val ACCOUNT_LABEL = "Signal"
}
private val _state = MutableStateFlow(AuthenticatorSetupState(setupKey = repository.getSetupKey()))
private val _actions = Channel<AuthenticatorSetupAction>(Channel.BUFFERED)
val state: StateFlow<AuthenticatorSetupState> = _state.asStateFlow()
val actions: Flow<AuthenticatorSetupAction> = _actions.receiveAsFlow()
override suspend fun processEvent(event: AuthenticatorSetupEvent) {
when (event) {
AuthenticatorSetupEvent.NavigateBackClicked -> {
_actions.send(AuthenticatorSetupAction.NavigateBack)
}
AuthenticatorSetupEvent.OpenAuthenticatorAppClicked -> {
_actions.send(AuthenticatorSetupAction.LaunchAuthenticatorApp(buildSetupUri(_state.value.setupKey)))
}
AuthenticatorSetupEvent.CopyKeyClicked -> {
_actions.send(AuthenticatorSetupAction.CopyKeyToClipboard(_state.value.setupKey))
_actions.send(AuthenticatorSetupAction.ShowKeyCopied)
}
AuthenticatorSetupEvent.NoAuthenticatorAppFound -> {
_actions.send(AuthenticatorSetupAction.ShowNoAuthenticatorAppFound)
}
AuthenticatorSetupEvent.ContinueClicked -> {
_actions.send(AuthenticatorSetupAction.NavigateToCodeEntry)
}
}
}
private fun buildSetupUri(setupKey: String): String {
return Uri.Builder()
.scheme("otpauth")
.authority("totp")
.appendPath(ACCOUNT_LABEL)
.appendQueryParameter("secret", setupKey)
.appendQueryParameter("issuer", ACCOUNT_LABEL)
.build()
.toString()
}
}
@@ -0,0 +1,92 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import org.signal.libsignal.net.RequestResult
import java.security.SecureRandom
/**
* Stands in for the service until the gRPC methods land. Nothing here is persisted or sent anywhere, so it lasts only
* as long as the process does.
*
* It doesn't verify one-time passwords -- any code confirms the pending key. It does copy the service's behaviour where
* that behaviour shapes the screens: one pending key at a time, [TotpApi.MAX_KEYS] confirmed keys, ids drawn from the
* lowest free slot, and name length enforced.
*/
class InMemoryTotpApi : TotpApi {
companion object {
/** What the service generates: a 256-bit key. */
private const val KEY_LENGTH_BYTES = 32
}
private val lock = Any()
private val secureRandom = SecureRandom()
private var hasPendingKey = false
private val confirmedKeys = mutableMapOf<Int, TotpApi.Metadata>()
override suspend fun generateKey(): RequestResult<TotpApi.GeneratedKey, TotpApi.GenerateKeyError> = synchronized(lock) {
if (confirmedKeys.size >= TotpApi.MAX_KEYS) {
return RequestResult.NonSuccess(TotpApi.GenerateKeyError.TooManyKeys)
}
hasPendingKey = true
RequestResult.Success(TotpApi.GeneratedKey(key = ByteArray(KEY_LENGTH_BYTES).also { secureRandom.nextBytes(it) }))
}
override suspend fun confirmKey(oneTimePassword: Int, metadata: TotpApi.Metadata): RequestResult<Int, TotpApi.ConfirmKeyError> = synchronized(lock) {
requireNameFits(metadata)
if (!hasPendingKey) {
return RequestResult.NonSuccess(TotpApi.ConfirmKeyError.NotVerified)
}
if (confirmedKeys.size >= TotpApi.MAX_KEYS) {
return RequestResult.NonSuccess(TotpApi.ConfirmKeyError.TooManyKeys)
}
val keyId = nextKeyId()
confirmedKeys[keyId] = metadata
hasPendingKey = false
RequestResult.Success(keyId)
}
override suspend fun listKeys(): RequestResult<List<TotpApi.RemoteKey>, Nothing> = synchronized(lock) {
RequestResult.Success(
confirmedKeys.entries
.sortedBy { it.key }
.map { (keyId, metadata) -> TotpApi.RemoteKey(keyId = keyId, metadata = metadata) }
)
}
override suspend fun setKeyMetadata(keyId: Int, metadata: TotpApi.Metadata): RequestResult<Unit, TotpApi.SetKeyMetadataError> = synchronized(lock) {
requireNameFits(metadata)
if (keyId !in confirmedKeys) {
return RequestResult.NonSuccess(TotpApi.SetKeyMetadataError.KeyNotFound)
}
confirmedKeys[keyId] = metadata
RequestResult.Success(Unit)
}
override suspend fun removeKey(keyId: Int): RequestResult<Unit, Nothing> = synchronized(lock) {
confirmedKeys.remove(keyId)
RequestResult.Success(Unit)
}
/** The service hands out the lowest free id rather than counting upwards, so removing a key frees its id for reuse. */
private fun nextKeyId(): Int = TotpApi.KEY_ID_RANGE.first { it !in confirmedKeys }
private fun requireNameFits(metadata: TotpApi.Metadata) {
require(metadata.name.toByteArray(Charsets.UTF_8).size <= TotpApi.Metadata.NAME_MAX_LENGTH) {
"Name must be at most ${TotpApi.Metadata.NAME_MAX_LENGTH} bytes of UTF-8"
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import org.signal.core.util.censor
import org.signal.libsignal.net.BadRequestError
import org.signal.libsignal.net.RequestResult
import java.time.Instant
/**
* All TOTP operations.
*/
interface TotpApi {
companion object {
/** How many confirmed keys an account may have, which the service enforces. */
const val MAX_KEYS = 2
/** The ids the service will assign, which fit in a byte with the sign bit clear. */
val KEY_ID_RANGE = 0..127
}
/**
* Generates a new pending key, replacing any pending key already on the account. The key doesn't take effect, or show
* up in [listKeys], until [confirmKey] proves the caller kept a copy of it.
*/
suspend fun generateKey(): RequestResult<GeneratedKey, GenerateKeyError>
/**
* Confirms the pending key by proving a one-time password can be derived from it, and attaches [metadata] to it,
* returning the id the service assigned.
*/
suspend fun confirmKey(oneTimePassword: Int, metadata: Metadata): RequestResult<Int, ConfirmKeyError>
/** The confirmed keys on the account. Key material is never returned, only metadata and parameters. */
suspend fun listKeys(): RequestResult<List<RemoteKey>, Nothing>
/** Replaces the metadata attached to a confirmed key. */
suspend fun setKeyMetadata(keyId: Int, metadata: Metadata): RequestResult<Unit, SetKeyMetadataError>
/** Removes a key, which also succeeds when there's no key with that id, so retries look the same as the first try. */
suspend fun removeKey(keyId: Int): RequestResult<Unit, Nothing>
data class Metadata(val name: String, val createdAt: Instant) {
override fun toString(): String = "Metadata(name=${name.censor()}, createdAt=$createdAt)"
companion object {
/** How long [name] may be, in bytes of UTF-8, which is the room the service's metadata blob leaves for it. */
const val NAME_MAX_LENGTH = 98
}
}
data class GeneratedKey(val key: ByteArray) {
override fun equals(other: Any?): Boolean = other is GeneratedKey && key.contentEquals(other.key)
override fun hashCode(): Int = key.contentHashCode()
override fun toString(): String = "GeneratedKey()"
}
data class RemoteKey(
/** The account-specific id, in [KEY_ID_RANGE]. */
val keyId: Int,
val metadata: Metadata
) {
override fun toString(): String = "RemoteKey(keyId=$keyId)"
}
sealed interface GenerateKeyError : BadRequestError {
/** The account already has [MAX_KEYS] keys. */
data object TooManyKeys : GenerateKeyError
}
sealed interface ConfirmKeyError : BadRequestError {
/** The password was wrong, the clocks are too far apart, or there was no pending key. The service can't tell us which. */
data object NotVerified : ConfirmKeyError
/** The account filled up with keys between generating this one and confirming it. */
data object TooManyKeys : ConfirmKeyError
}
sealed interface SetKeyMetadataError : BadRequestError {
data object KeyNotFound : SetKeyMetadataError
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.os.Bundle
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.totpapplist.TotpAppListAction
import org.signal.appsettings.totpapplist.TotpAppListEvent
import org.signal.appsettings.totpapplist.TotpAppListScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.navigation.safeNavigate
import org.signal.appsettings.R as AppSettingsR
/**
* Lists the authenticator apps on the account. Carries out the [TotpAppListAction]s that need the nav graph.
*/
class TotpAppListFragment : ComposeFragment() {
companion object {
private val TAG = Log.tag(TotpAppListFragment::class)
}
private val viewModel: TotpAppListViewModel by viewModels()
@Composable
override fun FragmentContent() {
val state by viewModel.state.collectAsStateWithLifecycle()
CollectActions(viewModel.actions) { action -> handleAction(action) }
TotpAppListScreen(
state = state,
onEvent = viewModel::onEvent
)
}
override fun onResume() {
super.onResume()
viewModel.onEvent(TotpAppListEvent.ScreenResumed)
}
private fun handleAction(action: TotpAppListAction) {
when (action) {
TotpAppListAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
TotpAppListAction.NavigateToSetup -> {
findNavController().safeNavigate(R.id.action_authenticatorAppsFragment_to_authenticatorSetupFragment)
}
is TotpAppListAction.NavigateToRename -> {
findNavController().safeNavigate(
R.id.action_authenticatorAppsFragment_to_authenticatorNameFragment,
Bundle().apply { TotpNavArgs.putRenamedApp(this, action.app) }
)
}
TotpAppListAction.ShowTotpAppRemoved -> toast(AppSettingsR.string.TotpAppListScreen__authenticator_app_removed)
TotpAppListAction.ShowRemovalFailed -> toast(AppSettingsR.string.TotpAppListScreen__couldnt_remove_authenticator_app)
TotpAppListAction.OpenLearnMore -> Log.w(TAG, "There's no support article to open yet.")
}
}
private fun toast(@StringRes message: Int) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
}
@@ -0,0 +1,109 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.signal.appsettings.totpapplist.TotpAppListAction
import org.signal.appsettings.totpapplist.TotpAppListEvent
import org.signal.appsettings.totpapplist.TotpAppListState
import org.signal.appsettings.totpapplist.TotpAppListState.Dialog
import org.signal.appsettings.totpapplist.TotpAppListState.LoadState
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
/**
* Drives the screen that lists the authenticator apps on the account.
*/
class TotpAppListViewModel(
private val repository: TotpRepository = TotpRepository()
) : EventDrivenViewModel<TotpAppListEvent>(TAG) {
companion object {
private val TAG = Log.tag(TotpAppListViewModel::class)
}
private val _state = MutableStateFlow(TotpAppListState(maxApps = repository.getMaxApps()))
private val _actions = Channel<TotpAppListAction>(Channel.BUFFERED)
val state: StateFlow<TotpAppListState> = _state.asStateFlow()
val actions: Flow<TotpAppListAction> = _actions.receiveAsFlow()
init {
viewModelScope.launch { refresh() }
}
override suspend fun processEvent(event: TotpAppListEvent) {
when (event) {
TotpAppListEvent.ScreenResumed -> {
refresh()
}
TotpAppListEvent.NavigateBackClicked -> {
_actions.send(TotpAppListAction.NavigateBack)
}
TotpAppListEvent.AddTotpAppClicked -> {
if (_state.value.atMaxApps) {
_state.update { it.copy(dialog = Dialog.MaxAppsReached) }
} else {
_actions.send(TotpAppListAction.NavigateToSetup)
}
}
TotpAppListEvent.LearnMoreClicked -> {
_actions.send(TotpAppListAction.OpenLearnMore)
}
is TotpAppListEvent.RenameAppClicked -> {
val app = _state.value.apps.firstOrNull { it.id == event.appId }
if (app == null) {
Log.w(TAG, "Asked to rename an app that isn't in the list.")
} else {
_actions.send(TotpAppListAction.NavigateToRename(app))
}
}
is TotpAppListEvent.RemoveAppClicked -> {
_state.update { it.copy(dialog = Dialog.ConfirmRemove(event.appId)) }
}
is TotpAppListEvent.RemoveAppConfirmed -> {
_state.update { it.copy(dialog = Dialog.None) }
removeApp(event.appId)
}
TotpAppListEvent.DialogDismissed -> {
_state.update { it.copy(dialog = Dialog.None) }
}
}
}
private suspend fun removeApp(appId: Long) {
when (repository.removeTotpApp(appId)) {
TotpRepository.UpdateResult.Success, TotpRepository.UpdateResult.AppNotFound -> {
_actions.send(TotpAppListAction.ShowTotpAppRemoved)
refresh()
}
TotpRepository.UpdateResult.NetworkFailure -> {
Log.w(TAG, "Couldn't remove the authenticator app. Leaving it in the list, where it still is.")
_actions.send(TotpAppListAction.ShowRemovalFailed)
}
}
}
private suspend fun refresh() {
when (val result = repository.getTotpApps()) {
is TotpRepository.AppsResult.Success -> {
_state.update { it.copy(apps = result.apps, loadState = LoadState.LOADED) }
}
TotpRepository.AppsResult.NetworkFailure -> {
Log.w(TAG, "Couldn't reach the service to list authenticator apps.")
_state.update { it.copy(apps = emptyList(), loadState = LoadState.NETWORK_FAILURE) }
}
}
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.totpcodeentry.TotpCodeEntryAction
import org.signal.appsettings.totpcodeentry.TotpCodeEntryScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.navigation.safeNavigate
/**
* Wrapper around [org.signal.appsettings.totpcodeentry.TotpCodeEntryScreen]
*/
class TotpCodeEntryFragment : ComposeFragment() {
/** A one-time code is not a credential, and a password manager offering to save one every time is pure noise. */
override val autofillEnabled: Boolean = false
private val viewModel: TotpCodeEntryViewModel by viewModels()
@Composable
override fun FragmentContent() {
val state by viewModel.state.collectAsStateWithLifecycle()
CollectActions(viewModel.actions) { action -> handleAction(action) }
TotpCodeEntryScreen(
state = state,
onEvent = viewModel::onEvent
)
}
private fun handleAction(action: TotpCodeEntryAction) {
when (action) {
TotpCodeEntryAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
is TotpCodeEntryAction.NavigateToNaming -> {
val args = Bundle().apply { putLong(TotpNavArgs.ARG_APP_ID, action.appId) }
findNavController().safeNavigate(R.id.action_authenticatorCodeEntryFragment_to_authenticatorNameFragment, args)
}
TotpCodeEntryAction.NavigateToSetup -> findNavController().popBackStack(R.id.authenticatorSetupFragment, false)
}
}
}
@@ -0,0 +1,83 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import org.signal.appsettings.totpcodeentry.TotpCodeEntryAction
import org.signal.appsettings.totpcodeentry.TotpCodeEntryEvent
import org.signal.appsettings.totpcodeentry.TotpCodeEntryState
import org.signal.appsettings.totpcodeentry.TotpCodeEntryState.Error
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
/**
* Drives the screen that collects a code from the user's authenticator app, which is how the service learns the user
* kept a copy of the key it just handed out.
*/
class TotpCodeEntryViewModel(
private val repository: TotpRepository = TotpRepository()
) : EventDrivenViewModel<TotpCodeEntryEvent>(TAG) {
companion object {
private val TAG = Log.tag(TotpCodeEntryViewModel::class)
}
private val _state = MutableStateFlow(TotpCodeEntryState())
private val _actions = Channel<TotpCodeEntryAction>(Channel.BUFFERED)
val state: StateFlow<TotpCodeEntryState> = _state.asStateFlow()
val actions: Flow<TotpCodeEntryAction> = _actions.receiveAsFlow()
override suspend fun processEvent(event: TotpCodeEntryEvent) {
when (event) {
TotpCodeEntryEvent.NavigateBackClicked -> {
_actions.send(TotpCodeEntryAction.NavigateBack)
}
is TotpCodeEntryEvent.CodeChanged -> {
val digits = event.code.filter { it.isDigit() }.take(TotpCodeEntryState.CODE_LENGTH)
_state.update { it.copy(code = digits, error = Error.None) }
}
TotpCodeEntryEvent.DoneClicked -> {
if (!_state.value.canSubmit) {
return
}
_state.update { it.copy(submitting = true, error = Error.None) }
confirmNewApp()
}
}
}
private suspend fun confirmNewApp() {
when (val result = repository.confirmPendingApp(_state.value.code)) {
is TotpRepository.ConfirmResult.Success -> {
_actions.send(TotpCodeEntryAction.NavigateToNaming(result.appId))
}
TotpRepository.ConfirmResult.IncorrectCode -> {
fail(Error.IncorrectCode)
}
TotpRepository.ConfirmResult.TooManyApps -> {
Log.w(TAG, "The account filled up while this key was pending. Going back to setup, which will explain the limit.")
_state.update { it.copy(submitting = false) }
_actions.send(TotpCodeEntryAction.NavigateToSetup)
}
TotpRepository.ConfirmResult.NetworkFailure -> {
fail(Error.NetworkFailure)
}
}
}
private fun fail(error: Error) {
_state.update { it.copy(submitting = false, error = error) }
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.widget.Toast
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.totpnameentry.TotpNameEntryAction
import org.signal.appsettings.totpnameentry.TotpNameEntryScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.viewModel
import org.signal.appsettings.R as AppSettingsR
/**
* Wrapper around [TotpNameEntryScreen].
*/
class TotpNameEntryFragment : ComposeFragment() {
/** The name the user gives an authenticator app is not a credential, so there's nothing here worth offering to save. */
override val autofillEnabled: Boolean = false
private val viewModel: TotpNameEntryViewModel by viewModel {
TotpNameEntryViewModel(
appId = TotpNavArgs.appId(arguments) ?: TotpNavArgs.NO_APP_ID,
renamedApp = TotpNavArgs.renamedApp(arguments)
)
}
@Composable
override fun FragmentContent() {
val state by viewModel.state.collectAsStateWithLifecycle()
CollectActions(viewModel.actions) { action -> handleAction(action) }
TotpNameEntryScreen(
state = state,
onEvent = viewModel::onEvent
)
}
private fun handleAction(action: TotpNameEntryAction) {
when (action) {
TotpNameEntryAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
TotpNameEntryAction.NavigateToTotpAppList -> findNavController().popBackStack(R.id.authenticatorAppsFragment, false)
TotpNameEntryAction.ShowTotpAppSetUp -> toast(AppSettingsR.string.TotpNameEntryScreen__authenticator_app_set_up)
TotpNameEntryAction.ShowTotpAppRenamed -> toast(AppSettingsR.string.TotpNameEntryScreen__authenticator_app_renamed)
TotpNameEntryAction.ShowNameNotSaved -> toast(AppSettingsR.string.TotpNameEntryScreen__couldnt_save_name)
}
}
private fun toast(@StringRes message: Int) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
}
@@ -0,0 +1,100 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import org.signal.appsettings.totpapplist.TotpApp
import org.signal.appsettings.totpnameentry.TotpNameEntryAction
import org.signal.appsettings.totpnameentry.TotpNameEntryEvent
import org.signal.appsettings.totpnameentry.TotpNameEntryState
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.BreakIteratorCompat
import org.signal.core.util.StringUtil
import org.signal.core.util.logging.Log
/**
* Handles both naming and renaming TOTP apps.
*/
class TotpNameEntryViewModel(
private val appId: Long,
private val renamedApp: TotpApp? = null,
private val repository: TotpRepository = TotpRepository()
) : EventDrivenViewModel<TotpNameEntryEvent>(TAG) {
companion object {
private val TAG = Log.tag(TotpNameEntryViewModel::class)
}
private val breakIterator = BreakIteratorCompat.getInstance()
private val _state = MutableStateFlow(
TotpNameEntryState(
renaming = renamedApp != null,
name = renamedApp?.name?.trimNameToLengthLimits() ?: ""
)
)
private val _actions = Channel<TotpNameEntryAction>(Channel.BUFFERED)
val state: StateFlow<TotpNameEntryState> = _state.asStateFlow()
val actions: Flow<TotpNameEntryAction> = _actions.receiveAsFlow()
override suspend fun processEvent(event: TotpNameEntryEvent) {
when (event) {
TotpNameEntryEvent.NavigateBackClicked -> {
_actions.send(TotpNameEntryAction.NavigateBack)
}
is TotpNameEntryEvent.NameChanged -> {
_state.update { it.copy(name = event.name.trimNameToLengthLimits()) }
}
TotpNameEntryEvent.NextClicked -> {
if (!_state.value.canSubmit) {
return
}
val name = _state.value.name.trim()
_state.update { it.copy(submitting = true) }
val result = if (renamedApp != null) {
repository.renameTotpApp(renamedApp, name)
} else {
repository.nameNewTotpApp(appId, name)
}
when (result) {
TotpRepository.UpdateResult.Success -> {
_actions.send(if (renamedApp != null) TotpNameEntryAction.ShowTotpAppRenamed else TotpNameEntryAction.ShowTotpAppSetUp)
_actions.send(TotpNameEntryAction.NavigateToTotpAppList)
}
TotpRepository.UpdateResult.AppNotFound -> {
Log.w(TAG, "Asked to name an app the service doesn't have. Going back to the list rather than stranding the user here.")
_actions.send(TotpNameEntryAction.NavigateToTotpAppList)
}
TotpRepository.UpdateResult.NetworkFailure -> {
_state.update { it.copy(submitting = false) }
_actions.send(TotpNameEntryAction.ShowNameNotSaved)
}
}
}
}
}
/** Keeps totp name within length limits */
private fun String.trimNameToLengthLimits(): String {
val input = this
val graphemeTruncated = breakIterator
.apply { setText(input) }
.take(TotpRepository.MAX_NAME_LENGTH_GRAPHEMES)
.toString()
return StringUtil.trimToFit(graphemeTruncated, TotpRepository.MAX_NAME_LENGTH_BYTES)
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.os.Bundle
import org.signal.appsettings.totpapplist.TotpApp
/**
* The nav arguments the authenticator app screens pass between each other, and the parsing that turns them back into
* something typed. Keep the values in sync with the argument defaults declared for these destinations in
* app_settings_with_change_number.xml.
*/
object TotpNavArgs {
/** The app being acted on. [NO_APP_ID] when nothing identified one. */
const val ARG_APP_ID = "app_id"
const val NO_APP_ID = -1L
/** The rest of the app being renamed. Absent when the screen is naming a newly paired app instead. */
const val ARG_APP_NAME = "app_name"
const val ARG_APP_CREATED_AT = "app_created_at"
const val NO_CREATED_AT = -1L
/** The app id in [arguments], or null when there isn't one. */
fun appId(arguments: Bundle?): Long? = arguments?.getLong(ARG_APP_ID, NO_APP_ID)?.takeIf { it != NO_APP_ID }
/** Packs [app] into [bundle] for the rename flow, so the name screen doesn't have to fetch what the list already had. */
fun putRenamedApp(bundle: Bundle, app: TotpApp) {
bundle.putLong(ARG_APP_ID, app.id)
bundle.putString(ARG_APP_NAME, app.name)
bundle.putLong(ARG_APP_CREATED_AT, app.createdAt)
}
/** The app being renamed, or null when [arguments] describe naming a newly paired app rather than a rename. */
fun renamedApp(arguments: Bundle?): TotpApp? {
val appId = appId(arguments) ?: return null
val createdAt = arguments?.getLong(ARG_APP_CREATED_AT, NO_CREATED_AT)?.takeIf { it != NO_CREATED_AT } ?: return null
return TotpApp(id = appId, name = arguments.getString(ARG_APP_NAME).orEmpty(), createdAt = createdAt)
}
}
@@ -0,0 +1,243 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import org.signal.appsettings.totpapplist.TotpApp
import org.signal.core.util.Base32
import org.signal.core.util.logging.Log
import org.signal.libsignal.net.RequestResult
import java.net.URLEncoder
import java.time.Instant
/**
* Everything the authenticator app screens need, sitting between them and the TOTP operations on [TotpApi].
*/
class TotpRepository(
private val api: TotpApi = SHARED_API,
private val clock: () -> Long = System::currentTimeMillis
) {
companion object {
private val TAG = Log.tag(TotpRepository::class)
/** Shared so that every screen in the flow sees the same state until there's a service behind this. */
private val SHARED_API: TotpApi = InMemoryTotpApi()
private const val ISSUER = "Signal"
/** What the service uses, and what every authenticator app supports without reading a single URI parameter. */
private const val ALGORITHM = "SHA1"
private const val DIGITS = 6
private const val PERIOD_SECONDS = 30
/** How many characters of the display form go between spaces. */
private const val DISPLAY_GROUP_SIZE = 4
const val MAX_NAME_LENGTH_BYTES = TotpApi.Metadata.NAME_MAX_LENGTH
const val MAX_NAME_LENGTH_GRAPHEMES = 30
}
fun getMaxApps(): Int {
return TotpApi.MAX_KEYS
}
/**
* Asks the service for a new key, returning what the setup screen needs to hand it to an authenticator app. The
* service holds the pending key from here until [confirmPendingApp], so nothing is kept on this side.
*/
suspend fun beginSetup(accountName: String): BeginSetupResult {
return when (val result = api.generateKey()) {
is RequestResult.Success -> {
val key = result.result.key
BeginSetupResult.Success(
setupUri = buildSetupUri(key = key, accountName = accountName),
displayKey = Base32.encode(key).chunked(DISPLAY_GROUP_SIZE).joinToString(" "),
clipboardKey = Base32.encode(key)
)
}
is RequestResult.NonSuccess -> {
when (result.error) {
TotpApi.GenerateKeyError.TooManyKeys -> BeginSetupResult.TooManyApps
}
}
is RequestResult.RetryableNetworkError -> {
Log.w(TAG, "Couldn't generate a key.", result.networkError)
BeginSetupResult.NetworkFailure
}
is RequestResult.ApplicationError -> {
Log.w(TAG, "Couldn't generate a key.", result.cause)
BeginSetupResult.NetworkFailure
}
}
}
/**
* Confirms the pending key with a code from the user's authenticator app.
*
* The key is confirmed without a name, because the service wants metadata at confirmation time and the user doesn't
* name their app until the screen after this one. Naming it later means a brief window where a key has no name, which
* is a better failure than a window where the second factor isn't active yet.
*/
suspend fun confirmPendingApp(code: String): ConfirmResult {
val oneTimePassword = code.toIntOrNull() ?: return ConfirmResult.IncorrectCode
val metadata = TotpApi.Metadata(name = "", createdAt = Instant.ofEpochMilli(clock()))
return when (val result = api.confirmKey(oneTimePassword = oneTimePassword, metadata = metadata)) {
is RequestResult.Success -> {
ConfirmResult.Success(appId = result.result.toLong())
}
is RequestResult.NonSuccess -> when (result.error) {
TotpApi.ConfirmKeyError.NotVerified -> ConfirmResult.IncorrectCode
TotpApi.ConfirmKeyError.TooManyKeys -> {
Log.w(TAG, "The account filled up with keys between generating this one and confirming it.")
ConfirmResult.TooManyApps
}
}
is RequestResult.RetryableNetworkError -> {
Log.w(TAG, "Couldn't confirm the pending key.", result.networkError)
ConfirmResult.NetworkFailure
}
is RequestResult.ApplicationError -> {
Log.w(TAG, "Couldn't confirm the pending key.", result.cause)
ConfirmResult.NetworkFailure
}
}
}
/** The authenticator apps on the account, newest id last. */
suspend fun getTotpApps(): AppsResult {
return when (val result = api.listKeys()) {
is RequestResult.Success -> {
AppsResult.Success(
result.result.map { key ->
TotpApp(
id = key.keyId.toLong(),
name = key.metadata.name,
createdAt = key.metadata.createdAt.toEpochMilli()
)
}
)
}
is RequestResult.RetryableNetworkError -> {
Log.w(TAG, "Couldn't list keys.", result.networkError)
AppsResult.NetworkFailure
}
is RequestResult.ApplicationError -> {
Log.w(TAG, "Couldn't list keys.", result.cause)
AppsResult.NetworkFailure
}
is RequestResult.NonSuccess -> error("Code branch is unreachable")
}
}
/** Renames [app], which means handing the whole metadata blob back to the service. */
suspend fun renameTotpApp(app: TotpApp, name: String): UpdateResult {
return setMetadata(app.id, TotpApi.Metadata(name = name, createdAt = Instant.ofEpochMilli(app.createdAt)))
}
/** Names a newly confirmed app, which was confirmed without one moments ago. */
suspend fun nameNewTotpApp(appId: Long, name: String): UpdateResult {
return setMetadata(appId, TotpApi.Metadata(name = name, createdAt = Instant.ofEpochMilli(clock())))
}
suspend fun removeTotpApp(appId: Long): UpdateResult {
return when (val result = api.removeKey(appId.toInt())) {
is RequestResult.Success -> UpdateResult.Success
is RequestResult.RetryableNetworkError -> {
Log.w(TAG, "Couldn't remove the key.", result.networkError)
UpdateResult.NetworkFailure
}
is RequestResult.ApplicationError -> {
Log.w(TAG, "Couldn't remove the key.", result.cause)
UpdateResult.NetworkFailure
}
is RequestResult.NonSuccess -> error("Code branch is unreachable")
}
}
private suspend fun setMetadata(appId: Long, metadata: TotpApi.Metadata): UpdateResult {
return when (val result = api.setKeyMetadata(keyId = appId.toInt(), metadata = metadata)) {
is RequestResult.Success -> UpdateResult.Success
is RequestResult.NonSuccess -> when (result.error) {
TotpApi.SetKeyMetadataError.KeyNotFound -> UpdateResult.AppNotFound
}
is RequestResult.RetryableNetworkError -> {
Log.w(TAG, "Couldn't set key metadata.", result.networkError)
UpdateResult.NetworkFailure
}
is RequestResult.ApplicationError -> {
Log.w(TAG, "Couldn't set key metadata.", result.cause)
UpdateResult.NetworkFailure
}
}
}
/**
* The `otpauth://` URI that hands the key to an authenticator app, following the de facto Key Uri Format every app
* implements. Note that a lot of apps ignore params like "algorithm", but we set them just in case.
*/
private fun buildSetupUri(key: ByteArray, accountName: String): String {
val label = if (accountName.isBlank()) encode(ISSUER) else "${encode(ISSUER)}:${encode(accountName)}"
val query = listOf(
"secret" to Base32.encode(key),
"issuer" to ISSUER,
"algorithm" to ALGORITHM,
"digits" to DIGITS.toString(),
"period" to PERIOD_SECONDS.toString()
).joinToString("&") { (name, value) -> "$name=${encode(value)}" }
return "otpauth://totp/$label?$query"
}
/**
* [URLEncoder] targets form encoding rather than URIs, so it renders a space as `+` where a URI needs `%20`, and
* escapes `~` where a URI leaves it alone.
*/
private fun encode(value: String): String {
return URLEncoder.encode(value, Charsets.UTF_8.name())
.replace("+", "%20")
.replace("%7E", "~")
}
sealed interface BeginSetupResult {
data class Success(val setupUri: String, val displayKey: String, val clipboardKey: String) : BeginSetupResult {
override fun toString(): String = "Success()"
}
/** The account already has as many authenticator apps as it's allowed. */
data object TooManyApps : BeginSetupResult
data object NetworkFailure : BeginSetupResult
}
sealed interface ConfirmResult {
data class Success(val appId: Long) : ConfirmResult
data object IncorrectCode : ConfirmResult
/** Another device filled the account up between generating the key and confirming it. */
data object TooManyApps : ConfirmResult
data object NetworkFailure : ConfirmResult
}
sealed interface AppsResult {
data class Success(val apps: List<TotpApp>) : AppsResult
data object NetworkFailure : AppsResult
}
sealed interface UpdateResult {
data object Success : UpdateResult
data object AppNotFound : UpdateResult
data object NetworkFailure : UpdateResult
}
}
@@ -15,9 +15,9 @@ import androidx.compose.runtime.getValue
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupAction
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupEvent
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupScreen
import org.signal.appsettings.totpsetup.TotpSetupAction
import org.signal.appsettings.totpsetup.TotpSetupEvent
import org.signal.appsettings.totpsetup.TotpSetupScreen
import org.signal.core.ui.compose.CollectActions
import org.signal.core.ui.compose.ComposeFragment
import org.signal.core.util.Util
@@ -27,16 +27,16 @@ import org.thoughtcrime.securesms.util.navigation.safeNavigate
import org.signal.appsettings.R as AppSettingsR
/**
* Walks the user through setting up an authenticator app. Carries out the [AuthenticatorSetupAction]s that need an
* Walks the user through setting up an authenticator app. Carries out the [TotpSetupAction]s that need an
* Activity or the nav graph.
*/
class AuthenticatorSetupFragment : ComposeFragment() {
class TotpSetupFragment : ComposeFragment() {
companion object {
private val TAG = Log.tag(AuthenticatorSetupFragment::class)
private val TAG = Log.tag(TotpSetupFragment::class)
}
private val viewModel: AuthenticatorSetupViewModel by viewModels()
private val viewModel: TotpSetupViewModel by viewModels()
@Composable
override fun FragmentContent() {
@@ -44,29 +44,29 @@ class AuthenticatorSetupFragment : ComposeFragment() {
CollectActions(viewModel.actions) { action -> handleAction(action) }
AuthenticatorSetupScreen(
TotpSetupScreen(
state = state,
onEvent = viewModel::onEvent
)
}
private fun handleAction(action: AuthenticatorSetupAction) {
private fun handleAction(action: TotpSetupAction) {
when (action) {
AuthenticatorSetupAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
is AuthenticatorSetupAction.LaunchAuthenticatorApp -> launchAuthenticatorApp(action.uri)
is AuthenticatorSetupAction.CopyKeyToClipboard -> Util.copyToClipboard(requireContext(), action.key)
AuthenticatorSetupAction.ShowKeyCopied -> toast(AppSettingsR.string.AuthenticatorSetupScreen__copied_to_clipboard)
AuthenticatorSetupAction.ShowNoAuthenticatorAppFound -> toast(AppSettingsR.string.AuthenticatorSetupScreen__no_authenticator_app_found)
AuthenticatorSetupAction.NavigateToCodeEntry -> findNavController().safeNavigate(R.id.action_authenticatorSetupFragment_to_authenticatorCodeEntryFragment)
TotpSetupAction.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
is TotpSetupAction.LaunchTotpApp -> launchTotpApp(action.uri)
is TotpSetupAction.CopyKeyToClipboard -> Util.copyToClipboard(requireContext(), action.key)
TotpSetupAction.ShowKeyCopied -> toast(AppSettingsR.string.TotpSetupScreen__copied_to_clipboard)
TotpSetupAction.ShowNoTotpAppFound -> toast(AppSettingsR.string.TotpSetupScreen__no_authenticator_app_found)
TotpSetupAction.NavigateToCodeEntry -> findNavController().safeNavigate(R.id.action_authenticatorSetupFragment_to_authenticatorCodeEntryFragment)
}
}
private fun launchAuthenticatorApp(uri: String) {
private fun launchTotpApp(uri: String) {
try {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(uri)))
} catch (e: ActivityNotFoundException) {
Log.w(TAG, "No app is willing to handle the authenticator setup link.", e)
viewModel.onEvent(AuthenticatorSetupEvent.NoAuthenticatorAppFound)
viewModel.onEvent(TotpSetupEvent.NoTotpAppFound)
}
}
@@ -0,0 +1,95 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.signal.appsettings.totpsetup.TotpSetupAction
import org.signal.appsettings.totpsetup.TotpSetupEvent
import org.signal.appsettings.totpsetup.TotpSetupState
import org.signal.appsettings.totpsetup.TotpSetupState.Dialog
import org.signal.core.ui.compose.EventDrivenViewModel
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.keyvalue.SignalStore
import java.util.UUID
class TotpSetupViewModel(
private val repository: TotpRepository = TotpRepository(),
private val accountName: String = accountNameFor(SignalStore.account.aci?.rawUuid)
) : EventDrivenViewModel<TotpSetupEvent>(TAG) {
companion object {
private val TAG = Log.tag(TotpSetupViewModel::class)
@VisibleForTesting
fun accountNameFor(aci: UUID?): String = aci?.toString()?.substringBefore('-')?.uppercase().orEmpty()
}
private val _state = MutableStateFlow(TotpSetupState())
private val _actions = Channel<TotpSetupAction>(Channel.BUFFERED)
val state: StateFlow<TotpSetupState> = _state.asStateFlow()
val actions: Flow<TotpSetupAction> = _actions.receiveAsFlow()
/** The URI and clipboard forms of the key, which differ from the grouped form the screen shows. */
private var setupUri: String = ""
private var clipboardKey: String = ""
init {
viewModelScope.launch { beginSetup() }
}
override suspend fun processEvent(event: TotpSetupEvent) {
when (event) {
TotpSetupEvent.NavigateBackClicked -> {
_actions.send(TotpSetupAction.NavigateBack)
}
TotpSetupEvent.OpenTotpAppClicked -> {
_actions.send(TotpSetupAction.LaunchTotpApp(setupUri))
}
TotpSetupEvent.CopyKeyClicked -> {
_actions.send(TotpSetupAction.CopyKeyToClipboard(clipboardKey))
_actions.send(TotpSetupAction.ShowKeyCopied)
}
TotpSetupEvent.NoTotpAppFound -> {
_actions.send(TotpSetupAction.ShowNoTotpAppFound)
}
TotpSetupEvent.ContinueClicked -> {
_actions.send(TotpSetupAction.NavigateToCodeEntry)
}
TotpSetupEvent.DialogDismissed -> {
_state.update { it.copy(dialog = Dialog.None) }
_actions.send(TotpSetupAction.NavigateBack)
}
}
}
private suspend fun beginSetup() {
when (val result = repository.beginSetup(accountName)) {
is TotpRepository.BeginSetupResult.Success -> {
setupUri = result.setupUri
clipboardKey = result.clipboardKey
_state.update { it.copy(setupKey = result.displayKey, loading = false) }
}
TotpRepository.BeginSetupResult.TooManyApps -> {
Log.w(TAG, "The account already has as many authenticator apps as it's allowed.")
_state.update { it.copy(loading = false, dialog = Dialog.MaxAppsReached(repository.getMaxApps())) }
}
TotpRepository.BeginSetupResult.NetworkFailure -> {
Log.w(TAG, "Couldn't reach the service to start setup.")
_state.update { it.copy(loading = false, dialog = Dialog.NetworkFailure) }
}
}
}
}
@@ -183,7 +183,8 @@ class AppRegistrationNetworkController(
pniPreKeys: PreKeyCollection?,
fcmToken: String?,
skipDeviceTransfer: Boolean,
aci: ACI?
aci: ACI?,
totp: Int?
): RequestResult<RegisterAccountResponse, RegisterAccountError> {
return registrationApi.registerAccount(
e164 = e164,
@@ -196,7 +197,8 @@ class AppRegistrationNetworkController(
pniPreKeys = pniPreKeys,
fcmToken = fcmToken,
skipDeviceTransfer = skipDeviceTransfer,
aci = aci
aci = aci,
totp = totp
)
}
@@ -246,7 +246,7 @@
<fragment
android:id="@+id/authenticatorAppsFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.AuthenticatorAppsFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpAppListFragment"
android:label="authenticator_apps_fragment">
<action
android:id="@+id/action_authenticatorAppsFragment_to_authenticatorSetupFragment"
@@ -262,18 +262,11 @@
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/action_authenticatorAppsFragment_to_authenticatorCodeEntryFragment"
app:destination="@id/authenticatorCodeEntryFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<fragment
android:id="@+id/authenticatorSetupFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.AuthenticatorSetupFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpSetupFragment"
android:label="authenticator_setup_fragment">
<action
android:id="@+id/action_authenticatorSetupFragment_to_authenticatorCodeEntryFragment"
@@ -286,7 +279,7 @@
<fragment
android:id="@+id/authenticatorCodeEntryFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.AuthenticatorCodeEntryFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpCodeEntryFragment"
android:label="authenticator_code_entry_fragment">
<action
android:id="@+id/action_authenticatorCodeEntryFragment_to_authenticatorNameFragment"
@@ -295,25 +288,25 @@
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<argument
android:name="purpose"
android:defaultValue="ADD"
app:argType="string" />
<fragment
android:id="@+id/authenticatorNameFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpNameEntryFragment"
android:label="authenticator_name_fragment">
<argument
android:name="app_id"
android:defaultValue="-1L"
app:argType="long" />
</fragment>
<fragment
android:id="@+id/authenticatorNameFragment"
android:name="org.thoughtcrime.securesms.components.settings.app.account.authenticator.AuthenticatorNameFragment"
android:label="authenticator_name_fragment">
<argument
android:name="app_id"
android:name="app_name"
android:defaultValue=""
app:argType="string" />
<argument
android:name="app_created_at"
android:defaultValue="-1L"
app:argType="long" />
</fragment>
@@ -63,7 +63,7 @@ class AccountSettingsViewModelTest {
every { repository.isClientDeprecated() } returns false
every { repository.getPinKeyboardType() } returns PinKeyboardType.NUMERIC
every { repository.isPhoneNumberless() } returns false
every { repository.getAuthenticatorAppCount() } returns 0
coEvery { repository.getTotpAppCount() } returns 0
every { repository.getPasskeyCount() } returns 0
every { repository.verifyLocalPin(any()) } answers { firstArg<String>() == CORRECT_PIN }
coEvery { repository.setRegistrationLockEnabled(any()) } returns true
@@ -303,16 +303,27 @@ class AccountSettingsViewModelTest {
@Test
fun `the Signal Login section is filled in when the account is phone-numberless`() = runTest(testDispatcher) {
every { repository.isPhoneNumberless() } returns true
every { repository.getAuthenticatorAppCount() } returns 2
coEvery { repository.getTotpAppCount() } returns 2
every { repository.getPasskeyCount() } returns 8
val viewModel = createViewModel()
assertThat(viewModel.state.value.isPhoneNumberless).isTrue()
assertThat(viewModel.state.value.signalLogin?.authenticatorAppCount).isEqualTo(2)
assertThat(viewModel.state.value.signalLogin?.totpAppCount).isEqualTo(2)
assertThat(viewModel.state.value.signalLogin?.passkeyCount).isEqualTo(8)
}
/** Zero would render as "no authenticator apps", which is a claim we can't make when we couldn't reach the service. */
@Test
fun `a count we couldn't fetch is null rather than zero`() = runTest(testDispatcher) {
every { repository.isPhoneNumberless() } returns true
coEvery { repository.getTotpAppCount() } returns null
val viewModel = createViewModel()
assertThat(viewModel.state.value.signalLogin?.totpAppCount).isNull()
}
@Test
fun `AccountAndRecoveryClicked opens the Signal Login details screen`() = runTest(testDispatcher) {
every { repository.isPhoneNumberless() } returns true
@@ -326,15 +337,15 @@ class AccountSettingsViewModelTest {
}
@Test
fun `AuthenticatorAppClicked opens the authenticator apps screen`() = runTest(testDispatcher) {
fun `TotpAppClicked opens the authenticator apps screen`() = runTest(testDispatcher) {
every { repository.isPhoneNumberless() } returns true
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AccountSettingsEvent.AuthenticatorAppClicked)
viewModel.onEvent(AccountSettingsEvent.TotpAppClicked)
assertThat(actions.last()).isEqualTo(AccountSettingsAction.NavigateToAuthenticatorApps)
assertThat(actions.last()).isEqualTo(AccountSettingsAction.NavigateToTotpAppList)
}
@Test
@@ -1,195 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.containsExactly
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.authenticatorapps.AuthenticatorApp
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsAction
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsEvent
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsState.Dialog
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
class AuthenticatorAppsViewModelTest {
companion object {
private val APP_ONE = AuthenticatorApp(id = 1, name = "Bitwarden Authenticator", createdAt = 0)
private val APP_TWO = AuthenticatorApp(id = 2, name = "Twilio Authy", createdAt = 0)
}
private val testDispatcher = UnconfinedTestDispatcher()
private val repository: AuthenticatorRepository = mockk(relaxed = true)
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
every { repository.getMaxApps() } returns 2
every { repository.getAuthenticatorApps() } returns emptyList()
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `the configured apps are read on creation`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
val viewModel = createViewModel()
assertThat(viewModel.state.value.apps).containsExactly(APP_ONE)
}
@Test
fun `ScreenResumed picks up apps added elsewhere`() = runTest(testDispatcher) {
val viewModel = createViewModel()
assertThat(viewModel.state.value.apps).isEmpty()
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
viewModel.onEvent(AuthenticatorAppsEvent.ScreenResumed)
assertThat(viewModel.state.value.apps).containsExactly(APP_ONE)
}
@Test
fun `AddAuthenticatorAppClicked opens setup when there's room for another app`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.AddAuthenticatorAppClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorAppsAction.NavigateToSetup)
}
@Test
fun `AddAuthenticatorAppClicked explains the limit when there's no room for another app`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE, APP_TWO)
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.AddAuthenticatorAppClicked)
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.MaxAppsReached)
assertThat(actions).isEmpty()
}
@Test
fun `RenameAppClicked opens the naming screen for that app`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.RenameAppClicked(APP_ONE.id))
assertThat(actions.last()).isEqualTo(AuthenticatorAppsAction.NavigateToRename(APP_ONE.id))
}
@Test
fun `RemoveAppClicked asks the user to confirm first`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.RemoveAppClicked(APP_ONE.id))
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.ConfirmRemove(APP_ONE.id))
assertThat(actions).isEmpty()
}
@Test
fun `RemoveAppConfirmed collects a code before removing the app`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.RemoveAppClicked(APP_ONE.id))
viewModel.onEvent(AuthenticatorAppsEvent.RemoveAppConfirmed)
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.None)
assertThat(actions.last()).isEqualTo(AuthenticatorAppsAction.NavigateToRemovalCodeEntry(APP_ONE.id))
}
@Test
fun `RemoveAppConfirmed does nothing when no removal is pending`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.RemoveAppConfirmed)
assertThat(actions).isEmpty()
}
@Test
fun `DialogDismissed clears the dialog`() = runTest(testDispatcher) {
every { repository.getAuthenticatorApps() } returns listOf(APP_ONE)
val viewModel = createViewModel()
viewModel.onEvent(AuthenticatorAppsEvent.RemoveAppClicked(APP_ONE.id))
viewModel.onEvent(AuthenticatorAppsEvent.DialogDismissed)
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.None)
}
@Test
fun `NavigateBackClicked leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorAppsAction.NavigateBack)
}
@Test
fun `LearnMoreClicked opens the support article`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorAppsEvent.LearnMoreClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorAppsAction.OpenLearnMore)
}
private fun createViewModel() = AuthenticatorAppsViewModel(repository)
private fun TestScope.collectActions(actions: Flow<AuthenticatorAppsAction>): List<AuthenticatorAppsAction> {
val collected = mutableListOf<AuthenticatorAppsAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -1,125 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryAction
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryEvent
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryState.Purpose
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
class AuthenticatorCodeEntryViewModelTest {
companion object {
private const val FULL_CODE = "123456"
}
private val testDispatcher = UnconfinedTestDispatcher()
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
clearApps()
}
@After
fun tearDown() {
Dispatchers.resetMain()
clearApps()
}
@Test
fun `non-digits are dropped and the code is capped at six digits`() = runTest(testDispatcher) {
val viewModel = createViewModel()
viewModel.onEvent(AuthenticatorCodeEntryEvent.CodeChanged("12a34 5678"))
assertThat(viewModel.state.value.code).isEqualTo(FULL_CODE)
}
@Test
fun `a partial code can't be submitted`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorCodeEntryEvent.CodeChanged("123"))
assertThat(viewModel.state.value.canSubmit).isFalse()
viewModel.onEvent(AuthenticatorCodeEntryEvent.DoneClicked)
assertThat(actions).isEmpty()
}
@Test
fun `a full code entered while adding sends the user on to name the app`() = runTest(testDispatcher) {
val viewModel = createViewModel(purpose = Purpose.Add)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorCodeEntryEvent.CodeChanged(FULL_CODE))
viewModel.onEvent(AuthenticatorCodeEntryEvent.DoneClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorCodeEntryAction.NavigateToNaming)
}
@Test
fun `a full code entered while removing removes the app and goes back to the list`() = runTest(testDispatcher) {
val appId = AuthenticatorAppStore.addApp(name = "Bitwarden Authenticator", createdAt = 0)
val viewModel = createViewModel(purpose = Purpose.Remove(appId))
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorCodeEntryEvent.CodeChanged(FULL_CODE))
viewModel.onEvent(AuthenticatorCodeEntryEvent.DoneClicked)
assertThat(AuthenticatorAppStore.getApps()).isEmpty()
assertThat(actions).contains(AuthenticatorCodeEntryAction.ShowAuthenticatorAppRemoved)
assertThat(actions.last()).isEqualTo(AuthenticatorCodeEntryAction.NavigateToAuthenticatorApps)
}
@Test
fun `NavigateBackClicked leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorCodeEntryEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorCodeEntryAction.NavigateBack)
}
private fun createViewModel(purpose: Purpose = Purpose.Add) = AuthenticatorCodeEntryViewModel(purpose = purpose)
private fun clearApps() {
AuthenticatorAppStore.getApps().forEach { AuthenticatorAppStore.removeApp(it.id) }
}
private fun TestScope.collectActions(actions: Flow<AuthenticatorCodeEntryAction>): List<AuthenticatorCodeEntryAction> {
val collected = mutableListOf<AuthenticatorCodeEntryAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -1,134 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.authenticatorapps.AuthenticatorApp
import org.signal.appsettings.authenticatorname.AuthenticatorNameAction
import org.signal.appsettings.authenticatorname.AuthenticatorNameEvent
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
class AuthenticatorNameViewModelTest {
companion object {
private val EXISTING_APP = AuthenticatorApp(id = 7, name = "Twilio Authy", createdAt = 0)
}
private val testDispatcher = UnconfinedTestDispatcher()
private val repository: AuthenticatorRepository = mockk(relaxed = true)
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
every { repository.getAuthenticatorApp(EXISTING_APP.id) } returns EXISTING_APP
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `naming a new app starts empty and isn't renaming`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = null)
assertThat(viewModel.state.value.name).isEqualTo("")
assertThat(viewModel.state.value.renaming).isFalse()
}
@Test
fun `renaming starts from the app's current name`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = EXISTING_APP.id)
assertThat(viewModel.state.value.name).isEqualTo(EXISTING_APP.name)
assertThat(viewModel.state.value.renaming).isTrue()
}
@Test
fun `a blank name can't be submitted`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = null)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorNameEvent.NameChanged(" "))
assertThat(viewModel.state.value.canSubmit).isFalse()
viewModel.onEvent(AuthenticatorNameEvent.NextClicked)
assertThat(actions).isEmpty()
}
@Test
fun `NextClicked adds a new app and goes back to the list`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = null)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorNameEvent.NameChanged(" Bitwarden Authenticator "))
viewModel.onEvent(AuthenticatorNameEvent.NextClicked)
verify { repository.addAuthenticatorApp("Bitwarden Authenticator") }
assertThat(actions).contains(AuthenticatorNameAction.ShowAuthenticatorAppSetUp)
assertThat(actions.last()).isEqualTo(AuthenticatorNameAction.NavigateToAuthenticatorApps)
}
@Test
fun `NextClicked renames an existing app and goes back to the list`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = EXISTING_APP.id)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorNameEvent.NameChanged("Work Authenticator"))
viewModel.onEvent(AuthenticatorNameEvent.NextClicked)
verify { repository.renameAuthenticatorApp(EXISTING_APP.id, "Work Authenticator") }
assertThat(actions).contains(AuthenticatorNameAction.ShowAuthenticatorAppRenamed)
assertThat(actions.last()).isEqualTo(AuthenticatorNameAction.NavigateToAuthenticatorApps)
}
@Test
fun `NavigateBackClicked leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = null)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorNameEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorNameAction.NavigateBack)
}
private fun createViewModel(appId: Long?) = AuthenticatorNameViewModel(appId, repository)
private fun TestScope.collectActions(actions: Flow<AuthenticatorNameAction>): List<AuthenticatorNameAction> {
val collected = mutableListOf<AuthenticatorNameAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -1,60 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.app.Application
import android.os.Bundle
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNull
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.appsettings.authenticatorcodeentry.AuthenticatorCodeEntryState.Purpose
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class AuthenticatorNavArgsTest {
@Test
fun `no arguments means adding a new app`() {
assertThat(AuthenticatorNavArgs.purpose(null)).isEqualTo(Purpose.Add)
assertThat(AuthenticatorNavArgs.appId(null)).isNull()
}
@Test
fun `an unset app id reads as null`() {
val arguments = Bundle().apply { putLong(AuthenticatorNavArgs.ARG_APP_ID, AuthenticatorNavArgs.NO_APP_ID) }
assertThat(AuthenticatorNavArgs.appId(arguments)).isNull()
}
@Test
fun `a removal carries the app id it names`() {
val arguments = Bundle().apply {
putString(AuthenticatorNavArgs.ARG_PURPOSE, AuthenticatorNavArgs.PURPOSE_REMOVE)
putLong(AuthenticatorNavArgs.ARG_APP_ID, 7)
}
assertThat(AuthenticatorNavArgs.appId(arguments)).isEqualTo(7L)
assertThat(AuthenticatorNavArgs.purpose(arguments)).isEqualTo(Purpose.Remove(7))
}
@Test
fun `a removal without an app id falls back to adding rather than removing something unidentified`() {
val arguments = Bundle().apply { putString(AuthenticatorNavArgs.ARG_PURPOSE, AuthenticatorNavArgs.PURPOSE_REMOVE) }
assertThat(AuthenticatorNavArgs.purpose(arguments)).isEqualTo(Purpose.Add)
}
@Test
fun `an unrecognized purpose falls back to adding instead of throwing`() {
val arguments = Bundle().apply { putString(AuthenticatorNavArgs.ARG_PURPOSE, "nonsense") }
assertThat(AuthenticatorNavArgs.purpose(arguments)).isEqualTo(Purpose.Add)
}
}
@@ -1,109 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.app.Application
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEqualTo
import assertk.assertions.isInstanceOf
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupAction
import org.signal.appsettings.authenticatorsetup.AuthenticatorSetupEvent
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class AuthenticatorSetupViewModelTest {
private val testDispatcher = UnconfinedTestDispatcher()
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `the setup key is available as soon as the screen opens`() = runTest(testDispatcher) {
val viewModel = AuthenticatorSetupViewModel()
assertThat(viewModel.state.value.setupKey).isEqualTo(AuthenticatorAppStore.MOCK_SETUP_KEY)
}
@Test
fun `OpenAuthenticatorAppClicked hands off a link carrying the setup key`() = runTest(testDispatcher) {
val viewModel = AuthenticatorSetupViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorSetupEvent.OpenAuthenticatorAppClicked)
val action = actions.last()
assertThat(action).isInstanceOf(AuthenticatorSetupAction.LaunchAuthenticatorApp::class)
assertThat((action as AuthenticatorSetupAction.LaunchAuthenticatorApp).uri).contains(AuthenticatorAppStore.MOCK_SETUP_KEY)
}
@Test
fun `CopyKeyClicked copies the key and tells the user`() = runTest(testDispatcher) {
val viewModel = AuthenticatorSetupViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorSetupEvent.CopyKeyClicked)
assertThat(actions).contains(AuthenticatorSetupAction.CopyKeyToClipboard(AuthenticatorAppStore.MOCK_SETUP_KEY))
assertThat(actions.last()).isEqualTo(AuthenticatorSetupAction.ShowKeyCopied)
}
@Test
fun `ContinueClicked moves on to code entry`() = runTest(testDispatcher) {
val viewModel = AuthenticatorSetupViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorSetupEvent.ContinueClicked)
assertThat(actions.last()).isEqualTo(AuthenticatorSetupAction.NavigateToCodeEntry)
}
@Test
fun `NoAuthenticatorAppFound reports the failure`() = runTest(testDispatcher) {
val viewModel = AuthenticatorSetupViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(AuthenticatorSetupEvent.NoAuthenticatorAppFound)
assertThat(actions.last()).isEqualTo(AuthenticatorSetupAction.ShowNoAuthenticatorAppFound)
}
private fun TestScope.collectActions(actions: Flow<AuthenticatorSetupAction>): List<AuthenticatorSetupAction> {
val collected = mutableListOf<AuthenticatorSetupAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -0,0 +1,129 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.hasSize
import assertk.assertions.isEqualTo
import assertk.assertions.isInstanceOf
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.signal.libsignal.net.RequestResult
import java.time.Instant
/**
* Covers the parts of the stand-in that copy behaviour the service is strict about, since those are the parts most
* likely to be wrong once there's a real service behind [TotpApi].
*/
class InMemoryTotpApiTest {
companion object {
private const val NOW = 1_700_000_000_000L
private const val CODE = 123456
private val METADATA = TotpApi.Metadata(name = "Aegis", createdAt = Instant.ofEpochMilli(NOW))
private val OTHER_METADATA = TotpApi.Metadata(name = "Aegis on my tablet", createdAt = Instant.ofEpochMilli(NOW))
}
private val api = InMemoryTotpApi()
@Test
fun `a generated key is 32 bytes`() = runTest {
val result = api.generateKey()
assertThat(result).isInstanceOf(RequestResult.Success::class)
assertThat((result as RequestResult.Success).result.key.size).isEqualTo(32)
}
@Test
fun `a pending key doesn't show up until it's confirmed`() = runTest {
api.generateKey()
assertThat(listedKeys()).hasSize(0)
}
@Test
fun `a confirmed key is assigned the lowest free id`() = runTest {
val first = confirmNewKey()
val second = confirmNewKey()
assertThat(first).isEqualTo(0)
assertThat(second).isEqualTo(1)
}
@Test
fun `an id freed by a removal is handed out again rather than counting upwards`() = runTest {
confirmNewKey()
val second = confirmNewKey()
api.removeKey(second)
assertThat(confirmNewKey()).isEqualTo(second)
}
@Test
fun `confirming with no pending key doesn't confirm anything`() = runTest {
assertThat(api.confirmKey(oneTimePassword = CODE, metadata = METADATA)).isEqualTo(RequestResult.NonSuccess(TotpApi.ConfirmKeyError.NotVerified))
assertThat(listedKeys()).hasSize(0)
}
@Test
fun `an account at its limit can't generate another key`() = runTest {
repeat(TotpApi.MAX_KEYS) { confirmNewKey() }
assertThat(api.generateKey()).isEqualTo(RequestResult.NonSuccess(TotpApi.GenerateKeyError.TooManyKeys))
}
@Test
fun `removing a key makes room for another`() = runTest {
repeat(TotpApi.MAX_KEYS) { confirmNewKey() }
api.removeKey(0)
assertThat(api.generateKey()).isInstanceOf(RequestResult.Success::class)
}
@Test
fun `metadata can be replaced on a confirmed key`() = runTest {
val keyId = confirmNewKey()
assertThat(api.setKeyMetadata(keyId, OTHER_METADATA)).isEqualTo(RequestResult.Success(Unit))
assertThat(listedKeys().first().metadata).isEqualTo(OTHER_METADATA)
}
@Test
fun `metadata for a key that isn't there is reported rather than created`() = runTest {
assertThat(api.setKeyMetadata(7, METADATA)).isEqualTo(RequestResult.NonSuccess(TotpApi.SetKeyMetadataError.KeyNotFound))
}
/** The service leaves a fixed amount of room for the name, so a name that doesn't fit is the caller's bug. */
@Test
fun `a name longer than the room the service leaves is refused`() = runTest {
val keyId = confirmNewKey()
val tooLong = METADATA.copy(name = "a".repeat(TotpApi.Metadata.NAME_MAX_LENGTH + 1))
assertFailure { api.setKeyMetadata(keyId, tooLong) }.isInstanceOf(IllegalArgumentException::class)
}
/** The service reports success either way, so a retried removal looks like the original. */
@Test
fun `removing a key that isn't there still succeeds`() = runTest {
assertThat(api.removeKey(7)).isEqualTo(RequestResult.Success(Unit))
}
@Test
fun `keys are listed in ascending id order`() = runTest {
confirmNewKey()
confirmNewKey()
assertThat(listedKeys().map { it.keyId }).isEqualTo(listOf(0, 1))
}
private suspend fun confirmNewKey(): Int {
api.generateKey()
return (api.confirmKey(oneTimePassword = CODE, metadata = METADATA) as RequestResult.Success).result
}
private suspend fun listedKeys(): List<TotpApi.RemoteKey> = (api.listKeys() as RequestResult.Success).result
}
@@ -0,0 +1,280 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.containsExactly
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.totpapplist.TotpApp
import org.signal.appsettings.totpapplist.TotpAppListAction
import org.signal.appsettings.totpapplist.TotpAppListEvent
import org.signal.appsettings.totpapplist.TotpAppListState.Dialog
import org.signal.appsettings.totpapplist.TotpAppListState.LoadState
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
class TotpAppListViewModelTest {
companion object {
private val APP_ONE = TotpApp(id = 1, name = "Bitwarden Authenticator", createdAt = 0)
private val APP_TWO = TotpApp(id = 2, name = "Twilio Authy", createdAt = 0)
}
private val testDispatcher = UnconfinedTestDispatcher()
private val repository: TotpRepository = mockk(relaxed = true)
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
every { repository.getMaxApps() } returns 2
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(emptyList())
coEvery { repository.removeTotpApp(any()) } returns TotpRepository.UpdateResult.Success
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `the configured apps are read on creation`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
assertThat(viewModel.state.value.apps).containsExactly(APP_ONE)
}
/** An empty list says nothing on its own, so the screen leans on [LoadState] to know we haven't heard back yet. */
@Test
fun `the state is LOADING until we've heard back about the account`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } coAnswers { awaitCancellation() }
val viewModel = createViewModel()
assertThat(viewModel.state.value.loadState).isEqualTo(LoadState.LOADING)
assertThat(viewModel.state.value.apps).isEmpty()
}
@Test
fun `a service we couldn't reach clears the list and says so`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.NetworkFailure
val viewModel = createViewModel()
assertThat(viewModel.state.value.loadState).isEqualTo(LoadState.NETWORK_FAILURE)
assertThat(viewModel.state.value.apps).isEmpty()
}
@Test
fun `a load that succeeds after one that failed clears the failure`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.NetworkFailure
val viewModel = createViewModel()
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
viewModel.onEvent(TotpAppListEvent.ScreenResumed)
assertThat(viewModel.state.value.loadState).isEqualTo(LoadState.LOADED)
assertThat(viewModel.state.value.apps).containsExactly(APP_ONE)
}
@Test
fun `ScreenResumed picks up apps added elsewhere`() = runTest(testDispatcher) {
val viewModel = createViewModel()
assertThat(viewModel.state.value.apps).isEmpty()
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
viewModel.onEvent(TotpAppListEvent.ScreenResumed)
assertThat(viewModel.state.value.apps).containsExactly(APP_ONE)
}
@Test
fun `AddTotpAppClicked opens setup when there's room for another app`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.AddTotpAppClicked)
assertThat(actions.last()).isEqualTo(TotpAppListAction.NavigateToSetup)
}
@Test
fun `AddTotpAppClicked explains the limit when there's no room for another app`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE, APP_TWO))
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.AddTotpAppClicked)
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.MaxAppsReached)
assertThat(actions).isEmpty()
}
@Test
fun `RenameAppClicked opens the naming screen for that app`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.RenameAppClicked(APP_ONE.id))
assertThat(actions.last()).isEqualTo(TotpAppListAction.NavigateToRename(APP_ONE))
}
@Test
fun `RemoveAppClicked asks the user to confirm first`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.RemoveAppClicked(APP_ONE.id))
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.ConfirmRemove(APP_ONE.id))
assertThat(actions).isEmpty()
}
@Test
fun `RemoveAppConfirmed removes the app and says so`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.RemoveAppClicked(APP_ONE.id))
viewModel.onEvent(TotpAppListEvent.RemoveAppConfirmed(APP_ONE.id))
coVerify { repository.removeTotpApp(APP_ONE.id) }
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.None)
assertThat(actions.last()).isEqualTo(TotpAppListAction.ShowTotpAppRemoved)
}
/** The list is what tells the user the app is gone, so it has to be read again rather than assumed. */
@Test
fun `a removal re-reads the list`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(emptyList())
viewModel.onEvent(TotpAppListEvent.RemoveAppConfirmed(APP_ONE.id))
assertThat(viewModel.state.value.apps).isEmpty()
}
/** Removing a key the service has already forgotten is the outcome the user wanted, so it isn't an error. */
@Test
fun `removing an app the service doesn't have still counts as removed`() = runTest(testDispatcher) {
coEvery { repository.removeTotpApp(any()) } returns TotpRepository.UpdateResult.AppNotFound
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.RemoveAppConfirmed(APP_ONE.id))
assertThat(actions.last()).isEqualTo(TotpAppListAction.ShowTotpAppRemoved)
}
@Test
fun `a removal that didn't go through says so rather than pretending the app is gone`() = runTest(testDispatcher) {
coEvery { repository.removeTotpApp(any()) } returns TotpRepository.UpdateResult.NetworkFailure
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.RemoveAppConfirmed(APP_ONE.id))
assertThat(actions.last()).isEqualTo(TotpAppListAction.ShowRemovalFailed)
}
/**
* What the confirm button actually does: the dialog dismisses itself before it reports the confirmation, so the
* removal has to survive arriving after the dialog is already gone.
*/
@Test
fun `RemoveAppConfirmed removes the app even though the dialog dismissed itself first`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
viewModel.onEvent(TotpAppListEvent.RemoveAppClicked(APP_ONE.id))
viewModel.onEvent(TotpAppListEvent.DialogDismissed)
viewModel.onEvent(TotpAppListEvent.RemoveAppConfirmed(APP_ONE.id))
coVerify { repository.removeTotpApp(APP_ONE.id) }
}
@Test
fun `DialogDismissed clears the dialog`() = runTest(testDispatcher) {
coEvery { repository.getTotpApps() } returns TotpRepository.AppsResult.Success(listOf(APP_ONE))
val viewModel = createViewModel()
viewModel.onEvent(TotpAppListEvent.RemoveAppClicked(APP_ONE.id))
viewModel.onEvent(TotpAppListEvent.DialogDismissed)
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.None)
}
@Test
fun `NavigateBackClicked leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(TotpAppListAction.NavigateBack)
}
@Test
fun `LearnMoreClicked opens the support article`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpAppListEvent.LearnMoreClicked)
assertThat(actions.last()).isEqualTo(TotpAppListAction.OpenLearnMore)
}
private fun createViewModel() = TotpAppListViewModel(repository)
private fun TestScope.collectActions(actions: Flow<TotpAppListAction>): List<TotpAppListAction> {
val collected = mutableListOf<TotpAppListAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -0,0 +1,154 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.totpcodeentry.TotpCodeEntryAction
import org.signal.appsettings.totpcodeentry.TotpCodeEntryEvent
import org.signal.appsettings.totpcodeentry.TotpCodeEntryState.Error
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
class TotpCodeEntryViewModelTest {
companion object {
private const val FULL_CODE = "123456"
private const val APP_ID = 3L
}
private val testDispatcher = UnconfinedTestDispatcher()
private val repository: TotpRepository = mockk(relaxed = true)
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
coEvery { repository.confirmPendingApp(any()) } returns TotpRepository.ConfirmResult.Success(APP_ID)
coEvery { repository.removeTotpApp(any()) } returns TotpRepository.UpdateResult.Success
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `non-digits are dropped and the code is capped at six digits`() = runTest(testDispatcher) {
val viewModel = createViewModel()
viewModel.onEvent(TotpCodeEntryEvent.CodeChanged("12a34 5678"))
assertThat(viewModel.state.value.code).isEqualTo(FULL_CODE)
}
@Test
fun `a partial code can't be submitted`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpCodeEntryEvent.CodeChanged("123"))
assertThat(viewModel.state.value.canSubmit).isFalse()
viewModel.onEvent(TotpCodeEntryEvent.DoneClicked)
assertThat(actions).isEmpty()
}
@Test
fun `a confirmed code sends the user on to name the app the service just created`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
submit(viewModel)
assertThat(actions.last()).isEqualTo(TotpCodeEntryAction.NavigateToNaming(APP_ID))
}
@Test
fun `a rejected code is reported and the user stays put to try again`() = runTest(testDispatcher) {
coEvery { repository.confirmPendingApp(any()) } returns TotpRepository.ConfirmResult.IncorrectCode
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
submit(viewModel)
assertThat(viewModel.state.value.error).isEqualTo(Error.IncorrectCode)
assertThat(viewModel.state.value.submitting).isFalse()
assertThat(actions).isEmpty()
}
@Test
fun `an account that filled up mid-setup goes back to setup, which explains the limit`() = runTest(testDispatcher) {
coEvery { repository.confirmPendingApp(any()) } returns TotpRepository.ConfirmResult.TooManyApps
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
submit(viewModel)
assertThat(viewModel.state.value.submitting).isFalse()
assertThat(actions.last()).isEqualTo(TotpCodeEntryAction.NavigateToSetup)
}
@Test
fun `typing again clears the last error`() = runTest(testDispatcher) {
coEvery { repository.confirmPendingApp(any()) } returns TotpRepository.ConfirmResult.IncorrectCode
val viewModel = createViewModel()
submit(viewModel)
viewModel.onEvent(TotpCodeEntryEvent.CodeChanged("1"))
assertThat(viewModel.state.value.error).isEqualTo(Error.None)
}
@Test
fun `NavigateBackClicked leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpCodeEntryEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(TotpCodeEntryAction.NavigateBack)
}
private fun submit(viewModel: TotpCodeEntryViewModel) {
viewModel.onEvent(TotpCodeEntryEvent.CodeChanged(FULL_CODE))
viewModel.onEvent(TotpCodeEntryEvent.DoneClicked)
}
private fun createViewModel() = TotpCodeEntryViewModel(repository = repository)
private fun TestScope.collectActions(actions: Flow<TotpCodeEntryAction>): List<TotpCodeEntryAction> {
val collected = mutableListOf<TotpCodeEntryAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -0,0 +1,191 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.totpapplist.TotpApp
import org.signal.appsettings.totpnameentry.TotpNameEntryAction
import org.signal.appsettings.totpnameentry.TotpNameEntryEvent
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
@OptIn(ExperimentalCoroutinesApi::class)
class TotpNameEntryViewModelTest {
companion object {
private val EXISTING_APP = TotpApp(id = 7, name = "Twilio Authy", createdAt = 0)
/** The id the service assigned when the code was confirmed, before the app had a name. */
private const val NEW_APP_ID = 1L
}
private val testDispatcher = UnconfinedTestDispatcher()
private val repository: TotpRepository = mockk(relaxed = true)
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
every { repository.getMaxApps() } returns 2
coEvery { repository.nameNewTotpApp(any(), any()) } returns TotpRepository.UpdateResult.Success
coEvery { repository.renameTotpApp(any(), any()) } returns TotpRepository.UpdateResult.Success
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `naming a new app starts empty and isn't renaming`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
assertThat(viewModel.state.value.name).isEqualTo("")
assertThat(viewModel.state.value.renaming).isFalse()
}
@Test
fun `renaming starts from the app's current name`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = EXISTING_APP.id, renamedApp = EXISTING_APP)
assertThat(viewModel.state.value.name).isEqualTo(EXISTING_APP.name)
assertThat(viewModel.state.value.renaming).isTrue()
}
@Test
fun `a blank name can't be submitted`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpNameEntryEvent.NameChanged(" "))
assertThat(viewModel.state.value.canSubmit).isFalse()
viewModel.onEvent(TotpNameEntryEvent.NextClicked)
assertThat(actions).isEmpty()
}
@Test
fun `NextClicked names the newly confirmed app and goes back to the list`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpNameEntryEvent.NameChanged(" Bitwarden Authenticator "))
viewModel.onEvent(TotpNameEntryEvent.NextClicked)
coVerify { repository.nameNewTotpApp(NEW_APP_ID, "Bitwarden Authenticator") }
assertThat(actions).contains(TotpNameEntryAction.ShowTotpAppSetUp)
assertThat(actions.last()).isEqualTo(TotpNameEntryAction.NavigateToTotpAppList)
}
@Test
fun `NextClicked renames an existing app and goes back to the list`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = EXISTING_APP.id, renamedApp = EXISTING_APP)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpNameEntryEvent.NameChanged("Work Authenticator"))
viewModel.onEvent(TotpNameEntryEvent.NextClicked)
coVerify { repository.renameTotpApp(EXISTING_APP, "Work Authenticator") }
assertThat(actions).contains(TotpNameEntryAction.ShowTotpAppRenamed)
assertThat(actions.last()).isEqualTo(TotpNameEntryAction.NavigateToTotpAppList)
}
@Test
fun `NavigateBackClicked leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpNameEntryEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(TotpNameEntryAction.NavigateBack)
}
@Test
fun `entry is capped at the grapheme limit rather than rejected`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
viewModel.onEvent(TotpNameEntryEvent.NameChanged("a".repeat(TotpRepository.MAX_NAME_LENGTH_GRAPHEMES + 20)))
assertThat(viewModel.state.value.name).isEqualTo("a".repeat(TotpRepository.MAX_NAME_LENGTH_GRAPHEMES))
assertThat(viewModel.state.value.canSubmit).isTrue()
}
/**
* The case the byte trim exists for: thirty emoji are inside the grapheme cap and well past the 98 bytes the service
* leaves room for, so the grapheme cap alone would let an unencryptable name through.
*/
@Test
fun `entry is also capped in bytes, which the grapheme limit does not guarantee`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
viewModel.onEvent(TotpNameEntryEvent.NameChanged("\uD83D\uDD10".repeat(TotpRepository.MAX_NAME_LENGTH_GRAPHEMES)))
val name = viewModel.state.value.name
assertThat(name.toByteArray(Charsets.UTF_8).size <= TotpRepository.MAX_NAME_LENGTH_BYTES).isTrue()
assertThat(name.isNotEmpty()).isTrue()
}
/** Trimming to a byte budget must not leave half a character behind. */
@Test
fun `capping in bytes does not split a character`() = runTest(testDispatcher) {
val viewModel = createViewModel(appId = NEW_APP_ID)
viewModel.onEvent(TotpNameEntryEvent.NameChanged("\uD83D\uDD10".repeat(TotpRepository.MAX_NAME_LENGTH_GRAPHEMES)))
val name = viewModel.state.value.name
assertThat(name.toByteArray(Charsets.UTF_8).toString(Charsets.UTF_8)).isEqualTo(name)
assertThat(name.length % 2).isEqualTo(0)
}
@Test
fun `a name that didn't save leaves the user on the screen to try again`() = runTest(testDispatcher) {
coEvery { repository.nameNewTotpApp(any(), any()) } returns TotpRepository.UpdateResult.NetworkFailure
val viewModel = createViewModel(appId = NEW_APP_ID)
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpNameEntryEvent.NameChanged("Aegis"))
viewModel.onEvent(TotpNameEntryEvent.NextClicked)
assertThat(actions.last()).isEqualTo(TotpNameEntryAction.ShowNameNotSaved)
assertThat(viewModel.state.value.submitting).isFalse()
}
private fun createViewModel(appId: Long, renamedApp: TotpApp? = null) = TotpNameEntryViewModel(appId = appId, renamedApp = renamedApp, repository = repository)
private fun TestScope.collectActions(actions: Flow<TotpNameEntryAction>): List<TotpNameEntryAction> {
val collected = mutableListOf<TotpNameEntryAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import android.app.Application
import android.os.Bundle
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNull
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.signal.appsettings.totpapplist.TotpApp
@RunWith(RobolectricTestRunner::class)
@Config(application = Application::class)
class TotpNavArgsTest {
companion object {
private val APP = TotpApp(id = 7, name = "Aegis", createdAt = 1_700_000_000_000L)
}
@Test
fun `no arguments means the screen is acting on a newly paired app`() {
assertThat(TotpNavArgs.appId(null)).isNull()
assertThat(TotpNavArgs.renamedApp(null)).isNull()
}
@Test
fun `an unset app id reads as null`() {
val arguments = Bundle().apply { putLong(TotpNavArgs.ARG_APP_ID, TotpNavArgs.NO_APP_ID) }
assertThat(TotpNavArgs.appId(arguments)).isNull()
}
@Test
fun `a newly paired app carries its id but no renamed app`() {
val arguments = Bundle().apply { putLong(TotpNavArgs.ARG_APP_ID, 7) }
assertThat(TotpNavArgs.appId(arguments)).isEqualTo(7L)
assertThat(TotpNavArgs.renamedApp(arguments)).isNull()
}
@Test
fun `a rename carries the whole app the list already had`() {
val arguments = Bundle().apply { TotpNavArgs.putRenamedApp(this, APP) }
assertThat(TotpNavArgs.appId(arguments)).isEqualTo(APP.id)
assertThat(TotpNavArgs.renamedApp(arguments)).isEqualTo(APP)
}
}
@@ -0,0 +1,178 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.hasSize
import assertk.assertions.isEmpty
import assertk.assertions.isEqualTo
import assertk.assertions.isInstanceOf
import assertk.assertions.startsWith
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.signal.appsettings.totpapplist.TotpApp
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpRepository.AppsResult
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpRepository.BeginSetupResult
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpRepository.ConfirmResult
import org.thoughtcrime.securesms.components.settings.app.account.authenticator.TotpRepository.UpdateResult
class TotpRepositoryTest {
companion object {
private const val NOW = 1_700_000_000_000L
private const val ACCOUNT_NAME = "8B4A1F0C"
private const val CODE = "123456"
}
private var now = NOW
private val api = InMemoryTotpApi()
private val repository = TotpRepository(api = api, clock = { now })
@Test
fun `beginSetup returns a link and a key in both the forms the screen needs`() = runTest {
val result = repository.beginSetup(ACCOUNT_NAME) as BeginSetupResult.Success
assertThat(result.setupUri).startsWith("otpauth://totp/Signal:$ACCOUNT_NAME?")
assertThat(result.setupUri).contains("secret=${result.clipboardKey}")
assertThat(result.displayKey).isEqualTo(result.clipboardKey.chunked(4).joinToString(" "))
}
/** The issuer and the account name have to differ, or an app that shows both renders "Signal: Signal". */
@Test
fun `beginSetup names the entry after the account, under the issuer`() = runTest {
val result = repository.beginSetup(ACCOUNT_NAME) as BeginSetupResult.Success
assertThat(result.setupUri).startsWith("otpauth://totp/Signal:$ACCOUNT_NAME?")
assertThat(result.setupUri).contains("issuer=Signal&")
}
/** Nothing should reach this without an ACI, but a bare issuer beats a label ending in a colon if anything does. */
@Test
fun `beginSetup falls back to the issuer alone when there's no account name`() = runTest {
val result = repository.beginSetup("") as BeginSetupResult.Success
assertThat(result.setupUri).startsWith("otpauth://totp/Signal?")
}
@Test
fun `beginSetup treats an account name of nothing but whitespace as no account name`() = runTest {
val result = repository.beginSetup(" ") as BeginSetupResult.Success
assertThat(result.setupUri).startsWith("otpauth://totp/Signal?")
}
/** A space has to become %20 rather than the + form encoding would produce, or apps render it literally. */
@Test
fun `beginSetup percent-encodes the account name`() = runTest {
val result = repository.beginSetup("+1 555") as BeginSetupResult.Success
assertThat(result.setupUri).startsWith("otpauth://totp/Signal:%2B1%20555?")
}
@Test
fun `setup asks for the parameters every authenticator app supports`() = runTest {
val result = repository.beginSetup(ACCOUNT_NAME) as BeginSetupResult.Success
assertThat(result.setupUri).contains("algorithm=SHA1")
assertThat(result.setupUri).contains("digits=6")
assertThat(result.setupUri).contains("period=30")
}
@Test
fun `an account at its limit is told rather than handed a key`() = runTest {
repeat(TotpApi.MAX_KEYS) { confirmNewApp() }
assertThat(repository.beginSetup(ACCOUNT_NAME)).isEqualTo(BeginSetupResult.TooManyApps)
}
@Test
fun `a confirmed app shows up in the list with the time it was confirmed`() = runTest {
val appId = confirmNewApp()
val apps = (repository.getTotpApps() as AppsResult.Success).apps
assertThat(apps).hasSize(1)
assertThat(apps.first().id).isEqualTo(appId)
assertThat(apps.first().createdAt).isEqualTo(NOW)
}
/** The service wants metadata at confirmation time, and the user hasn't been asked for a name yet. */
@Test
fun `a newly confirmed app starts out with no name`() = runTest {
confirmNewApp()
val apps = (repository.getTotpApps() as AppsResult.Success).apps
assertThat(apps.first().name).isEqualTo("")
}
@Test
fun `naming a new app names it`() = runTest {
val appId = confirmNewApp()
assertThat(repository.nameNewTotpApp(appId, "Aegis")).isEqualTo(UpdateResult.Success)
assertThat(listedApp(appId)?.name).isEqualTo("Aegis")
}
@Test
fun `renaming keeps the time the app was confirmed`() = runTest {
val appId = confirmNewApp()
repository.nameNewTotpApp(appId, "Aegis")
now += 60_000
assertThat(repository.renameTotpApp(listedApp(appId)!!, "Aegis on my tablet")).isEqualTo(UpdateResult.Success)
val app = listedApp(appId)
assertThat(app?.name).isEqualTo("Aegis on my tablet")
assertThat(app?.createdAt).isEqualTo(NOW)
}
@Test
fun `renaming an app that isn't there is reported rather than creating one`() = runTest {
val gone = TotpApp(id = 7, name = "Aegis", createdAt = NOW)
assertThat(repository.renameTotpApp(gone, "Aegis on my tablet")).isEqualTo(UpdateResult.AppNotFound)
}
@Test
fun `a removed app leaves the list`() = runTest {
val appId = confirmNewApp()
assertThat(repository.removeTotpApp(appId)).isEqualTo(UpdateResult.Success)
assertThat((repository.getTotpApps() as AppsResult.Success).apps).isEmpty()
}
/** The service can't tell a wrong code from a missing pending key, so neither can we. */
@Test
fun `confirming with nothing pending is just a wrong code`() = runTest {
assertThat(repository.confirmPendingApp(CODE)).isEqualTo(ConfirmResult.IncorrectCode)
}
@Test
fun `a code that isn't a number is reported as a wrong code`() = runTest {
repository.beginSetup(ACCOUNT_NAME)
assertThat(repository.confirmPendingApp("abcdef")).isEqualTo(ConfirmResult.IncorrectCode)
}
@Test
fun `a code confirms the app`() = runTest {
repository.beginSetup(ACCOUNT_NAME)
assertThat(repository.confirmPendingApp(CODE)).isInstanceOf(ConfirmResult.Success::class)
}
private suspend fun listedApp(appId: Long): TotpApp? {
return (repository.getTotpApps() as AppsResult.Success).apps.firstOrNull { it.id == appId }
}
private suspend fun confirmNewApp(): Long {
repository.beginSetup(ACCOUNT_NAME)
return (repository.confirmPendingApp(CODE) as ConfirmResult.Success).appId
}
}
@@ -0,0 +1,182 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.settings.app.account.authenticator
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.signal.appsettings.totpsetup.TotpSetupAction
import org.signal.appsettings.totpsetup.TotpSetupEvent
import org.signal.appsettings.totpsetup.TotpSetupState.Dialog
import org.thoughtcrime.securesms.testing.CoroutineDispatcherRule
import java.util.UUID
@OptIn(ExperimentalCoroutinesApi::class)
class TotpSetupViewModelTest {
companion object {
private const val ACCOUNT_NAME = "8B4A1F0C"
private const val SETUP_URI = "otpauth://totp/Signal:%2B15551234567?secret=MZXW6YTBOI"
private const val DISPLAY_KEY = "MZXW 6YTB OI"
private const val CLIPBOARD_KEY = "MZXW6YTBOI"
private val SETUP_SUCCESS = TotpRepository.BeginSetupResult.Success(
setupUri = SETUP_URI,
displayKey = DISPLAY_KEY,
clipboardKey = CLIPBOARD_KEY
)
}
private val testDispatcher = UnconfinedTestDispatcher()
private val repository: TotpRepository = mockk(relaxed = true)
@get:Rule
val dispatcherRule = CoroutineDispatcherRule(testDispatcher)
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
every { repository.getMaxApps() } returns 2
coEvery { repository.beginSetup(any()) } returns SETUP_SUCCESS
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `the screen asks for a key as soon as it opens and shows it grouped`() = runTest(testDispatcher) {
val viewModel = createViewModel()
assertThat(viewModel.state.value.setupKey).isEqualTo(DISPLAY_KEY)
assertThat(viewModel.state.value.loading).isFalse()
assertThat(viewModel.state.value.canContinue).isTrue()
}
@Test
fun `OpenTotpAppClicked hands off the setup link rather than the displayed key`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpSetupEvent.OpenTotpAppClicked)
assertThat(actions.last()).isEqualTo(TotpSetupAction.LaunchTotpApp(SETUP_URI))
}
@Test
fun `CopyKeyClicked copies the unbroken key rather than the grouped one`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpSetupEvent.CopyKeyClicked)
assertThat(actions.first()).isEqualTo(TotpSetupAction.CopyKeyToClipboard(CLIPBOARD_KEY))
assertThat(actions.last()).isEqualTo(TotpSetupAction.ShowKeyCopied)
}
@Test
fun `ContinueClicked moves on to code entry`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpSetupEvent.ContinueClicked)
assertThat(actions.last()).isEqualTo(TotpSetupAction.NavigateToCodeEntry)
}
@Test
fun `NoTotpAppFound reports the failure`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpSetupEvent.NoTotpAppFound)
assertThat(actions.last()).isEqualTo(TotpSetupAction.ShowNoTotpAppFound)
}
@Test
fun `backing out leaves the screen`() = runTest(testDispatcher) {
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpSetupEvent.NavigateBackClicked)
assertThat(actions.last()).isEqualTo(TotpSetupAction.NavigateBack)
}
@Test
fun `an account at its limit is told so rather than shown an empty key`() = runTest(testDispatcher) {
coEvery { repository.beginSetup(any()) } returns TotpRepository.BeginSetupResult.TooManyApps
val viewModel = createViewModel()
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.MaxAppsReached(2))
assertThat(viewModel.state.value.canContinue).isFalse()
}
@Test
fun `a network failure is reported rather than left spinning`() = runTest(testDispatcher) {
coEvery { repository.beginSetup(any()) } returns TotpRepository.BeginSetupResult.NetworkFailure
val viewModel = createViewModel()
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.NetworkFailure)
assertThat(viewModel.state.value.loading).isFalse()
}
@Test
fun `dismissing a failure dialog leaves the screen, since there's nothing to retry here`() = runTest(testDispatcher) {
coEvery { repository.beginSetup(any()) } returns TotpRepository.BeginSetupResult.NetworkFailure
val viewModel = createViewModel()
val actions = collectActions(viewModel.actions)
viewModel.onEvent(TotpSetupEvent.DialogDismissed)
assertThat(viewModel.state.value.dialog).isEqualTo(Dialog.None)
assertThat(actions.last()).isEqualTo(TotpSetupAction.NavigateBack)
}
@Test
fun `accountNameFor - takes the first hunk of the ACI, uppercased`() {
val aci = UUID.fromString("8b4a1f0c-2d3e-4a5b-9c7d-1e2f3a4b5c6d")
assertThat(TotpSetupViewModel.accountNameFor(aci)).isEqualTo("8B4A1F0C")
}
@Test
fun `accountNameFor - has nothing to say without an ACI, which leaves the issuer as the whole label`() {
assertThat(TotpSetupViewModel.accountNameFor(null)).isEqualTo("")
}
private fun createViewModel() = TotpSetupViewModel(repository = repository, accountName = ACCOUNT_NAME)
private fun TestScope.collectActions(actions: Flow<TotpSetupAction>): List<TotpSetupAction> {
val collected = mutableListOf<TotpSetupAction>()
backgroundScope.launch { actions.toList(collected) }
return collected
}
}
@@ -5,6 +5,7 @@
package org.signal.core.ui.compose
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -18,10 +19,28 @@ import org.signal.core.ui.logging.LoggingFragment
* Generic ComposeFragment which can be subclassed to build UI with compose.
*/
abstract class ComposeFragment : LoggingFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = content {
SignalTheme {
FragmentContent()
/**
* Whether the platform may offer to fill or save what the user types here.
*
* Compose registers its text fields with the autofill framework, so a password manager will offer to save the
* contents of any screen with a field on it. Override to false where that offer is wrong -- a one-time code or the
* name of a device is not a credential, and being asked to save it every time is noise the user can't turn off.
*/
open val autofillEnabled: Boolean = true
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = content {
SignalTheme {
FragmentContent()
}
}
if (!autofillEnabled && Build.VERSION.SDK_INT >= 26) {
view.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
}
return view
}
@Composable
@@ -0,0 +1,80 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.core.util
/**
* RFC 4648 base32. Padding is omitted on encode but tolerated on decode.
*/
object Base32 {
private const val ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
private const val PADDING = '='
private val DECODE_TABLE: IntArray = IntArray(128) { -1 }.apply {
ALPHABET.forEachIndexed { index, char ->
this[char.code] = index
this[char.lowercaseChar().code] = index
}
}
/** Encodes [data] as unpadded, uppercase base32. */
fun encode(data: ByteArray): String {
if (data.isEmpty()) {
return ""
}
val out = StringBuilder((data.size * 8 + 4) / 5)
var buffer = 0L
var bitsBuffered = 0
for (byte in data) {
buffer = (buffer shl 8) or (byte.toLong() and 0xFF)
bitsBuffered += 8
while (bitsBuffered >= 5) {
bitsBuffered -= 5
out.append(ALPHABET[((buffer shr bitsBuffered) and 0x1F).toInt()])
}
}
if (bitsBuffered > 0) {
out.append(ALPHABET[((buffer shl (5 - bitsBuffered)) and 0x1F).toInt()])
}
return out.toString()
}
/**
* Decodes base32 [input], ignoring padding and whitespace, or null if [input] contains anything else that isn't in
* the base32 alphabet.
*/
fun decodeOrNull(input: String): ByteArray? {
val out = ArrayList<Byte>(input.length * 5 / 8 + 1)
var buffer = 0L
var bitsBuffered = 0
for (char in input) {
if (char == PADDING || char.isWhitespace()) {
continue
}
val value = if (char.code < DECODE_TABLE.size) DECODE_TABLE[char.code] else -1
if (value < 0) {
return null
}
buffer = (buffer shl 5) or value.toLong()
bitsBuffered += 5
if (bitsBuffered >= 8) {
bitsBuffered -= 8
out += ((buffer shr bitsBuffered) and 0xFF).toByte()
}
}
return out.toByteArray()
}
}
@@ -0,0 +1,67 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.core.util
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNull
import org.junit.Test
class Base32Test {
/** The RFC 4648 section 10 vectors, minus the padding we don't emit. */
@Test
fun `encode - matches the RFC 4648 test vectors`() {
assertThat(Base32.encode("".toByteArray())).isEqualTo("")
assertThat(Base32.encode("f".toByteArray())).isEqualTo("MY")
assertThat(Base32.encode("fo".toByteArray())).isEqualTo("MZXQ")
assertThat(Base32.encode("foo".toByteArray())).isEqualTo("MZXW6")
assertThat(Base32.encode("foob".toByteArray())).isEqualTo("MZXW6YQ")
assertThat(Base32.encode("fooba".toByteArray())).isEqualTo("MZXW6YTB")
assertThat(Base32.encode("foobar".toByteArray())).isEqualTo("MZXW6YTBOI")
}
@Test
fun `decodeOrNull - matches the RFC 4648 test vectors`() {
assertThat(Base32.decodeOrNull("")?.decodeToString()).isEqualTo("")
assertThat(Base32.decodeOrNull("MY")?.decodeToString()).isEqualTo("f")
assertThat(Base32.decodeOrNull("MZXQ")?.decodeToString()).isEqualTo("fo")
assertThat(Base32.decodeOrNull("MZXW6")?.decodeToString()).isEqualTo("foo")
assertThat(Base32.decodeOrNull("MZXW6YQ")?.decodeToString()).isEqualTo("foob")
assertThat(Base32.decodeOrNull("MZXW6YTB")?.decodeToString()).isEqualTo("fooba")
assertThat(Base32.decodeOrNull("MZXW6YTBOI")?.decodeToString()).isEqualTo("foobar")
}
@Test
fun `decodeOrNull - tolerates the padding we don't emit`() {
assertThat(Base32.decodeOrNull("MZXW6YTBOI======")?.decodeToString()).isEqualTo("foobar")
}
@Test
fun `decodeOrNull - tolerates the spaces and lowercase a pasted key arrives with`() {
assertThat(Base32.decodeOrNull("mzxw 6ytb oi")?.decodeToString()).isEqualTo("foobar")
}
@Test
fun `decodeOrNull - rejects characters outside the alphabet`() {
assertThat(Base32.decodeOrNull("MZXW6YTB1")).isNull()
assertThat(Base32.decodeOrNull("MZXW6YTB0")).isNull()
assertThat(Base32.decodeOrNull("MZXW6YTB!")).isNull()
assertThat(Base32.decodeOrNull("MZXW6YTBé")).isNull()
}
@Test
fun `round trip - survives every byte value`() {
val data = ByteArray(256) { it.toByte() }
assertThat(Base32.decodeOrNull(Base32.encode(data))?.toList()).isEqualTo(data.toList())
}
@Test
fun `encode - produces a 52 character key for the 32 byte keys the service generates`() {
assertThat(Base32.encode(ByteArray(32)).length).isEqualTo(52)
}
}
@@ -140,13 +140,14 @@ class DebugNetworkController(
pniPreKeys: PreKeyCollection?,
fcmToken: String?,
skipDeviceTransfer: Boolean,
aci: ACI?
aci: ACI?,
totp: Int?
): RequestResult<RegisterAccountResponse, RegisterAccountError> {
NetworkDebugState.getOverride<RequestResult<RegisterAccountResponse, RegisterAccountError>>("registerAccount")?.let {
Log.d(TAG, "[registerAccount] Returning debug override")
return it
}
return delegate.registerAccount(e164, password, sessionId, recoveryPassword, receiptCredentialPresentation, attributes, aciPreKeys, pniPreKeys, fcmToken, skipDeviceTransfer, aci)
return delegate.registerAccount(e164, password, sessionId, recoveryPassword, receiptCredentialPresentation, attributes, aciPreKeys, pniPreKeys, fcmToken, skipDeviceTransfer, aci, totp)
}
override suspend fun createLoginPurchaseReceiptCredential(
@@ -214,7 +214,8 @@ class DemoNetworkController(
pniPreKeys: PreKeyCollection?,
fcmToken: String?,
skipDeviceTransfer: Boolean,
aci: ACI?
aci: ACI?,
totp: Int?
): RequestResult<RegisterAccountResponse, RegisterAccountError> {
return registrationApi.registerAccount(
e164 = e164,
@@ -227,7 +228,8 @@ class DemoNetworkController(
pniPreKeys = pniPreKeys,
fcmToken = fcmToken,
skipDeviceTransfer = skipDeviceTransfer,
aci = aci
aci = aci,
totp = totp
)
}
@@ -29,7 +29,7 @@ sealed interface AccountSettingsAction {
data object NavigateToSignalLoginDetails : AccountSettingsAction
/** Open the screen listing the account's authenticator apps. */
data object NavigateToAuthenticatorApps : AccountSettingsAction
data object NavigateToTotpAppList : AccountSettingsAction
/** Open the passkeys screen. */
data object NavigateToPasskeys : AccountSettingsAction
@@ -46,7 +46,7 @@ sealed interface AccountSettingsEvent {
data object RegistrationLockConfirmed : AccountSettingsEvent
/** The user tapped the authenticator app row in the two-factor authentication section. */
data object AuthenticatorAppClicked : AccountSettingsEvent
data object TotpAppClicked : AccountSettingsEvent
/** The user tapped the passkeys row in the two-factor authentication section. */
data object PasskeysClicked : AccountSettingsEvent
@@ -63,7 +63,7 @@ import org.signal.core.ui.R as CoreUiR
object AccountSettingsTestTags {
const val SCROLLER = "scroller"
const val CARD_SIGNAL_LOGIN = "card-signal-login"
const val ROW_AUTHENTICATOR_APP = "row-authenticator-app"
const val ROW_TOTP_APP = "row-totp-app"
const val ROW_PASSKEYS = "row-passkeys"
const val ROW_MODIFY_PIN = "row-modify-pin"
const val ROW_PIN_REMINDER = "row-pin-reminder"
@@ -126,16 +126,19 @@ fun AccountSettingsScreen(
}
item {
// A null count means we couldn't find out, which reads as the generic subtitle rather than as "none configured".
val totpAppCount = state.signalLogin.totpAppCount
Rows.TextRow(
icon = SignalIcons.DevicePhone.imageVector,
text = stringResource(R.string.AccountSettingsFragment__authenticator_app),
label = if (state.signalLogin.authenticatorAppCount > 0) {
pluralStringResource(R.plurals.AccountSettingsFragment__d_configured, state.signalLogin.authenticatorAppCount, state.signalLogin.authenticatorAppCount)
label = if (totpAppCount != null && totpAppCount > 0) {
pluralStringResource(R.plurals.AccountSettingsFragment__d_configured, totpAppCount, totpAppCount)
} else {
stringResource(R.string.AccountSettingsFragment__one_time_verification_codes)
},
onClick = { onEvent(AccountSettingsEvent.AuthenticatorAppClicked) },
modifier = Modifier.testTag(AccountSettingsTestTags.ROW_AUTHENTICATOR_APP)
onClick = { onEvent(AccountSettingsEvent.TotpAppClicked) },
modifier = Modifier.testTag(AccountSettingsTestTags.ROW_TOTP_APP)
)
}
@@ -565,7 +568,7 @@ private fun AccountSettingsScreenSignalLoginPreview() {
AccountSettingsScreen(
state = AccountSettingsState(
isPhoneNumberless = true,
signalLogin = AccountSettingsState.SignalLogin(authenticatorAppCount = 2, passkeyCount = 8)
signalLogin = AccountSettingsState.SignalLogin(totpAppCount = 2, passkeyCount = 8)
),
onEvent = {}
)
@@ -26,7 +26,8 @@ data class AccountSettingsState(
* the sections aren't shown at all.
*/
data class SignalLogin(
val authenticatorAppCount: Int,
/** How many authenticator apps are on the account, or null while we don't know -- see `getTotpAppCount`. */
val totpAppCount: Int?,
val passkeyCount: Int
)
@@ -1,30 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorapps
/**
* One-shot side effects that need the nav graph, and therefore have to be carried out by the fragment hosting
* [AuthenticatorAppsScreen] rather than the screen itself.
*
* Actions are logged, so be sure `toString()` contains nothing sensitive.
*/
sealed interface AuthenticatorAppsAction {
/** Leave the screen. */
data object NavigateBack : AuthenticatorAppsAction
/** Open the flow that pairs a new authenticator app. */
data object NavigateToSetup : AuthenticatorAppsAction
/** Open the screen that renames [appId]. */
data class NavigateToRename(val appId: Long) : AuthenticatorAppsAction
/** Collect a code from [appId] before it's removed. */
data class NavigateToRemovalCodeEntry(val appId: Long) : AuthenticatorAppsAction
/** Send the user to a support article about authenticator apps. */
data object OpenLearnMore : AuthenticatorAppsAction
}
@@ -1,36 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorapps
/**
* Reminder that these events are logged, so don't include anything sensitive in the toString.
*/
sealed interface AuthenticatorAppsEvent {
/** The screen came back to the foreground, so the list we read out of storage may be stale. */
data object ScreenResumed : AuthenticatorAppsEvent
/** The user tapped the navigation (back) icon. */
data object NavigateBackClicked : AuthenticatorAppsEvent
/** The user tapped the button that starts setting up another authenticator app. */
data object AddAuthenticatorAppClicked : AuthenticatorAppsEvent
/** The user tapped the learn more link. */
data object LearnMoreClicked : AuthenticatorAppsEvent
/** The user tapped the rename option in an app's overflow menu. */
data class RenameAppClicked(val appId: Long) : AuthenticatorAppsEvent
/** The user tapped the remove option in an app's overflow menu, which asks them to confirm first. */
data class RemoveAppClicked(val appId: Long) : AuthenticatorAppsEvent
/** The user confirmed removing the app named in [AuthenticatorAppsState.Dialog.ConfirmRemove]. */
data object RemoveAppConfirmed : AuthenticatorAppsEvent
/** Dismisses whatever is in [AuthenticatorAppsState.dialog]. */
data object DialogDismissed : AuthenticatorAppsEvent
}
@@ -1,27 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorcodeentry
/**
* One-shot side effects that need the nav graph, and therefore have to be carried out by the fragment hosting
* [AuthenticatorCodeEntryScreen] rather than the screen itself.
*
* Actions are logged, so be sure `toString()` contains nothing sensitive.
*/
sealed interface AuthenticatorCodeEntryAction {
/** Leave the screen. */
data object NavigateBack : AuthenticatorCodeEntryAction
/** The new authenticator app is confirmed, so go name it. */
data object NavigateToNaming : AuthenticatorCodeEntryAction
/** The removal is done, so go back to the list of authenticator apps. */
data object NavigateToAuthenticatorApps : AuthenticatorCodeEntryAction
/** Tell the user their authenticator app was removed. */
data object ShowAuthenticatorAppRemoved : AuthenticatorCodeEntryAction
}
@@ -1,31 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorcodeentry
data class AuthenticatorCodeEntryState(
val code: String = "",
val submitting: Boolean = false,
/** What the code is being collected for, which decides where the user goes once it's accepted. */
val purpose: Purpose = Purpose.Add
) {
val canSubmit: Boolean
get() = code.length == CODE_LENGTH && !submitting
override fun toString(): String = "AuthenticatorCodeEntryState(codeLength=${code.length}, submitting=$submitting, purpose=$purpose)"
sealed interface Purpose {
/** Confirming a newly paired authenticator app, which is then named. */
data object Add : Purpose
/** Confirming removal of the already-configured app identified by [appId]. */
data class Remove(val appId: Long) : Purpose
}
companion object {
const val CODE_LENGTH = 6
}
}
@@ -1,19 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorname
data class AuthenticatorNameState(
val name: String = "",
/** True when an already-configured app is being renamed, false when one is being named for the first time. */
val renaming: Boolean = false,
val submitting: Boolean = false
) {
val canSubmit: Boolean
get() = name.isNotBlank() && !submitting
override fun toString(): String = "AuthenticatorNameState(nameLength=${name.length}, renaming=$renaming, submitting=$submitting)"
}
@@ -1,13 +0,0 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorsetup
data class AuthenticatorSetupState(
/** The key the user hands to their authenticator app, either through the app link or by copying it. */
val setupKey: String = ""
) {
override fun toString(): String = "AuthenticatorSetupState(setupKey=${if (setupKey.isEmpty()) "empty" else "present"})"
}
@@ -3,16 +3,16 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorapps
package org.signal.appsettings.totpapplist
/**
* A single authenticator app configured on the user's account, as shown on [AuthenticatorAppsScreen].
* A single authenticator app configured on the user's account, as shown on [TotpAppListScreen].
*/
data class AuthenticatorApp(
data class TotpApp(
val id: Long,
val name: String,
/** When the app was configured, in epoch milliseconds. */
val createdAt: Long
) {
override fun toString(): String = "AuthenticatorApp(id=$id)"
override fun toString(): String = "TotpApp(id=$id)"
}
@@ -0,0 +1,33 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.totpapplist
/**
* One-shot side effects that need the nav graph, and therefore have to be carried out by the fragment hosting
* [TotpAppListScreen] rather than the screen itself.
*
* Actions are logged, so be sure `toString()` contains nothing sensitive.
*/
sealed interface TotpAppListAction {
/** Leave the screen. */
data object NavigateBack : TotpAppListAction
/** Open the flow that pairs a new authenticator app. */
data object NavigateToSetup : TotpAppListAction
/** Open the screen that renames [app]. */
data class NavigateToRename(val app: TotpApp) : TotpAppListAction
/** Tell the user their authenticator app was removed. */
data object ShowTotpAppRemoved : TotpAppListAction
/** Tell the user the removal didn't go through, so they know the app is still on the account. */
data object ShowRemovalFailed : TotpAppListAction
/** Send the user to a support article about authenticator apps. */
data object OpenLearnMore : TotpAppListAction
}
@@ -0,0 +1,36 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.totpapplist
/**
* Reminder that these events are logged, so don't include anything sensitive in the toString.
*/
sealed interface TotpAppListEvent {
/** The screen came back to the foreground, so the list we read out of storage may be stale. */
data object ScreenResumed : TotpAppListEvent
/** The user tapped the navigation (back) icon. */
data object NavigateBackClicked : TotpAppListEvent
/** The user tapped the button that starts setting up another authenticator app. */
data object AddTotpAppClicked : TotpAppListEvent
/** The user tapped the learn more link. */
data object LearnMoreClicked : TotpAppListEvent
/** The user tapped the rename option in an app's overflow menu. */
data class RenameAppClicked(val appId: Long) : TotpAppListEvent
/** The user tapped the remove option in an app's overflow menu, which asks them to confirm first. */
data class RemoveAppClicked(val appId: Long) : TotpAppListEvent
/** The user confirmed removing the app, which removes it. */
data class RemoveAppConfirmed(val appId: Long) : TotpAppListEvent
/** Dismisses whatever is in [TotpAppListState.dialog]. */
data object DialogDismissed : TotpAppListEvent
}
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorapps
package org.signal.appsettings.totpapplist
import android.text.format.DateUtils
import androidx.annotation.VisibleForTesting
@@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -35,7 +36,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withLink
import androidx.compose.ui.unit.dp
import org.signal.appsettings.R
import org.signal.appsettings.authenticatorapps.AuthenticatorAppsState.Dialog
import org.signal.appsettings.totpapplist.TotpAppListState.Dialog
import org.signal.appsettings.totpapplist.TotpAppListState.LoadState
import org.signal.core.ui.compose.Buttons
import org.signal.core.ui.compose.DayNightPreviews
import org.signal.core.ui.compose.Dialogs
@@ -50,7 +52,7 @@ import org.signal.core.ui.compose.Texts
import org.signal.core.ui.R as CoreUiR
@VisibleForTesting
object AuthenticatorAppsTestTags {
object TotpAppListTestTags {
const val SCROLLER = "scroller"
const val LEARN_MORE = "learn-more"
const val BUTTON_ADD = "button-add"
@@ -59,28 +61,30 @@ object AuthenticatorAppsTestTags {
const val MENU_ITEM_RENAME = "menu-item-rename"
const val MENU_ITEM_REMOVE = "menu-item-remove"
const val EMPTY_MESSAGE = "empty-message"
const val LOAD_FAILED_MESSAGE = "load-failed-message"
const val DIALOG_CONFIRM_REMOVE = "dialog-confirm-remove"
const val DIALOG_MAX_APPS_REACHED = "dialog-max-apps-reached"
const val LOADING = "loading"
}
/**
* Lists the authenticator apps configured on the account and lets the user add, rename, or remove one.
*/
@Composable
fun AuthenticatorAppsScreen(
state: AuthenticatorAppsState,
onEvent: (AuthenticatorAppsEvent) -> Unit
fun TotpAppListScreen(
state: TotpAppListState,
onEvent: (TotpAppListEvent) -> Unit
) {
Scaffolds.Settings(
title = stringResource(R.string.AuthenticatorAppsScreen__authenticator_app),
onNavigationClick = { onEvent(AuthenticatorAppsEvent.NavigateBackClicked) },
title = stringResource(R.string.TotpAppListScreen__authenticator_app),
onNavigationClick = { onEvent(TotpAppListEvent.NavigateBackClicked) },
navigationIcon = SignalIcons.ArrowStart.imageVector
) { contentPadding ->
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(contentPadding)
.testTag(AuthenticatorAppsTestTags.SCROLLER)
.testTag(TotpAppListTestTags.SCROLLER)
) {
item {
Image(
@@ -98,13 +102,13 @@ fun AuthenticatorAppsScreen(
modifier = Modifier
.padding(top = 24.dp)
.padding(horizontal = 34.dp)
.testTag(AuthenticatorAppsTestTags.LEARN_MORE)
.testTag(TotpAppListTestTags.LEARN_MORE)
)
}
item {
Buttons.MediumTonal(
onClick = { onEvent(AuthenticatorAppsEvent.AddAuthenticatorAppClicked) },
onClick = { onEvent(TotpAppListEvent.AddTotpAppClicked) },
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
@@ -113,9 +117,9 @@ fun AuthenticatorAppsScreen(
.fillMaxWidth()
.padding(top = 24.dp, bottom = 20.dp)
.padding(horizontal = 40.dp)
.testTag(AuthenticatorAppsTestTags.BUTTON_ADD)
.testTag(TotpAppListTestTags.BUTTON_ADD)
) {
Text(text = stringResource(R.string.AuthenticatorAppsScreen__add_authenticator_app))
Text(text = stringResource(R.string.TotpAppListScreen__add_authenticator_app))
}
}
@@ -125,44 +129,75 @@ fun AuthenticatorAppsScreen(
item {
Texts.SectionHeader(
text = stringResource(R.string.AuthenticatorAppsScreen__authenticator_apps),
text = stringResource(R.string.TotpAppListScreen__authenticator_apps),
modifier = Modifier.fillMaxWidth()
)
}
if (state.apps.isEmpty()) {
item {
Text(
text = stringResource(R.string.AuthenticatorAppsScreen__no_authenticator_apps),
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
when (state.loadState) {
LoadState.LOADING -> item {
CircularProgressIndicator(
modifier = Modifier
.padding(top = 40.dp)
.testTag(AuthenticatorAppsTestTags.EMPTY_MESSAGE)
.size(24.dp)
.testTag(TotpAppListTestTags.LOADING)
)
}
} else {
items(state.apps, key = { it.id }) { app ->
AuthenticatorAppRow(
app = app,
onEvent = onEvent
LoadState.NETWORK_FAILURE -> item {
SectionMessage(
text = stringResource(R.string.TotpAppListScreen__couldnt_load_authenticator_apps),
modifier = Modifier.testTag(TotpAppListTestTags.LOAD_FAILED_MESSAGE)
)
}
LoadState.LOADED -> if (state.apps.isEmpty()) {
item {
SectionMessage(
text = stringResource(R.string.TotpAppListScreen__no_authenticator_apps),
modifier = Modifier.testTag(TotpAppListTestTags.EMPTY_MESSAGE)
)
}
} else {
items(state.apps, key = { it.id }) { app ->
TotpAppRow(
app = app,
onEvent = onEvent
)
}
}
}
}
}
when (val dialog = state.dialog) {
Dialog.None -> Unit
is Dialog.ConfirmRemove -> ConfirmRemoveDialog(onEvent)
is Dialog.ConfirmRemove -> ConfirmRemoveDialog(appId = dialog.appId, onEvent = onEvent)
Dialog.MaxAppsReached -> MaxAppsReachedDialog(maxApps = state.maxApps, onEvent = onEvent)
}
}
/** Whatever the list section has to say when it has no rows to show. */
@Composable
private fun AuthenticatorAppRow(
app: AuthenticatorApp,
onEvent: (AuthenticatorAppsEvent) -> Unit
private fun SectionMessage(
text: String,
modifier: Modifier = Modifier
) {
Text(
text = text,
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
modifier = modifier
.padding(top = 40.dp)
.padding(horizontal = 34.dp)
)
}
@Composable
private fun TotpAppRow(
app: TotpApp,
onEvent: (TotpAppListEvent) -> Unit
) {
val context = LocalContext.current
val addedTime = remember(app.createdAt) {
@@ -180,33 +215,33 @@ private fun AuthenticatorAppRow(
text = {
TextAndLabel(
text = app.name,
label = stringResource(R.string.AuthenticatorAppsScreen__added_s, addedTime)
label = stringResource(R.string.TotpAppListScreen__added_s, addedTime)
)
AuthenticatorAppMenuButton(
TotpAppMenuButton(
app = app,
onEvent = onEvent
)
},
modifier = Modifier.testTag(AuthenticatorAppsTestTags.ROW_APP)
modifier = Modifier.testTag(TotpAppListTestTags.ROW_APP)
)
}
@Composable
private fun AuthenticatorAppMenuButton(
app: AuthenticatorApp,
onEvent: (AuthenticatorAppsEvent) -> Unit
private fun TotpAppMenuButton(
app: TotpApp,
onEvent: (TotpAppListEvent) -> Unit
) {
val menuController = remember { DropdownMenus.MenuController() }
Box {
IconButton(
onClick = menuController::show,
modifier = Modifier.testTag(AuthenticatorAppsTestTags.BUTTON_APP_MENU)
modifier = Modifier.testTag(TotpAppListTestTags.BUTTON_APP_MENU)
) {
Icon(
imageVector = SignalIcons.MoreVertical.imageVector,
contentDescription = stringResource(R.string.AuthenticatorAppsScreen__open_authenticator_app_options),
contentDescription = stringResource(R.string.TotpAppListScreen__open_authenticator_app_options),
tint = MaterialTheme.colorScheme.onSurface
)
}
@@ -214,22 +249,22 @@ private fun AuthenticatorAppMenuButton(
DropdownMenus.Menu(controller = menuController) { controller ->
DropdownMenus.Item(
leadingIconResId = CoreUiR.drawable.symbol_edit_24,
text = { Text(text = stringResource(R.string.AuthenticatorAppsScreen__rename)) },
text = { Text(text = stringResource(R.string.TotpAppListScreen__rename)) },
onClick = {
onEvent(AuthenticatorAppsEvent.RenameAppClicked(app.id))
onEvent(TotpAppListEvent.RenameAppClicked(app.id))
controller.hide()
},
modifier = Modifier.testTag(AuthenticatorAppsTestTags.MENU_ITEM_RENAME)
modifier = Modifier.testTag(TotpAppListTestTags.MENU_ITEM_RENAME)
)
DropdownMenus.Item(
leadingIconResId = CoreUiR.drawable.symbol_x_circle_24,
text = { Text(text = stringResource(R.string.AuthenticatorAppsScreen__remove)) },
text = { Text(text = stringResource(R.string.TotpAppListScreen__remove)) },
onClick = {
onEvent(AuthenticatorAppsEvent.RemoveAppClicked(app.id))
onEvent(TotpAppListEvent.RemoveAppClicked(app.id))
controller.hide()
},
modifier = Modifier.testTag(AuthenticatorAppsTestTags.MENU_ITEM_REMOVE)
modifier = Modifier.testTag(TotpAppListTestTags.MENU_ITEM_REMOVE)
)
}
}
@@ -237,22 +272,22 @@ private fun AuthenticatorAppMenuButton(
@Composable
private fun DescriptionWithLearnMore(
onEvent: (AuthenticatorAppsEvent) -> Unit,
onEvent: (TotpAppListEvent) -> Unit,
modifier: Modifier = Modifier
) {
Text(
text = buildAnnotatedString {
append(stringResource(R.string.AuthenticatorAppsScreen__set_up_an_authenticator_app))
append(stringResource(R.string.TotpAppListScreen__set_up_an_authenticator_app))
append(' ')
withLink(
LinkAnnotation.Clickable(
tag = "learn-more",
styles = TextLinkStyles(style = SpanStyle(color = MaterialTheme.colorScheme.primary)),
linkInteractionListener = { onEvent(AuthenticatorAppsEvent.LearnMoreClicked) }
linkInteractionListener = { onEvent(TotpAppListEvent.LearnMoreClicked) }
)
) {
append(stringResource(R.string.AuthenticatorAppsScreen__learn_more))
append(stringResource(R.string.TotpAppListScreen__learn_more))
}
},
style = MaterialTheme.typography.bodyLarge,
@@ -264,44 +299,45 @@ private fun DescriptionWithLearnMore(
@Composable
private fun ConfirmRemoveDialog(
onEvent: (AuthenticatorAppsEvent) -> Unit
appId: Long,
onEvent: (TotpAppListEvent) -> Unit
) {
Dialogs.SimpleAlertDialog(
title = stringResource(R.string.AuthenticatorAppsScreen__remove_authenticator_app),
body = stringResource(R.string.AuthenticatorAppsScreen__to_remove_this_authentication_method),
confirm = stringResource(R.string.AuthenticatorAppsScreen__remove),
onConfirm = { onEvent(AuthenticatorAppsEvent.RemoveAppConfirmed) },
onDismiss = { onEvent(AuthenticatorAppsEvent.DialogDismissed) },
title = stringResource(R.string.TotpAppListScreen__remove_authenticator_app),
body = stringResource(R.string.TotpAppListScreen__you_wont_be_able_to_use_this_app),
confirm = stringResource(R.string.TotpAppListScreen__remove),
onConfirm = { onEvent(TotpAppListEvent.RemoveAppConfirmed(appId)) },
onDismiss = { onEvent(TotpAppListEvent.DialogDismissed) },
dismiss = stringResource(android.R.string.cancel),
onDismissRequest = { onEvent(AuthenticatorAppsEvent.DialogDismissed) },
modifier = Modifier.testTag(AuthenticatorAppsTestTags.DIALOG_CONFIRM_REMOVE)
onDismissRequest = { onEvent(TotpAppListEvent.DialogDismissed) },
modifier = Modifier.testTag(TotpAppListTestTags.DIALOG_CONFIRM_REMOVE)
)
}
@Composable
private fun MaxAppsReachedDialog(
maxApps: Int,
onEvent: (AuthenticatorAppsEvent) -> Unit
onEvent: (TotpAppListEvent) -> Unit
) {
Dialogs.SimpleAlertDialog(
title = stringResource(R.string.AuthenticatorAppsScreen__cant_add_authenticator_app),
body = stringResource(R.string.AuthenticatorAppsScreen__you_cant_add_more_than_d, maxApps),
title = stringResource(R.string.TotpAppListScreen__cant_add_authenticator_app),
body = stringResource(R.string.TotpAppListScreen__you_cant_add_more_than_d, maxApps),
confirm = stringResource(android.R.string.ok),
onConfirm = {},
onDismiss = { onEvent(AuthenticatorAppsEvent.DialogDismissed) },
dismiss = stringResource(R.string.AuthenticatorAppsScreen__learn_more),
onDeny = { onEvent(AuthenticatorAppsEvent.LearnMoreClicked) },
onDismissRequest = { onEvent(AuthenticatorAppsEvent.DialogDismissed) },
modifier = Modifier.testTag(AuthenticatorAppsTestTags.DIALOG_MAX_APPS_REACHED)
onDismiss = { onEvent(TotpAppListEvent.DialogDismissed) },
dismiss = stringResource(R.string.TotpAppListScreen__learn_more),
onDeny = { onEvent(TotpAppListEvent.LearnMoreClicked) },
onDismissRequest = { onEvent(TotpAppListEvent.DialogDismissed) },
modifier = Modifier.testTag(TotpAppListTestTags.DIALOG_MAX_APPS_REACHED)
)
}
@DayNightPreviews
@Composable
private fun AuthenticatorAppsScreenPreview() {
private fun TotpAppListScreenPreview() {
Previews.Preview {
AuthenticatorAppsScreen(
state = AuthenticatorAppsState(),
TotpAppListScreen(
state = TotpAppListState(),
onEvent = {}
)
}
@@ -309,10 +345,32 @@ private fun AuthenticatorAppsScreenPreview() {
@DayNightPreviews
@Composable
private fun AuthenticatorAppsScreenWithAppsPreview() {
private fun TotpAppListScreenEmptyPreview() {
Previews.Preview {
AuthenticatorAppsScreen(
state = AuthenticatorAppsState(apps = PREVIEW_APPS),
TotpAppListScreen(
state = TotpAppListState(loadState = LoadState.LOADED),
onEvent = {}
)
}
}
@DayNightPreviews
@Composable
private fun TotpAppListScreenLoadFailedPreview() {
Previews.Preview {
TotpAppListScreen(
state = TotpAppListState(loadState = LoadState.NETWORK_FAILURE),
onEvent = {}
)
}
}
@DayNightPreviews
@Composable
private fun TotpAppListPreview() {
Previews.Preview {
TotpAppListScreen(
state = TotpAppListState(apps = PREVIEW_APPS, loadState = LoadState.LOADED),
onEvent = {}
)
}
@@ -322,7 +380,7 @@ private fun AuthenticatorAppsScreenWithAppsPreview() {
@Composable
private fun ConfirmRemoveDialogPreview() {
Previews.Preview {
ConfirmRemoveDialog(onEvent = {})
ConfirmRemoveDialog(appId = 1, onEvent = {})
}
}
@@ -335,6 +393,6 @@ private fun MaxAppsReachedDialogPreview() {
}
private val PREVIEW_APPS = listOf(
AuthenticatorApp(id = 1, name = "Bitwarden Authenticator", createdAt = System.currentTimeMillis()),
AuthenticatorApp(id = 2, name = "Twilio Authy", createdAt = System.currentTimeMillis())
TotpApp(id = 1, name = "Bitwarden Authenticator", createdAt = System.currentTimeMillis()),
TotpApp(id = 2, name = "Twilio Authy", createdAt = System.currentTimeMillis())
)
@@ -3,19 +3,32 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorapps
package org.signal.appsettings.totpapplist
data class AuthenticatorAppsState(
/** The authenticator apps configured on the account. When empty, the list section says so instead of listing rows. */
val apps: List<AuthenticatorApp> = emptyList(),
data class TotpAppListState(
/** The authenticator apps configured on the account, which only means anything once [loadState] is [LoadState.LOADED]. */
val apps: List<TotpApp> = emptyList(),
/** How many authenticator apps the account is allowed to have at once. */
val maxApps: Int = 0,
/** How the last look at the account went, which decides what the list section shows in place of rows. */
val loadState: LoadState = LoadState.LOADING,
val dialog: Dialog = Dialog.None
) {
val atMaxApps: Boolean
get() = apps.size >= maxApps
/** How the last attempt to read the account's authenticator apps went, since an empty list can't say on its own. */
enum class LoadState {
/** We haven't heard back about the account yet. */
LOADING,
LOADED,
/** We couldn't reach the service, which is worth another try. */
NETWORK_FAILURE
}
/** Whichever dialog the screen is showing, if any. Only one is ever up at a time. */
sealed interface Dialog {
data object None : Dialog
@@ -0,0 +1,24 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.totpcodeentry
/**
* One-shot side effects that need the nav graph, and therefore have to be carried out by the fragment hosting
* [TotpCodeEntryScreen] rather than the screen itself.
*
* Actions are logged, so be sure `toString()` contains nothing sensitive.
*/
sealed interface TotpCodeEntryAction {
/** Leave the screen. */
data object NavigateBack : TotpCodeEntryAction
/** The new authenticator app is confirmed and the service gave it [appId], so go name it. */
data class NavigateToNaming(val appId: Long) : TotpCodeEntryAction
/** Go back to setup, because the key the user was confirming is gone and there's nothing to retry against. */
data object NavigateToSetup : TotpCodeEntryAction
}
@@ -3,21 +3,21 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorcodeentry
package org.signal.appsettings.totpcodeentry
/**
* Reminder that these events are logged, so don't include anything sensitive in the toString.
*/
sealed interface AuthenticatorCodeEntryEvent {
sealed interface TotpCodeEntryEvent {
/** The user tapped the navigation (back) icon. */
data object NavigateBackClicked : AuthenticatorCodeEntryEvent
data object NavigateBackClicked : TotpCodeEntryEvent
/** The user typed in the code field. */
data class CodeChanged(val code: String) : AuthenticatorCodeEntryEvent {
data class CodeChanged(val code: String) : TotpCodeEntryEvent {
override fun toString(): String = "CodeChanged(length=${code.length})"
}
/** The user submitted the code they entered. */
data object DoneClicked : AuthenticatorCodeEntryEvent
data object DoneClicked : TotpCodeEntryEvent
}
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorcodeentry
package org.signal.appsettings.totpcodeentry
import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.Column
@@ -38,18 +38,19 @@ import org.signal.core.ui.compose.Scaffolds
import org.signal.core.ui.compose.SignalIcons
@VisibleForTesting
object AuthenticatorCodeEntryTestTags {
object TotpCodeEntryTestTags {
const val CODE_INPUT = "code-input"
const val BUTTON_DONE = "button-done"
const val ERROR = "error"
}
/**
* Collects the one-time code the user's authenticator app generated, which is the last step of setting one up.
*/
@Composable
fun AuthenticatorCodeEntryScreen(
state: AuthenticatorCodeEntryState,
onEvent: (AuthenticatorCodeEntryEvent) -> Unit
fun TotpCodeEntryScreen(
state: TotpCodeEntryState,
onEvent: (TotpCodeEntryEvent) -> Unit
) {
val focusRequester = remember { FocusRequester() }
@@ -58,8 +59,8 @@ fun AuthenticatorCodeEntryScreen(
}
Scaffolds.Settings(
title = stringResource(R.string.AuthenticatorCodeEntryScreen__enter_your_code),
onNavigationClick = { onEvent(AuthenticatorCodeEntryEvent.NavigateBackClicked) },
title = stringResource(R.string.TotpCodeEntryScreen__enter_your_code),
onNavigationClick = { onEvent(TotpCodeEntryEvent.NavigateBackClicked) },
navigationIcon = SignalIcons.ArrowStart.imageVector
) { contentPadding ->
Column(
@@ -70,7 +71,7 @@ fun AuthenticatorCodeEntryScreen(
horizontalAlignment = Alignment.End
) {
Text(
text = stringResource(R.string.AuthenticatorCodeEntryScreen__enter_the_6_digit_code),
text = stringResource(R.string.TotpCodeEntryScreen__enter_the_6_digit_code),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier
@@ -78,25 +79,31 @@ fun AuthenticatorCodeEntryScreen(
.padding(horizontal = 24.dp, vertical = 16.dp)
)
val errorMessage = state.error.message()
TextField(
value = state.code,
onValueChange = { onEvent(AuthenticatorCodeEntryEvent.CodeChanged(it)) },
label = { Text(text = stringResource(R.string.AuthenticatorCodeEntryScreen__code)) },
onValueChange = { onEvent(TotpCodeEntryEvent.CodeChanged(it)) },
label = { Text(text = stringResource(R.string.TotpCodeEntryScreen__code)) },
singleLine = true,
enabled = !state.submitting,
isError = errorMessage != null,
supportingText = errorMessage?.let { message ->
{ Text(text = message, modifier = Modifier.testTag(TotpCodeEntryTestTags.ERROR)) }
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.NumberPassword, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { if (state.canSubmit) onEvent(AuthenticatorCodeEntryEvent.DoneClicked) }),
keyboardActions = KeyboardActions(onDone = { if (state.canSubmit) onEvent(TotpCodeEntryEvent.DoneClicked) }),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
.focusRequester(focusRequester)
.testTag(AuthenticatorCodeEntryTestTags.CODE_INPUT)
.testTag(TotpCodeEntryTestTags.CODE_INPUT)
)
Spacer(modifier = Modifier.weight(1f))
Buttons.LargeTonal(
onClick = { onEvent(AuthenticatorCodeEntryEvent.DoneClicked) },
onClick = { onEvent(TotpCodeEntryEvent.DoneClicked) },
enabled = state.canSubmit,
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
@@ -104,20 +111,41 @@ fun AuthenticatorCodeEntryScreen(
),
modifier = Modifier
.padding(horizontal = 24.dp, vertical = 24.dp)
.testTag(AuthenticatorCodeEntryTestTags.BUTTON_DONE)
.testTag(TotpCodeEntryTestTags.BUTTON_DONE)
) {
Text(text = stringResource(R.string.AuthenticatorCodeEntryScreen__done))
Text(text = stringResource(R.string.TotpCodeEntryScreen__done))
}
}
}
}
/**
* The message shown under the code field, or null when there's nothing wrong.
*/
@Composable
private fun TotpCodeEntryState.Error.message(): String? = when (this) {
TotpCodeEntryState.Error.None -> null
TotpCodeEntryState.Error.IncorrectCode -> stringResource(R.string.TotpCodeEntryScreen__incorrect_code)
TotpCodeEntryState.Error.NetworkFailure -> stringResource(R.string.TotpCodeEntryScreen__couldnt_reach_signal)
}
@DayNightPreviews
@Composable
private fun AuthenticatorCodeEntryScreenPreview() {
private fun TotpCodeEntryScreenPreview() {
Previews.Preview {
AuthenticatorCodeEntryScreen(
state = AuthenticatorCodeEntryState(code = "123456"),
TotpCodeEntryScreen(
state = TotpCodeEntryState(code = "123456"),
onEvent = {}
)
}
}
@DayNightPreviews
@Composable
private fun TotpCodeEntryScreenErrorPreview() {
Previews.Preview {
TotpCodeEntryScreen(
state = TotpCodeEntryState(code = "123456", error = TotpCodeEntryState.Error.IncorrectCode),
onEvent = {}
)
}
@@ -0,0 +1,32 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.totpcodeentry
data class TotpCodeEntryState(
val code: String = "",
val submitting: Boolean = false,
/** Why the last submission didn't work, shown under the code field and cleared as soon as the user types. */
val error: Error = Error.None
) {
val canSubmit: Boolean
get() = code.length == CODE_LENGTH && !submitting
override fun toString(): String = "TotpCodeEntryState(codeLength=${code.length}, submitting=$submitting, error=$error)"
sealed interface Error {
data object None : Error
/** The service rejected the code, and we have no reason to think it was anything but a wrong code. */
data object IncorrectCode : Error
data object NetworkFailure : Error
}
companion object {
const val CODE_LENGTH = 6
}
}
@@ -3,25 +3,28 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorname
package org.signal.appsettings.totpnameentry
/**
* One-shot side effects that need the nav graph, and therefore have to be carried out by the fragment hosting
* [AuthenticatorNameScreen] rather than the screen itself.
* [TotpNameEntryScreen] rather than the screen itself.
*
* Actions are logged, so be sure `toString()` contains nothing sensitive.
*/
sealed interface AuthenticatorNameAction {
sealed interface TotpNameEntryAction {
/** Leave the screen. */
data object NavigateBack : AuthenticatorNameAction
data object NavigateBack : TotpNameEntryAction
/** The app has a name now, so go back to the list of authenticator apps. */
data object NavigateToAuthenticatorApps : AuthenticatorNameAction
data object NavigateToTotpAppList : TotpNameEntryAction
/** Tell the user their authenticator app was set up. */
data object ShowAuthenticatorAppSetUp : AuthenticatorNameAction
data object ShowTotpAppSetUp : TotpNameEntryAction
/** Tell the user their authenticator app was renamed. */
data object ShowAuthenticatorAppRenamed : AuthenticatorNameAction
data object ShowTotpAppRenamed : TotpNameEntryAction
/** Tell the user the name didn't stick, so they know to try again. */
data object ShowNameNotSaved : TotpNameEntryAction
}
@@ -3,21 +3,21 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorname
package org.signal.appsettings.totpnameentry
/**
* Reminder that these events are logged, so don't include anything sensitive in the toString.
*/
sealed interface AuthenticatorNameEvent {
sealed interface TotpNameEntryEvent {
/** The user tapped the navigation (back) icon. */
data object NavigateBackClicked : AuthenticatorNameEvent
data object NavigateBackClicked : TotpNameEntryEvent
/** The user typed in the name field. */
data class NameChanged(val name: String) : AuthenticatorNameEvent {
data class NameChanged(val name: String) : TotpNameEntryEvent {
override fun toString(): String = "NameChanged(length=${name.length})"
}
/** The user submitted the name they entered. */
data object NextClicked : AuthenticatorNameEvent
data object NextClicked : TotpNameEntryEvent
}
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorname
package org.signal.appsettings.totpnameentry
import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.layout.Column
@@ -38,7 +38,7 @@ import org.signal.core.ui.compose.Scaffolds
import org.signal.core.ui.compose.SignalIcons
@VisibleForTesting
object AuthenticatorNameTestTags {
object TotpNameEntryTestTags {
const val NAME_INPUT = "name-input"
const val BUTTON_NEXT = "button-next"
}
@@ -48,9 +48,9 @@ object AuthenticatorNameTestTags {
* renaming one that already exists.
*/
@Composable
fun AuthenticatorNameScreen(
state: AuthenticatorNameState,
onEvent: (AuthenticatorNameEvent) -> Unit
fun TotpNameEntryScreen(
state: TotpNameEntryState,
onEvent: (TotpNameEntryEvent) -> Unit
) {
val focusRequester = remember { FocusRequester() }
@@ -59,8 +59,8 @@ fun AuthenticatorNameScreen(
}
Scaffolds.Settings(
title = stringResource(R.string.AuthenticatorNameScreen__choose_a_name),
onNavigationClick = { onEvent(AuthenticatorNameEvent.NavigateBackClicked) },
title = stringResource(R.string.TotpNameEntryScreen__choose_a_name),
onNavigationClick = { onEvent(TotpNameEntryEvent.NavigateBackClicked) },
navigationIcon = SignalIcons.ArrowStart.imageVector
) { contentPadding ->
Column(
@@ -72,9 +72,9 @@ fun AuthenticatorNameScreen(
) {
Text(
text = if (state.renaming) {
stringResource(R.string.AuthenticatorNameScreen__choose_a_unique_name)
stringResource(R.string.TotpNameEntryScreen__choose_a_unique_name)
} else {
stringResource(R.string.AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it)
stringResource(R.string.TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it)
},
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
@@ -85,23 +85,23 @@ fun AuthenticatorNameScreen(
TextField(
value = state.name,
onValueChange = { onEvent(AuthenticatorNameEvent.NameChanged(it)) },
label = { Text(text = stringResource(R.string.AuthenticatorNameScreen__name)) },
onValueChange = { onEvent(TotpNameEntryEvent.NameChanged(it)) },
label = { Text(text = stringResource(R.string.TotpNameEntryScreen__name)) },
singleLine = true,
enabled = !state.submitting,
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text, imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { if (state.canSubmit) onEvent(AuthenticatorNameEvent.NextClicked) }),
keyboardActions = KeyboardActions(onDone = { if (state.canSubmit) onEvent(TotpNameEntryEvent.NextClicked) }),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
.focusRequester(focusRequester)
.testTag(AuthenticatorNameTestTags.NAME_INPUT)
.testTag(TotpNameEntryTestTags.NAME_INPUT)
)
Spacer(modifier = Modifier.weight(1f))
Buttons.LargeTonal(
onClick = { onEvent(AuthenticatorNameEvent.NextClicked) },
onClick = { onEvent(TotpNameEntryEvent.NextClicked) },
enabled = state.canSubmit,
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
@@ -109,9 +109,9 @@ fun AuthenticatorNameScreen(
),
modifier = Modifier
.padding(horizontal = 24.dp, vertical = 24.dp)
.testTag(AuthenticatorNameTestTags.BUTTON_NEXT)
.testTag(TotpNameEntryTestTags.BUTTON_NEXT)
) {
Text(text = stringResource(R.string.AuthenticatorNameScreen__next))
Text(text = stringResource(R.string.TotpNameEntryScreen__next))
}
}
}
@@ -119,10 +119,10 @@ fun AuthenticatorNameScreen(
@DayNightPreviews
@Composable
private fun AuthenticatorNameScreenPreview() {
private fun TotpNameEntryScreenPreview() {
Previews.Preview {
AuthenticatorNameScreen(
state = AuthenticatorNameState(name = "Bitwarden Authenticator"),
TotpNameEntryScreen(
state = TotpNameEntryState(name = "Bitwarden Authenticator"),
onEvent = {}
)
}
@@ -130,10 +130,10 @@ private fun AuthenticatorNameScreenPreview() {
@DayNightPreviews
@Composable
private fun AuthenticatorNameScreenRenamePreview() {
private fun TotpNameEntryScreenRenamePreview() {
Previews.Preview {
AuthenticatorNameScreen(
state = AuthenticatorNameState(name = "Twilio Authy", renaming = true),
TotpNameEntryScreen(
state = TotpNameEntryState(name = "Twilio Authy", renaming = true),
onEvent = {}
)
}
@@ -0,0 +1,24 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.totpnameentry
data class TotpNameEntryState(
/**
* The name so far, already capped in grapheme clusters and in UTF-8 bytes by whoever fed it in. Nothing here needs to
* know either limit: an over-length name is never a state this screen has to render or explain, because the field
* simply stops accepting one.
*/
val name: String = "",
/** True when an already-configured app is being renamed, false when one is being named for the first time. */
val renaming: Boolean = false,
val submitting: Boolean = false
) {
val canSubmit: Boolean
get() = name.isNotBlank() && !submitting
override fun toString(): String = "TotpNameEntryState(nameLength=${name.length}, renaming=$renaming, submitting=$submitting)"
}
@@ -3,35 +3,35 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorsetup
package org.signal.appsettings.totpsetup
/**
* One-shot side effects that need an Activity or the nav graph, and therefore have to be carried out by the fragment
* hosting [AuthenticatorSetupScreen] rather than the screen itself.
* hosting [TotpSetupScreen] rather than the screen itself.
*
* Actions are logged, so be sure `toString()` contains nothing sensitive.
*/
sealed interface AuthenticatorSetupAction {
sealed interface TotpSetupAction {
/** Leave the screen. */
data object NavigateBack : AuthenticatorSetupAction
data object NavigateBack : TotpSetupAction
/** Hand [uri] off to whichever authenticator app the user has installed. */
data class LaunchAuthenticatorApp(val uri: String) : AuthenticatorSetupAction {
override fun toString(): String = "LaunchAuthenticatorApp()"
data class LaunchTotpApp(val uri: String) : TotpSetupAction {
override fun toString(): String = "LaunchTotpApp()"
}
/** Put [key] on the clipboard. */
data class CopyKeyToClipboard(val key: String) : AuthenticatorSetupAction {
data class CopyKeyToClipboard(val key: String) : TotpSetupAction {
override fun toString(): String = "CopyKeyToClipboard()"
}
/** Tell the user the setup key was copied. */
data object ShowKeyCopied : AuthenticatorSetupAction
data object ShowKeyCopied : TotpSetupAction
/** Tell the user we couldn't find an app to hand the setup key to. */
data object ShowNoAuthenticatorAppFound : AuthenticatorSetupAction
data object ShowNoTotpAppFound : TotpSetupAction
/** Move on to the screen where the user enters a code from their authenticator app. */
data object NavigateToCodeEntry : AuthenticatorSetupAction
data object NavigateToCodeEntry : TotpSetupAction
}
@@ -3,25 +3,28 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorsetup
package org.signal.appsettings.totpsetup
/**
* Reminder that these events are logged, so don't include anything sensitive in the toString.
*/
sealed interface AuthenticatorSetupEvent {
sealed interface TotpSetupEvent {
/** The user tapped the navigation (back) icon. */
data object NavigateBackClicked : AuthenticatorSetupEvent
data object NavigateBackClicked : TotpSetupEvent
/** The user tapped the button that hands the setup key off to their authenticator app. */
data object OpenAuthenticatorAppClicked : AuthenticatorSetupEvent
data object OpenTotpAppClicked : TotpSetupEvent
/** The user tapped the button that copies the setup key. */
data object CopyKeyClicked : AuthenticatorSetupEvent
data object CopyKeyClicked : TotpSetupEvent
/** The fragment reported that no installed app could handle the setup link. */
data object NoAuthenticatorAppFound : AuthenticatorSetupEvent
data object NoTotpAppFound : TotpSetupEvent
/** The user finished the steps and is ready to enter a code. */
data object ContinueClicked : AuthenticatorSetupEvent
data object ContinueClicked : TotpSetupEvent
/** Dismisses whatever is in [TotpSetupState.dialog], which leaves the screen since none of them are recoverable here. */
data object DialogDismissed : TotpSetupEvent
}
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.authenticatorsetup
package org.signal.appsettings.totpsetup
import androidx.annotation.DrawableRes
import androidx.annotation.VisibleForTesting
@@ -23,6 +23,7 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@@ -45,31 +46,33 @@ import androidx.compose.ui.unit.sp
import org.signal.appsettings.R
import org.signal.core.ui.compose.Buttons
import org.signal.core.ui.compose.DayNightPreviews
import org.signal.core.ui.compose.Dialogs
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.Scaffolds
import org.signal.core.ui.compose.SignalIcons
import org.signal.core.ui.compose.theme.SignalTheme
@VisibleForTesting
object AuthenticatorSetupTestTags {
object TotpSetupTestTags {
const val SCROLLER = "scroller"
const val BUTTON_OPEN = "button-open"
const val BUTTON_COPY = "button-copy"
const val BUTTON_CONTINUE = "button-continue"
const val SETUP_KEY = "setup-key"
const val SETUP_KEY_SPINNER = "setup-key-spinner"
}
/**
* Walks the user through pairing an authenticator app with their account, ending in the code entry screen.
*/
@Composable
fun AuthenticatorSetupScreen(
state: AuthenticatorSetupState,
onEvent: (AuthenticatorSetupEvent) -> Unit
fun TotpSetupScreen(
state: TotpSetupState,
onEvent: (TotpSetupEvent) -> Unit
) {
Scaffolds.Settings(
title = stringResource(R.string.AuthenticatorSetupScreen__set_up_your_authenticator_app),
onNavigationClick = { onEvent(AuthenticatorSetupEvent.NavigateBackClicked) },
title = stringResource(R.string.TotpSetupScreen__set_up_your_authenticator_app),
onNavigationClick = { onEvent(TotpSetupEvent.NavigateBackClicked) },
navigationIcon = SignalIcons.ArrowStart.imageVector
) { contentPadding ->
Column(
@@ -81,16 +84,16 @@ fun AuthenticatorSetupScreen(
modifier = Modifier
.weight(1f)
.verticalScroll(rememberScrollState())
.testTag(AuthenticatorSetupTestTags.SCROLLER)
.testTag(TotpSetupTestTags.SCROLLER)
) {
TextWithLearnMore(
text = stringResource(R.string.AuthenticatorSetupScreen__follow_these_steps),
text = stringResource(R.string.TotpSetupScreen__follow_these_steps),
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
)
StepCard(
title = stringResource(R.string.AuthenticatorSetupScreen__step_1),
body = stringResource(R.string.AuthenticatorSetupScreen__install_a_trusted_authenticator_app),
title = stringResource(R.string.TotpSetupScreen__step_1),
body = stringResource(R.string.TotpSetupScreen__install_a_trusted_authenticator_app),
illustration = {
StepImage(
image = R.drawable.image_authenticator_install_app,
@@ -101,8 +104,8 @@ fun AuthenticatorSetupScreen(
)
StepCard(
title = stringResource(R.string.AuthenticatorSetupScreen__step_2),
body = stringResource(R.string.AuthenticatorSetupScreen__open_your_authenticator_app),
title = stringResource(R.string.TotpSetupScreen__step_2),
body = stringResource(R.string.TotpSetupScreen__open_your_authenticator_app),
illustration = {
StepImage(
image = R.drawable.image_authenticator_open_app,
@@ -112,12 +115,13 @@ fun AuthenticatorSetupScreen(
}
) {
SurfaceButton(
text = stringResource(R.string.AuthenticatorSetupScreen__open),
text = stringResource(R.string.TotpSetupScreen__open),
icon = SignalIcons.Open,
onClick = { onEvent(AuthenticatorSetupEvent.OpenAuthenticatorAppClicked) },
enabled = state.canContinue,
onClick = { onEvent(TotpSetupEvent.OpenTotpAppClicked) },
modifier = Modifier
.padding(top = 16.dp)
.testTag(AuthenticatorSetupTestTags.BUTTON_OPEN)
.testTag(TotpSetupTestTags.BUTTON_OPEN)
)
HorizontalDivider(
@@ -127,38 +131,49 @@ fun AuthenticatorSetupScreen(
)
Text(
text = stringResource(R.string.AuthenticatorSetupScreen__or_you_can_copy_this_key),
text = stringResource(R.string.TotpSetupScreen__or_you_can_copy_this_key),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(top = 24.dp)
)
Text(
text = state.setupKey,
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontSize = 15.sp,
lineHeight = 28.sp,
letterSpacing = 0.9.sp
),
modifier = Modifier
.padding(top = 4.dp)
.testTag(AuthenticatorSetupTestTags.SETUP_KEY)
)
if (state.loading) {
CircularProgressIndicator(
strokeWidth = 2.dp,
modifier = Modifier
.padding(top = 8.dp)
.size(20.dp)
.testTag(TotpSetupTestTags.SETUP_KEY_SPINNER)
)
} else {
Text(
text = state.setupKey,
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontSize = 15.sp,
lineHeight = 28.sp,
letterSpacing = 0.9.sp
),
modifier = Modifier
.padding(top = 4.dp)
.testTag(TotpSetupTestTags.SETUP_KEY)
)
}
SurfaceButton(
text = stringResource(R.string.AuthenticatorSetupScreen__copy),
text = stringResource(R.string.TotpSetupScreen__copy),
icon = SignalIcons.Copy,
onClick = { onEvent(AuthenticatorSetupEvent.CopyKeyClicked) },
enabled = state.canContinue,
onClick = { onEvent(TotpSetupEvent.CopyKeyClicked) },
modifier = Modifier
.padding(top = 16.dp)
.testTag(AuthenticatorSetupTestTags.BUTTON_COPY)
.testTag(TotpSetupTestTags.BUTTON_COPY)
)
}
StepCard(
title = stringResource(R.string.AuthenticatorSetupScreen__step_3),
body = stringResource(R.string.AuthenticatorSetupScreen__copy_the_code_thats_generated),
title = stringResource(R.string.TotpSetupScreen__step_3),
body = stringResource(R.string.TotpSetupScreen__copy_the_code_thats_generated),
illustration = {
StepImage(
image = R.drawable.image_authenticator_copy_code,
@@ -172,7 +187,8 @@ fun AuthenticatorSetupScreen(
}
Buttons.LargeTonal(
onClick = { onEvent(AuthenticatorSetupEvent.ContinueClicked) },
onClick = { onEvent(TotpSetupEvent.ContinueClicked) },
enabled = state.canContinue,
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
@@ -180,14 +196,37 @@ fun AuthenticatorSetupScreen(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 40.dp, vertical = 16.dp)
.testTag(AuthenticatorSetupTestTags.BUTTON_CONTINUE)
.testTag(TotpSetupTestTags.BUTTON_CONTINUE)
) {
Text(text = stringResource(R.string.AuthenticatorSetupScreen__continue))
Text(text = stringResource(R.string.TotpSetupScreen__continue))
}
}
SetupDialog(dialog = state.dialog, onEvent = onEvent)
}
}
/**
* Neither of these is recoverable on this screen, so dismissing either one leaves it.
*/
@Composable
private fun SetupDialog(
dialog: TotpSetupState.Dialog,
onEvent: (TotpSetupEvent) -> Unit
) {
val message = when (dialog) {
TotpSetupState.Dialog.None -> return
is TotpSetupState.Dialog.MaxAppsReached -> stringResource(R.string.TotpAppListScreen__you_cant_add_more_than_d, dialog.maxApps)
TotpSetupState.Dialog.NetworkFailure -> stringResource(R.string.TotpSetupScreen__couldnt_reach_signal)
}
Dialogs.SimpleMessageDialog(
message = message,
dismiss = stringResource(android.R.string.ok),
onDismiss = { onEvent(TotpSetupEvent.DialogDismissed) }
)
}
/**
* Body text with a "Learn more" link appended, which has nowhere to go yet.
*/
@@ -196,7 +235,7 @@ private fun TextWithLearnMore(
text: String,
modifier: Modifier = Modifier
) {
val learnMore = stringResource(R.string.AuthenticatorSetupScreen__learn_more)
val learnMore = stringResource(R.string.TotpSetupScreen__learn_more)
val primaryColor = MaterialTheme.colorScheme.primary
Text(
@@ -283,10 +322,12 @@ private fun SurfaceButton(
text: String,
icon: SignalIcons,
onClick: () -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
enabled: Boolean = true
) {
Buttons.MediumTonal(
onClick = onClick,
enabled = enabled,
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
@@ -307,10 +348,10 @@ private fun SurfaceButton(
@DayNightPreviews
@Composable
private fun AuthenticatorSetupScreenPreview() {
private fun TotpSetupScreenPreview() {
Previews.Preview {
AuthenticatorSetupScreen(
state = AuthenticatorSetupState(setupKey = "KVZ7WL3FDDWJZMTOB7PLZPKVRFD4LYSX"),
TotpSetupScreen(
state = TotpSetupState(setupKey = "KVZ7 WL3F DDWJ ZMTO B7PL ZPKV RFD4 LYSX", loading = false),
onEvent = {}
)
}
@@ -0,0 +1,31 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.signal.appsettings.totpsetup
data class TotpSetupState(
/** The key the user hands to their authenticator app, grouped for reading rather than for pasting. */
val setupKey: String = "",
/** True until the service has handed us a key, which is everything on this screen. */
val loading: Boolean = true,
val dialog: Dialog = Dialog.None
) {
/** Nothing on this screen works without a key, so the buttons wait for one. */
val canContinue: Boolean
get() = !loading && setupKey.isNotEmpty()
override fun toString(): String = "TotpSetupState(setupKey=${if (setupKey.isEmpty()) "empty" else "present"}, loading=$loading, dialog=$dialog)"
sealed interface Dialog {
data object None : Dialog
/** The account already has the [maxApps] authenticator apps it's allowed, so there's no key to be had. */
data class MaxAppsReached(val maxApps: Int) : Dialog
/** We couldn't reach the service to ask for a key. */
data object NetworkFailure : Dialog
}
}
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Vind meer uit</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Stel jou bevestigingstoepassing op</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Stel jou bevestigingstoepassing op</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Volg hierdie stappe om jou bevestigingstoepassing op te stel.</string>
<string name="TotpSetupScreen__follow_these_steps">Volg hierdie stappe om jou bevestigingstoepassing op te stel.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Vind meer uit</string>
<string name="TotpSetupScreen__learn_more">Vind meer uit</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Stap 1</string>
<string name="TotpSetupScreen__step_1">Stap 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Installeer \'n betroubare bevestigingstoepassing op jou toestel.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Installeer \'n betroubare bevestigingstoepassing op jou toestel.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Stap 2</string>
<string name="TotpSetupScreen__step_2">Stap 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Maak jou bevestigingstoepassing oop deur op die knoppie hier onder te tik om jou Signal-rekening by te voeg.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Maak jou bevestigingstoepassing oop deur op die knoppie hier onder te tik om jou Signal-rekening by te voeg.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Maak oop</string>
<string name="TotpSetupScreen__open">Maak oop</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Of jy kan hierdie sleutel kopieer om dit handmatig op te stel.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Of jy kan hierdie sleutel kopieer om dit handmatig op te stel.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopieer</string>
<string name="TotpSetupScreen__copy">Kopieer</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Na knipbord gekopieer</string>
<string name="TotpSetupScreen__copied_to_clipboard">Na knipbord gekopieer</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Geen bevestigingstoepassing gevind nie</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Geen bevestigingstoepassing gevind nie</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Stap 3</string>
<string name="TotpSetupScreen__step_3">Stap 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopieer die kode wat gegenereer word en keer terug hierheen om voort te gaan.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopieer die kode wat gegenereer word en keer terug hierheen om voort te gaan.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Gaan voort</string>
<string name="TotpSetupScreen__continue">Gaan voort</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Verwyder</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Voer jou sleutel in</string>
<string name="TotpCodeEntryScreen__enter_your_code">Voer jou sleutel in</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Voer die 6-syfer-kode vanaf jou bevestigingstoepassing in.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Voer die 6-syfer-kode vanaf jou bevestigingstoepassing in.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kode</string>
<string name="TotpCodeEntryScreen__code">Kode</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Klaar</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Klaar</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Bevestigingstoepassing</string>
<string name="TotpAppListScreen__authenticator_app">Bevestigingstoepassing</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Stel \'n bevestigingstoepassing op om eenmalige verifiëringskodes te genereer</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Stel \'n bevestigingstoepassing op om eenmalige verifiëringskodes te genereer</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Vind meer uit</string>
<string name="TotpAppListScreen__learn_more">Vind meer uit</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Voeg bevestigingstoepassing by</string>
<string name="TotpAppListScreen__add_authenticator_app">Voeg bevestigingstoepassing by</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Bevestigingstoepassings</string>
<string name="TotpAppListScreen__authenticator_apps">Bevestigingstoepassings</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Geen bevestigingstoepassings nie</string>
<string name="TotpAppListScreen__no_authenticator_apps">Geen bevestigingstoepassings nie</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" bygevoeg</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" bygevoeg</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Maak bevestigingstoepassing-opsies oop</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Maak bevestigingstoepassing-opsies oop</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Hernoem</string>
<string name="TotpAppListScreen__rename">Hernoem</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Verwyder</string>
<string name="TotpAppListScreen__remove">Verwyder</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Verwyder bevestigingstoepassing?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Verwyder bevestigingstoepassing?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">Om hierdie bevestigingsmetode te verwyder, word die 6-syfer-kode vanaf jou bevestigingstoepassing vereis.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">Om hierdie bevestigingsmetode te verwyder, word die 6-syfer-kode vanaf jou bevestigingstoepassing vereis.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Kan nie bevestigingstoepassing byvoeg nie</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Kan nie bevestigingstoepassing byvoeg nie</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Jy kan nie meer as %1$d bevestigingstoepassings byvoeg nie. Probeer om eers een te verwyder.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Jy kan nie meer as %1$d bevestigingstoepassings byvoeg nie. Probeer om eers een te verwyder.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Bevestigingstoepassing verwyder</string>
<string name="TotpAppListScreen__authenticator_app_removed">Bevestigingstoepassing verwyder</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Kies \'n naam</string>
<string name="TotpNameEntryScreen__choose_a_name">Kies \'n naam</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Kies \'n unieke naam vir hierdie bevestigingstoepassing.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Kies \'n unieke naam vir hierdie bevestigingstoepassing.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Kies \'n unieke naam vir hierdie bevestigingstoepassing om jou te help om dit later te identifiseer.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Kies \'n unieke naam vir hierdie bevestigingstoepassing om jou te help om dit later te identifiseer.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Naam</string>
<string name="TotpNameEntryScreen__name">Naam</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Volgende</string>
<string name="TotpNameEntryScreen__next">Volgende</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Bevestigingstoepassing opgestel</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Bevestigingstoepassing opgestel</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Bevestigingstoepassing hernoem</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Bevestigingstoepassing hernoem</string>
</resources>
@@ -92,37 +92,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">اعرف المزيد</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">اتَّبِع هذه الخطوات لإعداد تطبيق المصادقة.</string>
<string name="TotpSetupScreen__follow_these_steps">اتَّبِع هذه الخطوات لإعداد تطبيق المصادقة.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">اعرف المزيد</string>
<string name="TotpSetupScreen__learn_more">اعرف المزيد</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">الخطوة 1</string>
<string name="TotpSetupScreen__step_1">الخطوة 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">ثبِّت تطبيق مصادقة موثوق على جهازك.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">ثبِّت تطبيق مصادقة موثوق على جهازك.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">الخطوة 2</string>
<string name="TotpSetupScreen__step_2">الخطوة 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">افتح تطبيق المصادقة بالضغط على الزر أدناه لإضافة حساب سيجنال الخاص بك.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">افتح تطبيق المصادقة بالضغط على الزر أدناه لإضافة حساب سيجنال الخاص بك.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">فتح</string>
<string name="TotpSetupScreen__open">فتح</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">أو يمكنك نسخ المفتاح لإعداده يدويًا.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">أو يمكنك نسخ المفتاح لإعداده يدويًا.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">نسخ</string>
<string name="TotpSetupScreen__copy">نسخ</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">تمَّ النسخ إلى الحافظة</string>
<string name="TotpSetupScreen__copied_to_clipboard">تمَّ النسخ إلى الحافظة</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">لم يتم العثور على أي تطبيق مصادقة</string>
<string name="TotpSetupScreen__no_authenticator_app_found">لم يتم العثور على أي تطبيق مصادقة</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">الخطوة 3</string>
<string name="TotpSetupScreen__step_3">الخطوة 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">انسخ الرمز الذي تمَّ إنشاؤه وعُد إلى هنا للمواصلة.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">انسخ الرمز الذي تمَّ إنشاؤه وعُد إلى هنا للمواصلة.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">متابعة</string>
<string name="TotpSetupScreen__continue">متابعة</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -152,60 +152,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">إزالة</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">أدخِل الكود الخاص بك</string>
<string name="TotpCodeEntryScreen__enter_your_code">أدخِل الكود الخاص بك</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">أدخِل الكود المُكوَّن من 6 أرقام من تطبيق المصادقة لديك.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">أدخِل الكود المُكوَّن من 6 أرقام من تطبيق المصادقة لديك.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">الكود</string>
<string name="TotpCodeEntryScreen__code">الكود</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">تم</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">تم</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">تطبيق المصادقة</string>
<string name="TotpAppListScreen__authenticator_app">تطبيق المصادقة</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">اعرف المزيد</string>
<string name="TotpAppListScreen__learn_more">اعرف المزيد</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">تمَّت إضافة \"%1$s\"</string>
<string name="TotpAppListScreen__added_s">تمَّت إضافة \"%1$s\"</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">إعادة التسمية</string>
<string name="TotpAppListScreen__rename">إعادة التسمية</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">إزالة</string>
<string name="TotpAppListScreen__remove">إزالة</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">اختر اسمًا</string>
<string name="TotpNameEntryScreen__choose_a_name">اختر اسمًا</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">اِسم</string>
<string name="TotpNameEntryScreen__name">اِسم</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">التالي</string>
<string name="TotpNameEntryScreen__next">التالي</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Daha ətraflı</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Autentifikasiya tətbiqinizi quraşdırın</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Autentifikasiya tətbiqinizi quraşdırın</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Autentifikasiya tətbiqini quraşdırmaq üçün bu addımlara əməl edin:</string>
<string name="TotpSetupScreen__follow_these_steps">Autentifikasiya tətbiqini quraşdırmaq üçün bu addımlara əməl edin:</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Daha ətraflı</string>
<string name="TotpSetupScreen__learn_more">Daha ətraflı</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Addım 1</string>
<string name="TotpSetupScreen__step_1">Addım 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Cihazınıza etibarlı bir autentifikasiya tətbiqi quraşdırın.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Cihazınıza etibarlı bir autentifikasiya tətbiqi quraşdırın.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Addım 2</string>
<string name="TotpSetupScreen__step_2">Addım 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Signal hesabınızı əlavə etmək üçün aşağıdakı düyməyə toxunaraq autentifikasiya tətbiqini açın.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Signal hesabınızı əlavə etmək üçün aşağıdakı düyməyə toxunaraq autentifikasiya tətbiqini açın.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open"></string>
<string name="TotpSetupScreen__open"></string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Yaxud da əllə quraşdırma üçün bu parolu kopiyalaya bilərsiniz.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Yaxud da əllə quraşdırma üçün bu parolu kopiyalaya bilərsiniz.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopyala</string>
<string name="TotpSetupScreen__copy">Kopyala</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Mübadilə buferinə kopyalandı</string>
<string name="TotpSetupScreen__copied_to_clipboard">Mübadilə buferinə kopyalandı</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Heç bir autentifikasiya tətbiqi tapılmadı</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Heç bir autentifikasiya tətbiqi tapılmadı</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Addım 3</string>
<string name="TotpSetupScreen__step_3">Addım 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Yaradılmış kodu kopiyalayıb davam etmək üçün buraya qayıdın.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Yaradılmış kodu kopiyalayıb davam etmək üçün buraya qayıdın.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Davam et</string>
<string name="TotpSetupScreen__continue">Davam et</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Çıxart</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Kodunuzu daxil edin</string>
<string name="TotpCodeEntryScreen__enter_your_code">Kodunuzu daxil edin</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Autentifikasiya tətbiqində yaradılmış 6 rəqəmli kodu daxil edin.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Autentifikasiya tətbiqində yaradılmış 6 rəqəmli kodu daxil edin.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Koda bax</string>
<string name="TotpCodeEntryScreen__code">Koda bax</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Bitdi</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Bitdi</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Autentifikasiya tətbiqi</string>
<string name="TotpAppListScreen__authenticator_app">Autentifikasiya tətbiqi</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Birdəfəlik təsdiq kodları yaratmaq üçün autentifikasiya tətbiqi quraşdırın</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Birdəfəlik təsdiq kodları yaratmaq üçün autentifikasiya tətbiqi quraşdırın</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Daha ətraflı</string>
<string name="TotpAppListScreen__learn_more">Daha ətraflı</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Autentifikasiya tətbiqi əlavə et</string>
<string name="TotpAppListScreen__add_authenticator_app">Autentifikasiya tətbiqi əlavə et</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Autentifikasiya tətbiqləri</string>
<string name="TotpAppListScreen__authenticator_apps">Autentifikasiya tətbiqləri</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Autentifikasiya tətbiqi yoxdur</string>
<string name="TotpAppListScreen__no_authenticator_apps">Autentifikasiya tətbiqi yoxdur</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" əlavə edildi</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" əlavə edildi</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Autentifikasiya tətbiqi seçimlərini açın</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Autentifikasiya tətbiqi seçimlərini açın</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Adı dəyiş</string>
<string name="TotpAppListScreen__rename">Adı dəyiş</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Çıxart</string>
<string name="TotpAppListScreen__remove">Çıxart</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Autentifikasiya tətbiqi silinsin?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Autentifikasiya tətbiqi silinsin?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">Bu autentifikasiya metodunu silmək üçün autentifikasiya tətbiqinizin yaratdığı 6 rəqəmli kod tələb olunur.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">Bu autentifikasiya metodunu silmək üçün autentifikasiya tətbiqinizin yaratdığı 6 rəqəmli kod tələb olunur.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Autentifikasiya tətbiqi əlavə etmək mümkün olmadı</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Autentifikasiya tətbiqi əlavə etmək mümkün olmadı</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Maksimum %1$d autentifikasiya tətbiqi əlavə edə bilərsiniz. Əvvəl birini silməyə çalışın.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Maksimum %1$d autentifikasiya tətbiqi əlavə edə bilərsiniz. Əvvəl birini silməyə çalışın.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Autentifikasiya tətbiqi silindi</string>
<string name="TotpAppListScreen__authenticator_app_removed">Autentifikasiya tətbiqi silindi</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Bir ad seçin</string>
<string name="TotpNameEntryScreen__choose_a_name">Bir ad seçin</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Bu autentifikasiya tətbiqi üçün unikal ad seçin.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Bu autentifikasiya tətbiqi üçün unikal ad seçin.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Daha sonra onu tanımağınız üçün bu autentifikasiya tətbiqinə unikal bir ad seçin.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Daha sonra onu tanımağınız üçün bu autentifikasiya tətbiqinə unikal bir ad seçin.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Ad</string>
<string name="TotpNameEntryScreen__name">Ad</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Növbəti</string>
<string name="TotpNameEntryScreen__next">Növbəti</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Autentifikasiya tətbiqi quraşdırıldı</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Autentifikasiya tətbiqi quraşdırıldı</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Autentifikaisya tətbiqinin adı dəyişdirildi</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Autentifikaisya tətbiqinin adı dəyişdirildi</string>
</resources>
@@ -86,37 +86,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Даведацца больш</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Наладзьце праграму аўтэнтыфікацыі</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Наладзьце праграму аўтэнтыфікацыі</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Зрабіце наступныя крокі, каб наладзіць праграму аўтэнтыфікацыі.</string>
<string name="TotpSetupScreen__follow_these_steps">Зрабіце наступныя крокі, каб наладзіць праграму аўтэнтыфікацыі.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Даведацца больш</string>
<string name="TotpSetupScreen__learn_more">Даведацца больш</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Крок 1</string>
<string name="TotpSetupScreen__step_1">Крок 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Усталюйце на сваю прыладу надзейную праграму аўтэнтыфікацыі.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Усталюйце на сваю прыладу надзейную праграму аўтэнтыфікацыі.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Крок 2</string>
<string name="TotpSetupScreen__step_2">Крок 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Адкрыйце праграму аўтэнтыфікацыі, націснуўшы кнопку ніжэй, каб дадаць свой уліковы запіс Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Адкрыйце праграму аўтэнтыфікацыі, націснуўшы кнопку ніжэй, каб дадаць свой уліковы запіс Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Адкрыць</string>
<string name="TotpSetupScreen__open">Адкрыць</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Або вы можаце скапіраваць гэты код, каб наладзіць яе ўручную.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Або вы можаце скапіраваць гэты код, каб наладзіць яе ўручную.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Капіраваць</string>
<string name="TotpSetupScreen__copy">Капіраваць</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Скапіравана ў буфер абмену</string>
<string name="TotpSetupScreen__copied_to_clipboard">Скапіравана ў буфер абмену</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Праграма аўтэнтыфікацыі не знойдзена</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Праграма аўтэнтыфікацыі не знойдзена</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Крок 3</string>
<string name="TotpSetupScreen__step_3">Крок 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Скапіруйце згенераваны код і вяртайцеся сюды, каб працягнуць.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Скапіруйце згенераваны код і вяртайцеся сюды, каб працягнуць.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Працягнуць</string>
<string name="TotpSetupScreen__continue">Працягнуць</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -146,60 +146,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Выдаліць</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Увядзіце свой код</string>
<string name="TotpCodeEntryScreen__enter_your_code">Увядзіце свой код</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Увядзіце 6-значны код з праграмы аўтэнтыфікацыі.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Увядзіце 6-значны код з праграмы аўтэнтыфікацыі.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Код</string>
<string name="TotpCodeEntryScreen__code">Код</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Гатова</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Гатова</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Праграма аўтэнтыфікацыі</string>
<string name="TotpAppListScreen__authenticator_app">Праграма аўтэнтыфікацыі</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Наладзьце праграму аўтэнтыфікацыі для стварэння аднаразовых праверачных кодаў</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Наладзьце праграму аўтэнтыфікацыі для стварэння аднаразовых праверачных кодаў</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Даведацца больш</string>
<string name="TotpAppListScreen__learn_more">Даведацца больш</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Дадаць праграму аўтэнтыфікацыі</string>
<string name="TotpAppListScreen__add_authenticator_app">Дадаць праграму аўтэнтыфікацыі</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Праграмы аўтэнтыфікацыі</string>
<string name="TotpAppListScreen__authenticator_apps">Праграмы аўтэнтыфікацыі</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Праграмы аўтэнтыфікацыі не знойдзены</string>
<string name="TotpAppListScreen__no_authenticator_apps">Праграмы аўтэнтыфікацыі не знойдзены</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">%1$s быў(-ла) даданы(-а)</string>
<string name="TotpAppListScreen__added_s">%1$s быў(-ла) даданы(-а)</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Адкрыць параметры праграмы аўтэнтыфікацыі</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Адкрыць параметры праграмы аўтэнтыфікацыі</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Перайменаваць</string>
<string name="TotpAppListScreen__rename">Перайменаваць</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Выдаліць</string>
<string name="TotpAppListScreen__remove">Выдаліць</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Выдаліць праграму аўтэнтыфікацыі?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Выдаліць праграму аўтэнтыфікацыі?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">Каб выдаліць гэты метад аўтэнтыфікацыі, трэба ўвесці 6-значны код з вашай праграмы аўтэнтыфікацыі.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">Каб выдаліць гэты метад аўтэнтыфікацыі, трэба ўвесці 6-значны код з вашай праграмы аўтэнтыфікацыі.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Немагчыма дадаць праграму аўтэнтыфікацыі</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Немагчыма дадаць праграму аўтэнтыфікацыі</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Вы не можаце дадаць больш за %1$d праграм аўтэнтыфікацыі. Паспрабуйце спачатку выдаліць адну.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Вы не можаце дадаць больш за %1$d праграм аўтэнтыфікацыі. Паспрабуйце спачатку выдаліць адну.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Праграма аўтэнтыфікацыі выдалена</string>
<string name="TotpAppListScreen__authenticator_app_removed">Праграма аўтэнтыфікацыі выдалена</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Выбраць назву</string>
<string name="TotpNameEntryScreen__choose_a_name">Выбраць назву</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Выберыце ўнікальную назву для гэтай праграмы аўтэнтыфікацыі.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Выберыце ўнікальную назву для гэтай праграмы аўтэнтыфікацыі.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Выберыце ўнікальную назву для гэтай праграмы аўтэнтыфікацыі, каб пазней было лягчэй яе ідэнтыфікаваць.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Выберыце ўнікальную назву для гэтай праграмы аўтэнтыфікацыі, каб пазней было лягчэй яе ідэнтыфікаваць.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Імя</string>
<string name="TotpNameEntryScreen__name">Імя</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Далей</string>
<string name="TotpNameEntryScreen__next">Далей</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Налада праграмы аўтэнтыфікацыі</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Налада праграмы аўтэнтыфікацыі</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Праграма аўтэнтыфікацыі перайменавана</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Праграма аўтэнтыфікацыі перайменавана</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Научете повече</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Настройте вашето приложение за автентикация</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Настройте вашето приложение за автентикация</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Следвайте тези стъпки, за да настроите вашето приложение за автентикация.</string>
<string name="TotpSetupScreen__follow_these_steps">Следвайте тези стъпки, за да настроите вашето приложение за автентикация.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Научете повече</string>
<string name="TotpSetupScreen__learn_more">Научете повече</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Стъпка 1</string>
<string name="TotpSetupScreen__step_1">Стъпка 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Инсталирайте приложение за автентикация, на което имате доверие, на своето устройство.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Инсталирайте приложение за автентикация, на което имате доверие, на своето устройство.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Стъпка 2</string>
<string name="TotpSetupScreen__step_2">Стъпка 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Отворете вашето приложение за автентикация, като докоснете бутона по-долу, за да добавите акаунта ви в Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Отворете вашето приложение за автентикация, като докоснете бутона по-долу, за да добавите акаунта ви в Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Отваряне</string>
<string name="TotpSetupScreen__open">Отваряне</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Или можете да копирате този ключ за ръчна настройка.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Или можете да копирате този ключ за ръчна настройка.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Копиране</string>
<string name="TotpSetupScreen__copy">Копиране</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Копирано</string>
<string name="TotpSetupScreen__copied_to_clipboard">Копирано</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Не е открито приложение за автентикация</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Не е открито приложение за автентикация</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Стъпка 3</string>
<string name="TotpSetupScreen__step_3">Стъпка 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Копирайте генерирания код и се върнете тук, за да продължите.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Копирайте генерирания код и се върнете тук, за да продължите.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Продължаване</string>
<string name="TotpSetupScreen__continue">Продължаване</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Премахване</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Въведете вашия код</string>
<string name="TotpCodeEntryScreen__enter_your_code">Въведете вашия код</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Въведете 6-цифрения код от вашето приложение за автентикация.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Въведете 6-цифрения код от вашето приложение за автентикация.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Код</string>
<string name="TotpCodeEntryScreen__code">Код</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Готово</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Готово</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Приложение за автентикация</string>
<string name="TotpAppListScreen__authenticator_app">Приложение за автентикация</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Настройте приложение за автентикация за генериране на еднократни кодове за потвърждение</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Настройте приложение за автентикация за генериране на еднократни кодове за потвърждение</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Научете повече</string>
<string name="TotpAppListScreen__learn_more">Научете повече</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Добавяне на приложение за автентикация</string>
<string name="TotpAppListScreen__add_authenticator_app">Добавяне на приложение за автентикация</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Приложения за автентикация</string>
<string name="TotpAppListScreen__authenticator_apps">Приложения за автентикация</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Няма приложения за автентикация</string>
<string name="TotpAppListScreen__no_authenticator_apps">Няма приложения за автентикация</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Добавихте \"%1$s\"</string>
<string name="TotpAppListScreen__added_s">Добавихте \"%1$s\"</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Отваряне на опциите на приложението за автентикация</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Отваряне на опциите на приложението за автентикация</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Преименуване</string>
<string name="TotpAppListScreen__rename">Преименуване</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Премахване</string>
<string name="TotpAppListScreen__remove">Премахване</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Премахване на приложението за автентикация?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Премахване на приложението за автентикация?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">За премахване на този метод за автентикация е необходим 6-цифреният код от вашето приложение за автентикация.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">За премахване на този метод за автентикация е необходим 6-цифреният код от вашето приложение за автентикация.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Неуспешно добавяне на приложение за автентикация</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Неуспешно добавяне на приложение за автентикация</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Не можете да добавите повече от %1$d приложения за автентикация. Опитайте първо да премахнете някое.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Не можете да добавите повече от %1$d приложения за автентикация. Опитайте първо да премахнете някое.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Приложението за автентикация е премахнато</string>
<string name="TotpAppListScreen__authenticator_app_removed">Приложението за автентикация е премахнато</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Изберете име</string>
<string name="TotpNameEntryScreen__choose_a_name">Изберете име</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Изберете уникално име за това приложение за автентикация.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Изберете уникално име за това приложение за автентикация.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Изберете уникално име за това приложение за автентикация, за да го разпознаете по-късно.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Изберете уникално име за това приложение за автентикация, за да го разпознаете по-късно.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Име</string>
<string name="TotpNameEntryScreen__name">Име</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Напред</string>
<string name="TotpNameEntryScreen__next">Напред</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Приложението за автентикация е настроено</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Приложението за автентикация е настроено</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Приложението за автентикация е преименувано</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Приложението за автентикация е преименувано</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">আরো জানুন</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">আপনার অথেন্টিকেটর অ্যাপ সেট আপ করতে এই ধাপগুলো অনুসরণ করুন।</string>
<string name="TotpSetupScreen__follow_these_steps">আপনার অথেন্টিকেটর অ্যাপ সেট আপ করতে এই ধাপগুলো অনুসরণ করুন।</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">আরো জানুন</string>
<string name="TotpSetupScreen__learn_more">আরো জানুন</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">ধাপ ১</string>
<string name="TotpSetupScreen__step_1">ধাপ ১</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">আপনার ডিভাইসে একটি আস্থাভাজন অথেন্টিকেটর অ্যাপ ইনস্টল করুন।</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">আপনার ডিভাইসে একটি আস্থাভাজন অথেন্টিকেটর অ্যাপ ইনস্টল করুন।</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">ধাপ ২</string>
<string name="TotpSetupScreen__step_2">ধাপ ২</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">আপনার Signal অ্যাকাউন্ট যোগ করতে নিচের বাটনটি ট্যাপ করে আপনার অথেন্টিকেটর অ্যাপটি খুলুন।</string>
<string name="TotpSetupScreen__open_your_authenticator_app">আপনার Signal অ্যাকাউন্ট যোগ করতে নিচের বাটনটি ট্যাপ করে আপনার অথেন্টিকেটর অ্যাপটি খুলুন।</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">খুলুন</string>
<string name="TotpSetupScreen__open">খুলুন</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">অথবা আপনি এই কী-টি কপি করে ম্যানুয়ালি সেট আপ করতে পারেন।</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">অথবা আপনি এই কী-টি কপি করে ম্যানুয়ালি সেট আপ করতে পারেন।</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">অনুলিপি</string>
<string name="TotpSetupScreen__copy">অনুলিপি</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">ক্লিপবোর্ডে কপি করা হয়েছে</string>
<string name="TotpSetupScreen__copied_to_clipboard">ক্লিপবোর্ডে কপি করা হয়েছে</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">কোনো অথেন্টিকেটর অ্যাপ পাওয়া যায়নি</string>
<string name="TotpSetupScreen__no_authenticator_app_found">কোনো অথেন্টিকেটর অ্যাপ পাওয়া যায়নি</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">ধাপ ৩</string>
<string name="TotpSetupScreen__step_3">ধাপ ৩</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">তৈরি হওয়া কোডটি কপি করুন এবং চালিয়ে যাওয়ার জন্য এখানে ফিরে আসুন।</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">তৈরি হওয়া কোডটি কপি করুন এবং চালিয়ে যাওয়ার জন্য এখানে ফিরে আসুন।</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">চলতে থাকুন</string>
<string name="TotpSetupScreen__continue">চলতে থাকুন</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">সরিয়ে ফেলুন</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">আপনার কোড লিখুন</string>
<string name="TotpCodeEntryScreen__enter_your_code">আপনার কোড লিখুন</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">আপনার অথেন্টিকেটর অ্যাপ থেকে ৬-সংখ্যার কোডটি লিখুন।</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">আপনার অথেন্টিকেটর অ্যাপ থেকে ৬-সংখ্যার কোডটি লিখুন।</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">কোড</string>
<string name="TotpCodeEntryScreen__code">কোড</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">সম্পন্ন হয়েছে</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">সম্পন্ন হয়েছে</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">অথেন্টিকেটর অ্যাপ</string>
<string name="TotpAppListScreen__authenticator_app">অথেন্টিকেটর অ্যাপ</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">আরো জানুন</string>
<string name="TotpAppListScreen__learn_more">আরো জানুন</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" যুক্ত হয়েছে</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" যুক্ত হয়েছে</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">রিনেম করুন</string>
<string name="TotpAppListScreen__rename">রিনেম করুন</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">সরিয়ে ফেলুন</string>
<string name="TotpAppListScreen__remove">সরিয়ে ফেলুন</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">একটি নাম চয়ন করুন</string>
<string name="TotpNameEntryScreen__choose_a_name">একটি নাম চয়ন করুন</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">নাম</string>
<string name="TotpNameEntryScreen__name">নাম</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">পরবর্তী</string>
<string name="TotpNameEntryScreen__next">পরবর্তী</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -86,37 +86,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Saznaj više</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Slijedite ove korake da postavite aplikaciju za autentifikaciju.</string>
<string name="TotpSetupScreen__follow_these_steps">Slijedite ove korake da postavite aplikaciju za autentifikaciju.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Saznaj više</string>
<string name="TotpSetupScreen__learn_more">Saznaj više</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">1. korak</string>
<string name="TotpSetupScreen__step_1">1. korak</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instalirajte pouzdanu aplikaciju za autentifikaciju na svoj uređaj.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instalirajte pouzdanu aplikaciju za autentifikaciju na svoj uređaj.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">2. korak</string>
<string name="TotpSetupScreen__step_2">2. korak</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Otvorite aplikaciju za autentifikaciju dodirom na dugme u nastavku kako biste dodali svoj Signal račun.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Otvorite aplikaciju za autentifikaciju dodirom na dugme u nastavku kako biste dodali svoj Signal račun.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Otvori</string>
<string name="TotpSetupScreen__open">Otvori</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Ili možete kopirati ovaj ključ za ručno postavljanje.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Ili možete kopirati ovaj ključ za ručno postavljanje.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopiraj</string>
<string name="TotpSetupScreen__copy">Kopiraj</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Kopirano u međuspremnik</string>
<string name="TotpSetupScreen__copied_to_clipboard">Kopirano u međuspremnik</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Aplikacija za autentifikaciju nije pronađena</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Aplikacija za autentifikaciju nije pronađena</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">3. korak</string>
<string name="TotpSetupScreen__step_3">3. korak</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopirajte generirani kôd i vratite se ovdje da nastavite.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopirajte generirani kôd i vratite se ovdje da nastavite.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Nastavi</string>
<string name="TotpSetupScreen__continue">Nastavi</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -146,60 +146,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Ukloni</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Unesite svoj kôd</string>
<string name="TotpCodeEntryScreen__enter_your_code">Unesite svoj kôd</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Unesite šestocifreni kôd iz aplikacije za autentifikaciju.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Unesite šestocifreni kôd iz aplikacije za autentifikaciju.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kȏd</string>
<string name="TotpCodeEntryScreen__code">Kȏd</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Gotovo</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Gotovo</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Aplikacija za autentifikaciju</string>
<string name="TotpAppListScreen__authenticator_app">Aplikacija za autentifikaciju</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Saznaj više</string>
<string name="TotpAppListScreen__learn_more">Saznaj više</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Uvršten/a \"%1$s\"</string>
<string name="TotpAppListScreen__added_s">Uvršten/a \"%1$s\"</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Rename</string>
<string name="TotpAppListScreen__rename">Rename</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Ukloni</string>
<string name="TotpAppListScreen__remove">Ukloni</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Choose a name</string>
<string name="TotpNameEntryScreen__choose_a_name">Choose a name</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Name</string>
<string name="TotpNameEntryScreen__name">Name</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Dalje</string>
<string name="TotpNameEntryScreen__next">Dalje</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Més informació</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Segueix aquests passos per configurar la teva app d\'autenticació.</string>
<string name="TotpSetupScreen__follow_these_steps">Segueix aquests passos per configurar la teva app d\'autenticació.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Més informació</string>
<string name="TotpSetupScreen__learn_more">Més informació</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Pas 1</string>
<string name="TotpSetupScreen__step_1">Pas 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instal·la una app d\'autenticació de confiança al teu dispositiu.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instal·la una app d\'autenticació de confiança al teu dispositiu.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Pas 2</string>
<string name="TotpSetupScreen__step_2">Pas 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Toca el botó d\'aquí baix per obrir la teva app d\'autenticació i afegir el teu compte de Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Toca el botó d\'aquí baix per obrir la teva app d\'autenticació i afegir el teu compte de Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Obrir</string>
<string name="TotpSetupScreen__open">Obrir</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">O copia aquesta clau per configurar-la de forma manual.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">O copia aquesta clau per configurar-la de forma manual.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Copia</string>
<string name="TotpSetupScreen__copy">Copia</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Copiat al portapapers</string>
<string name="TotpSetupScreen__copied_to_clipboard">Copiat al portapapers</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">No s\'ha trobat cap app d\'autenticació</string>
<string name="TotpSetupScreen__no_authenticator_app_found">No s\'ha trobat cap app d\'autenticació</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Pas 3</string>
<string name="TotpSetupScreen__step_3">Pas 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Copia la clau que generada i torna aquí per continuar.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Copia la clau que generada i torna aquí per continuar.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Continua</string>
<string name="TotpSetupScreen__continue">Continua</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Suprimeix</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Introdueix la teva clau</string>
<string name="TotpCodeEntryScreen__enter_your_code">Introdueix la teva clau</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Introdueix la clau de 6 dígits de la teva app d\'autenticació.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Introdueix la clau de 6 dígits de la teva app d\'autenticació.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Codi</string>
<string name="TotpCodeEntryScreen__code">Codi</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Fet</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Fet</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">App d\'autenticació</string>
<string name="TotpAppListScreen__authenticator_app">App d\'autenticació</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Més informació</string>
<string name="TotpAppListScreen__learn_more">Més informació</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">S\'hi ha afegit %1$s</string>
<string name="TotpAppListScreen__added_s">S\'hi ha afegit %1$s</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Canviar el nom</string>
<string name="TotpAppListScreen__rename">Canviar el nom</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Suprimeix</string>
<string name="TotpAppListScreen__remove">Suprimeix</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Trieu un nom</string>
<string name="TotpNameEntryScreen__choose_a_name">Trieu un nom</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nom</string>
<string name="TotpNameEntryScreen__name">Nom</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Següent</string>
<string name="TotpNameEntryScreen__next">Següent</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -86,37 +86,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Zjistit více</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Nastavte si ověřovací aplikaci</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Nastavte si ověřovací aplikaci</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Pro nastavení ověřovací aplikace postupujte takto:</string>
<string name="TotpSetupScreen__follow_these_steps">Pro nastavení ověřovací aplikace postupujte takto:</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Zjistit více</string>
<string name="TotpSetupScreen__learn_more">Zjistit více</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Krok 1</string>
<string name="TotpSetupScreen__step_1">Krok 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Nainstalujte si do zařízení důvěryhodnou ověřovací aplikaci.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Nainstalujte si do zařízení důvěryhodnou ověřovací aplikaci.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Krok 2</string>
<string name="TotpSetupScreen__step_2">Krok 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Klepnutím na tlačítko níže otevřete ověřovací aplikaci a přidejte svůj účet Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Klepnutím na tlačítko níže otevřete ověřovací aplikaci a přidejte svůj účet Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Otevřít</string>
<string name="TotpSetupScreen__open">Otevřít</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Případně můžete tento klíč zkopírovat a provést ruční nastavení.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Případně můžete tento klíč zkopírovat a provést ruční nastavení.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopírovat</string>
<string name="TotpSetupScreen__copy">Kopírovat</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Zkopírováno do schránky</string>
<string name="TotpSetupScreen__copied_to_clipboard">Zkopírováno do schránky</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Nebyla nalezena žádná ověřovací aplikace</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Nebyla nalezena žádná ověřovací aplikace</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Krok 3</string>
<string name="TotpSetupScreen__step_3">Krok 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Zkopírujte vygenerovaný kód a zadejte sem, abyste mohli pokračovat.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Zkopírujte vygenerovaný kód a zadejte sem, abyste mohli pokračovat.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Pokračovat</string>
<string name="TotpSetupScreen__continue">Pokračovat</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -146,60 +146,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Odstranit</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Zadejte kód</string>
<string name="TotpCodeEntryScreen__enter_your_code">Zadejte kód</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Zadejte 6číselný kód ze své ověřovací aplikace.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Zadejte 6číselný kód ze své ověřovací aplikace.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kód</string>
<string name="TotpCodeEntryScreen__code">Kód</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Hotovo</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Hotovo</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Ověřovací aplikace</string>
<string name="TotpAppListScreen__authenticator_app">Ověřovací aplikace</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Nastavte si ověřovací aplikaci pro generování jednorázových ověřovacích kódů</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Nastavte si ověřovací aplikaci pro generování jednorázových ověřovacích kódů</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Zjistit více</string>
<string name="TotpAppListScreen__learn_more">Zjistit více</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Přidat ověřovací aplikaci</string>
<string name="TotpAppListScreen__add_authenticator_app">Přidat ověřovací aplikaci</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Ověřovací aplikace</string>
<string name="TotpAppListScreen__authenticator_apps">Ověřovací aplikace</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Žádná ověřovací aplikace</string>
<string name="TotpAppListScreen__no_authenticator_apps">Žádná ověřovací aplikace</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Přidán %1$s</string>
<string name="TotpAppListScreen__added_s">Přidán %1$s</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Otevřít možnosti ověřovací aplikace</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Otevřít možnosti ověřovací aplikace</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Přejmenovat</string>
<string name="TotpAppListScreen__rename">Přejmenovat</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Odstranit</string>
<string name="TotpAppListScreen__remove">Odstranit</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Odstranit ověřovací aplikaci?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Odstranit ověřovací aplikaci?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">K odstranění této ověřovací metody je potřeba 6místný kód z vaší ověřovací aplikace.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">K odstranění této ověřovací metody je potřeba 6místný kód z vaší ověřovací aplikace.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Ověřovací aplikaci nelze přidat</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Ověřovací aplikaci nelze přidat</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Nelze přidat více než %1$d ověřovací aplikaci. Zkuste nejprve jednu odstranit.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Nelze přidat více než %1$d ověřovací aplikaci. Zkuste nejprve jednu odstranit.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Ověřovací aplikace odstraněna</string>
<string name="TotpAppListScreen__authenticator_app_removed">Ověřovací aplikace odstraněna</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Zvolte jméno</string>
<string name="TotpNameEntryScreen__choose_a_name">Zvolte jméno</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Zvolte jedinečný název pro tuto ověřovací aplikaci.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Zvolte jedinečný název pro tuto ověřovací aplikaci.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Zvolte jedinečný název pro tuto ověřovací aplikaci, abyste ji později snadno rozpoznali.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Zvolte jedinečný název pro tuto ověřovací aplikaci, abyste ji později snadno rozpoznali.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Název</string>
<string name="TotpNameEntryScreen__name">Název</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Další</string>
<string name="TotpNameEntryScreen__next">Další</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Ověřovací aplikace nastavena</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Ověřovací aplikace nastavena</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Ověřovací aplikace přejmenována</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Ověřovací aplikace přejmenována</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Få mere at vide</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Opsæt din godkendelsesapp</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Opsæt din godkendelsesapp</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Følg disse trin til opsætning af din godkendelsesapp.</string>
<string name="TotpSetupScreen__follow_these_steps">Følg disse trin til opsætning af din godkendelsesapp.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Få mere at vide</string>
<string name="TotpSetupScreen__learn_more">Få mere at vide</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Trin 1</string>
<string name="TotpSetupScreen__step_1">Trin 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Installer en godkendt godkendelsesapp på din enhed.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Installer en godkendt godkendelsesapp på din enhed.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Trin 2</string>
<string name="TotpSetupScreen__step_2">Trin 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Åbn din godkendelsesapp ved at trykke på knappen nedenfor for at tilføje din Signal-konto.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Åbn din godkendelsesapp ved at trykke på knappen nedenfor for at tilføje din Signal-konto.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Åbn</string>
<string name="TotpSetupScreen__open">Åbn</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Eller du kan kopiere denne nøgle til manuel opsætning.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Eller du kan kopiere denne nøgle til manuel opsætning.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopiér</string>
<string name="TotpSetupScreen__copy">Kopiér</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Kopieret til udklipsholder</string>
<string name="TotpSetupScreen__copied_to_clipboard">Kopieret til udklipsholder</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Ingen authenticator-app fundet</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Ingen authenticator-app fundet</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Trin 3</string>
<string name="TotpSetupScreen__step_3">Trin 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopiér den genererede kode, og vend tilbage hertil for at fortsætte.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopiér den genererede kode, og vend tilbage hertil for at fortsætte.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Fortsæt</string>
<string name="TotpSetupScreen__continue">Fortsæt</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Fjern</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Angiv din kode</string>
<string name="TotpCodeEntryScreen__enter_your_code">Angiv din kode</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Angiv den sekscifrede kode fra din godkendelsesapp.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Angiv den sekscifrede kode fra din godkendelsesapp.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kode</string>
<string name="TotpCodeEntryScreen__code">Kode</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Færdig</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Færdig</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Godkendelsesapp</string>
<string name="TotpAppListScreen__authenticator_app">Godkendelsesapp</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Opsæt en godkendelsesapp til at generere engangsbekræftelseskoder</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Opsæt en godkendelsesapp til at generere engangsbekræftelseskoder</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Få mere at vide</string>
<string name="TotpAppListScreen__learn_more">Få mere at vide</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Tilføj godkendelsesapp</string>
<string name="TotpAppListScreen__add_authenticator_app">Tilføj godkendelsesapp</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Godkendelsesapps</string>
<string name="TotpAppListScreen__authenticator_apps">Godkendelsesapps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Ingen godkendelsesapps</string>
<string name="TotpAppListScreen__no_authenticator_apps">Ingen godkendelsesapps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" tilføjet</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" tilføjet</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Åbn indstillinger for godkendelsesapp</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Åbn indstillinger for godkendelsesapp</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Omdøb</string>
<string name="TotpAppListScreen__rename">Omdøb</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Fjern</string>
<string name="TotpAppListScreen__remove">Fjern</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Vil du godkendelsesappen?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Vil du godkendelsesappen?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">For at fjerne denne godkendelsesmetode skal du bruge den sekscifrede kode fra din godkendelsesapp.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">For at fjerne denne godkendelsesmetode skal du bruge den sekscifrede kode fra din godkendelsesapp.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Kan ikke tilføje godkendelsesapp</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Kan ikke tilføje godkendelsesapp</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Du kan ikke tilføje mere end %1$d godkendelsesapps. Prøv at fjerne en først.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Du kan ikke tilføje mere end %1$d godkendelsesapps. Prøv at fjerne en først.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Godkendelsesapp fjernet</string>
<string name="TotpAppListScreen__authenticator_app_removed">Godkendelsesapp fjernet</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Skriv et navn</string>
<string name="TotpNameEntryScreen__choose_a_name">Skriv et navn</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Vælg et unikt navn til denne godkendelsesapp.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Vælg et unikt navn til denne godkendelsesapp.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Vælg et unikt navn til denne godkendelsesapp, så du nemt kan genkende den senere.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Vælg et unikt navn til denne godkendelsesapp, så du nemt kan genkende den senere.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Navn</string>
<string name="TotpNameEntryScreen__name">Navn</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Næste</string>
<string name="TotpNameEntryScreen__next">Næste</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Godkendelsesapp er opsat</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Godkendelsesapp er opsat</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Godkendelsesapp er omdøbt</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Godkendelsesapp er omdøbt</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Mehr erfahren</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Befolge diese Schritte, um deine Authentifizierungs-App einzurichten.</string>
<string name="TotpSetupScreen__follow_these_steps">Befolge diese Schritte, um deine Authentifizierungs-App einzurichten.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Mehr erfahren</string>
<string name="TotpSetupScreen__learn_more">Mehr erfahren</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">1. Schritt</string>
<string name="TotpSetupScreen__step_1">1. Schritt</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Installiere eine vertrauenswürdige Authentifizierungs-App auf deinem Gerät.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Installiere eine vertrauenswürdige Authentifizierungs-App auf deinem Gerät.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">2. Schritt</string>
<string name="TotpSetupScreen__step_2">2. Schritt</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Öffne deine Authentifizierungs-App, indem du auf die Schaltfläche unten tippst, um dein Signal-Konto hinzuzufügen.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Öffne deine Authentifizierungs-App, indem du auf die Schaltfläche unten tippst, um dein Signal-Konto hinzuzufügen.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Öffnen</string>
<string name="TotpSetupScreen__open">Öffnen</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Oder kopiere diesen Schlüssel für eine manuelle Einrichtung.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Oder kopiere diesen Schlüssel für eine manuelle Einrichtung.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopieren</string>
<string name="TotpSetupScreen__copy">Kopieren</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">In Zwischenablage kopiert</string>
<string name="TotpSetupScreen__copied_to_clipboard">In Zwischenablage kopiert</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Keine Authentifizierungs-App gefunden</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Keine Authentifizierungs-App gefunden</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">3. Schritt</string>
<string name="TotpSetupScreen__step_3">3. Schritt</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopiere den generierten Code und komm hierher zurück, um fortzufahren.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopiere den generierten Code und komm hierher zurück, um fortzufahren.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Weiter</string>
<string name="TotpSetupScreen__continue">Weiter</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Entfernen</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Gib deinen Code ein</string>
<string name="TotpCodeEntryScreen__enter_your_code">Gib deinen Code ein</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Gib den 6-stelligen Code aus deiner Authentifizierungs-App ein.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Gib den 6-stelligen Code aus deiner Authentifizierungs-App ein.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Code</string>
<string name="TotpCodeEntryScreen__code">Code</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Fertig</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Fertig</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Authentifizierungs-App</string>
<string name="TotpAppListScreen__authenticator_app">Authentifizierungs-App</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Mehr erfahren</string>
<string name="TotpAppListScreen__learn_more">Mehr erfahren</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">%1$s hinzugefügt</string>
<string name="TotpAppListScreen__added_s">%1$s hinzugefügt</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Umbenennen</string>
<string name="TotpAppListScreen__rename">Umbenennen</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Entfernen</string>
<string name="TotpAppListScreen__remove">Entfernen</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Name wählen</string>
<string name="TotpNameEntryScreen__choose_a_name">Name wählen</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Name</string>
<string name="TotpNameEntryScreen__name">Name</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Weiter</string>
<string name="TotpNameEntryScreen__next">Weiter</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Μάθε περισσότερα</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Ακολούθησε αυτά τα βήματα για να ρυθμίσεις την εφαρμογή επαλήθευσης.</string>
<string name="TotpSetupScreen__follow_these_steps">Ακολούθησε αυτά τα βήματα για να ρυθμίσεις την εφαρμογή επαλήθευσης.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Μάθε περισσότερα</string>
<string name="TotpSetupScreen__learn_more">Μάθε περισσότερα</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Βήμα 1</string>
<string name="TotpSetupScreen__step_1">Βήμα 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Εγκατάστησε μια έμπιστη εφαρμογή επαλήθευσης στη συσκευή σου.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Εγκατάστησε μια έμπιστη εφαρμογή επαλήθευσης στη συσκευή σου.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Βήμα 2</string>
<string name="TotpSetupScreen__step_2">Βήμα 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Άνοιξε την εφαρμογή επαλήθευσης, πατώντας το κουμπί παρακάτω ώστε να προσθέσεις τον λογαριασμό σου Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Άνοιξε την εφαρμογή επαλήθευσης, πατώντας το κουμπί παρακάτω ώστε να προσθέσεις τον λογαριασμό σου Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Άνοιγμα</string>
<string name="TotpSetupScreen__open">Άνοιγμα</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Ή μπορείς να αντιγράψεις αυτό το κλειδί χειροκίνητα για να τον προσθέσεις.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Ή μπορείς να αντιγράψεις αυτό το κλειδί χειροκίνητα για να τον προσθέσεις.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Αντιγραφή</string>
<string name="TotpSetupScreen__copy">Αντιγραφή</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Αντιγράφηκε στο πρόχειρο</string>
<string name="TotpSetupScreen__copied_to_clipboard">Αντιγράφηκε στο πρόχειρο</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Δεν βρέθηκε εφαρμογή επαλήθευσης</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Δεν βρέθηκε εφαρμογή επαλήθευσης</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Βήμα 3</string>
<string name="TotpSetupScreen__step_3">Βήμα 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Αντίγραψε τον κωδικό που δημιουργήθηκε και επίστρεψε εδώ για να συνεχίσεις.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Αντίγραψε τον κωδικό που δημιουργήθηκε και επίστρεψε εδώ για να συνεχίσεις.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Συνέχεια</string>
<string name="TotpSetupScreen__continue">Συνέχεια</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Αφαίρεση</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Γράψε τον κωδικό σου</string>
<string name="TotpCodeEntryScreen__enter_your_code">Γράψε τον κωδικό σου</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Γράψε τον 6-ψηφιο κωδικό από την εφαρμογή επαλήθευσης.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Γράψε τον 6-ψηφιο κωδικό από την εφαρμογή επαλήθευσης.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Κωδικός</string>
<string name="TotpCodeEntryScreen__code">Κωδικός</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Τέλος</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Τέλος</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Εφαρμογή επαλήθευσης</string>
<string name="TotpAppListScreen__authenticator_app">Εφαρμογή επαλήθευσης</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Μάθε περισσότερα</string>
<string name="TotpAppListScreen__learn_more">Μάθε περισσότερα</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Ο/Η \"%1$s\" προστέθηκε</string>
<string name="TotpAppListScreen__added_s">Ο/Η \"%1$s\" προστέθηκε</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Μετονομασία</string>
<string name="TotpAppListScreen__rename">Μετονομασία</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Αφαίρεση</string>
<string name="TotpAppListScreen__remove">Αφαίρεση</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Διάλεξε όνομα</string>
<string name="TotpNameEntryScreen__choose_a_name">Διάλεξε όνομα</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Όνομα</string>
<string name="TotpNameEntryScreen__name">Όνομα</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Επόμενο</string>
<string name="TotpNameEntryScreen__next">Επόμενο</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Más información</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Sigue estos pasos para configurar tu aplicación de autenticación.</string>
<string name="TotpSetupScreen__follow_these_steps">Sigue estos pasos para configurar tu aplicación de autenticación.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Más información</string>
<string name="TotpSetupScreen__learn_more">Más información</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Paso 1</string>
<string name="TotpSetupScreen__step_1">Paso 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instala una aplicación de autenticación de confianza en tu dispositivo.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instala una aplicación de autenticación de confianza en tu dispositivo.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Paso 2</string>
<string name="TotpSetupScreen__step_2">Paso 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Toca el botón de abajo para abrir tu aplicación de autenticación y añadir tu cuenta de Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Toca el botón de abajo para abrir tu aplicación de autenticación y añadir tu cuenta de Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Abrir</string>
<string name="TotpSetupScreen__open">Abrir</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">También puedes copiar esta clave para configurar la app de forma manual.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">También puedes copiar esta clave para configurar la app de forma manual.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Copiar</string>
<string name="TotpSetupScreen__copy">Copiar</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Copiado al portapapeles</string>
<string name="TotpSetupScreen__copied_to_clipboard">Copiado al portapapeles</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">No se ha encontrado ninguna aplicación de autenticación</string>
<string name="TotpSetupScreen__no_authenticator_app_found">No se ha encontrado ninguna aplicación de autenticación</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Paso 3</string>
<string name="TotpSetupScreen__step_3">Paso 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Copia la clave que se genere y vuelve aquí para continuar.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Copia la clave que se genere y vuelve aquí para continuar.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Continuar</string>
<string name="TotpSetupScreen__continue">Continuar</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Eliminar</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Introduce tu clave</string>
<string name="TotpCodeEntryScreen__enter_your_code">Introduce tu clave</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Introduce la clave de 6 dígitos de tu aplicación de autenticación.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Introduce la clave de 6 dígitos de tu aplicación de autenticación.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Código</string>
<string name="TotpCodeEntryScreen__code">Código</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Listo</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Listo</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Aplicación de autenticación</string>
<string name="TotpAppListScreen__authenticator_app">Aplicación de autenticación</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Más información</string>
<string name="TotpAppListScreen__learn_more">Más información</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Se ha añadido a %1$s</string>
<string name="TotpAppListScreen__added_s">Se ha añadido a %1$s</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Cambiar nombre</string>
<string name="TotpAppListScreen__rename">Cambiar nombre</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Eliminar</string>
<string name="TotpAppListScreen__remove">Eliminar</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Elige un nombre</string>
<string name="TotpNameEntryScreen__choose_a_name">Elige un nombre</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nombre</string>
<string name="TotpNameEntryScreen__name">Nombre</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Siguiente</string>
<string name="TotpNameEntryScreen__next">Siguiente</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Rohkem teavet</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Seadista oma autentimise äpp</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Seadista oma autentimise äpp</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Järgi neid samme, et oma autentimise äppi seadistada.</string>
<string name="TotpSetupScreen__follow_these_steps">Järgi neid samme, et oma autentimise äppi seadistada.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Rohkem teavet</string>
<string name="TotpSetupScreen__learn_more">Rohkem teavet</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Samm 1</string>
<string name="TotpSetupScreen__step_1">Samm 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Paigalda oma seadmesse usaldusväärne autentimise äpp.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Paigalda oma seadmesse usaldusväärne autentimise äpp.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Samm 2</string>
<string name="TotpSetupScreen__step_2">Samm 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Ava oma autentimise äpp, puudutades allolevat nuppu, et oma Signali konto lisada.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Ava oma autentimise äpp, puudutades allolevat nuppu, et oma Signali konto lisada.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Ava</string>
<string name="TotpSetupScreen__open">Ava</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Võid ka selle võtme kopeerida, et käsitsi seadistada.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Võid ka selle võtme kopeerida, et käsitsi seadistada.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopeeri</string>
<string name="TotpSetupScreen__copy">Kopeeri</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Lõikelauale kopeeritud</string>
<string name="TotpSetupScreen__copied_to_clipboard">Lõikelauale kopeeritud</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Ühtegi autentimise äppi ei leitud</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Ühtegi autentimise äppi ei leitud</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Samm 3</string>
<string name="TotpSetupScreen__step_3">Samm 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopeeri loodud kood ja tule siia tagasi, et jätkata.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopeeri loodud kood ja tule siia tagasi, et jätkata.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Jätka</string>
<string name="TotpSetupScreen__continue">Jätka</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Eemalda</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Sisesta oma kood</string>
<string name="TotpCodeEntryScreen__enter_your_code">Sisesta oma kood</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Sisesta oma autentimise äpist 6-kohaline kood.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Sisesta oma autentimise äpist 6-kohaline kood.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kood</string>
<string name="TotpCodeEntryScreen__code">Kood</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Valmis</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Valmis</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Autentimise äpp</string>
<string name="TotpAppListScreen__authenticator_app">Autentimise äpp</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Seadista autentimise äpp ühekordsete kinnituskoodide loomiseks</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Seadista autentimise äpp ühekordsete kinnituskoodide loomiseks</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Rohkem teavet</string>
<string name="TotpAppListScreen__learn_more">Rohkem teavet</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Lisa autentimise äpp</string>
<string name="TotpAppListScreen__add_authenticator_app">Lisa autentimise äpp</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Autentimise äpid</string>
<string name="TotpAppListScreen__authenticator_apps">Autentimise äpid</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Ühtegi autentimise äppi ei ole</string>
<string name="TotpAppListScreen__no_authenticator_apps">Ühtegi autentimise äppi ei ole</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" lisatud</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" lisatud</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Ava autentimise äpi valikud</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Ava autentimise äpi valikud</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Nimeta ümber</string>
<string name="TotpAppListScreen__rename">Nimeta ümber</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Eemalda</string>
<string name="TotpAppListScreen__remove">Eemalda</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Kas eemaldada autentimise äpp?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Kas eemaldada autentimise äpp?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">Selle autentimise meetodi eemaldamiseks on vaja 6-kohalist koodi su autentimise äpist.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">Selle autentimise meetodi eemaldamiseks on vaja 6-kohalist koodi su autentimise äpist.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Autentimise äppi ei saa lisada</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Autentimise äppi ei saa lisada</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Sa ei saa lisada rohkem kui %1$d autentimise äppi. Proovi enne üks eemaldada.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Sa ei saa lisada rohkem kui %1$d autentimise äppi. Proovi enne üks eemaldada.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Autentimise äpp on eemaldatud</string>
<string name="TotpAppListScreen__authenticator_app_removed">Autentimise äpp on eemaldatud</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Vali nimi</string>
<string name="TotpNameEntryScreen__choose_a_name">Vali nimi</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Vali selle autentimise äpi jaoks kordumatu nimi.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Vali selle autentimise äpi jaoks kordumatu nimi.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Vali selle autentimise äpi jaoks kordumatu nimi, mis aitab sul seda hiljem leida.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Vali selle autentimise äpi jaoks kordumatu nimi, mis aitab sul seda hiljem leida.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nimi</string>
<string name="TotpNameEntryScreen__name">Nimi</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Edasi</string>
<string name="TotpNameEntryScreen__next">Edasi</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Autentimise äpp on seadistatud</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Autentimise äpp on seadistatud</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Autentimise äpp on ümber nimetatud</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Autentimise äpp on ümber nimetatud</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Informazio gehiago</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Jarraitu urrats hauek autentifikatzeko aplikazioan konfiguratzeko.</string>
<string name="TotpSetupScreen__follow_these_steps">Jarraitu urrats hauek autentifikatzeko aplikazioan konfiguratzeko.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Informazio gehiago</string>
<string name="TotpSetupScreen__learn_more">Informazio gehiago</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">1. urratsa</string>
<string name="TotpSetupScreen__step_1">1. urratsa</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instalatu autentifikatzeko aplikazio fidagarri bat zure gailuan.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instalatu autentifikatzeko aplikazio fidagarri bat zure gailuan.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">2. urratsa</string>
<string name="TotpSetupScreen__step_2">2. urratsa</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Ireki autentifikatzeko aplikazioa beheko botoia sakatuz Signal-eko kontua gehitzeko.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Ireki autentifikatzeko aplikazioa beheko botoia sakatuz Signal-eko kontua gehitzeko.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Ireki</string>
<string name="TotpSetupScreen__open">Ireki</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Edo gako hau kopia dezakezu eskuz konfiguratzeko.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Edo gako hau kopia dezakezu eskuz konfiguratzeko.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopiatu</string>
<string name="TotpSetupScreen__copy">Kopiatu</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Arbelera kopiatuta</string>
<string name="TotpSetupScreen__copied_to_clipboard">Arbelera kopiatuta</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Ez da autentifikatzeko aplikaziorik aurkitu</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Ez da autentifikatzeko aplikaziorik aurkitu</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">3. urratsa</string>
<string name="TotpSetupScreen__step_3">3. urratsa</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopiatu sortu den kodea eta itzuli hona jarraitzeko.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopiatu sortu den kodea eta itzuli hona jarraitzeko.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Jarraitu</string>
<string name="TotpSetupScreen__continue">Jarraitu</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Kendu</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Idatzi kodea</string>
<string name="TotpCodeEntryScreen__enter_your_code">Idatzi kodea</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Idatzi 6 digituko kodea autentifikatzeko aplikaziotik.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Idatzi 6 digituko kodea autentifikatzeko aplikaziotik.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kodea</string>
<string name="TotpCodeEntryScreen__code">Kodea</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Eginda</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Eginda</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Autentifikatzeko aplikazioa</string>
<string name="TotpAppListScreen__authenticator_app">Autentifikatzeko aplikazioa</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Informazio gehiago</string>
<string name="TotpAppListScreen__learn_more">Informazio gehiago</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" gehitua</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" gehitua</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Rename</string>
<string name="TotpAppListScreen__rename">Rename</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Kendu</string>
<string name="TotpAppListScreen__remove">Kendu</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Choose a name</string>
<string name="TotpNameEntryScreen__choose_a_name">Choose a name</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Name</string>
<string name="TotpNameEntryScreen__name">Name</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Hurrengoa</string>
<string name="TotpNameEntryScreen__next">Hurrengoa</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">اطلاعات بیشتر</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">راه‌اندازی برنامه احراز هویت</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">راه‌اندازی برنامه احراز هویت</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">برای راه‌اندازی برنامه احراز هویت خود، این مراحل را دنبال کنید.</string>
<string name="TotpSetupScreen__follow_these_steps">برای راه‌اندازی برنامه احراز هویت خود، این مراحل را دنبال کنید.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">اطلاعات بیشتر</string>
<string name="TotpSetupScreen__learn_more">اطلاعات بیشتر</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">مرحله ۱</string>
<string name="TotpSetupScreen__step_1">مرحله ۱</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">یک برنامه احراز هویت معتبر را روی دستگاهتان نصب کنید.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">یک برنامه احراز هویت معتبر را روی دستگاهتان نصب کنید.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">مرحله ۲</string>
<string name="TotpSetupScreen__step_2">مرحله ۲</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">با ضربه زدن روی دکمه زیر، برنامه احراز هویت را باز کنید تا حساب سیگنال خود را اضافه کنید.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">با ضربه زدن روی دکمه زیر، برنامه احراز هویت را باز کنید تا حساب سیگنال خود را اضافه کنید.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">باز کردن</string>
<string name="TotpSetupScreen__open">باز کردن</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">یا می‌توانید این رمز را کپی کنید تا آن را به‌صورت دستی راه‌اندازی کنید.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">یا می‌توانید این رمز را کپی کنید تا آن را به‌صورت دستی راه‌اندازی کنید.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">کپی</string>
<string name="TotpSetupScreen__copy">کپی</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">در کلیپ‌بورد کپی شد</string>
<string name="TotpSetupScreen__copied_to_clipboard">در کلیپ‌بورد کپی شد</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">هیچ برنامه احراز هویتی پیدا نشد</string>
<string name="TotpSetupScreen__no_authenticator_app_found">هیچ برنامه احراز هویتی پیدا نشد</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">مرحله ۳</string>
<string name="TotpSetupScreen__step_3">مرحله ۳</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">کد تولیدشده را کپی کنید و برای ادامه به اینجا برگردید.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">کد تولیدشده را کپی کنید و برای ادامه به اینجا برگردید.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">ادامه</string>
<string name="TotpSetupScreen__continue">ادامه</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">حذف</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">کد خود را وارد کنید</string>
<string name="TotpCodeEntryScreen__enter_your_code">کد خود را وارد کنید</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">کد ۶ رقمی را از برنامه احراز هویت خود وارد کنید.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">کد ۶ رقمی را از برنامه احراز هویت خود وارد کنید.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">کد</string>
<string name="TotpCodeEntryScreen__code">کد</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">انجام شد</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">انجام شد</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">برنامه احراز هویت</string>
<string name="TotpAppListScreen__authenticator_app">برنامه احراز هویت</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">یک برنامه احراز هویت برای تولید کدهای تأیید یکبارمصرف راه‌اندازی کنید</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">یک برنامه احراز هویت برای تولید کدهای تأیید یکبارمصرف راه‌اندازی کنید</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">اطلاعات بیشتر</string>
<string name="TotpAppListScreen__learn_more">اطلاعات بیشتر</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">افزودن برنامه احراز هویت</string>
<string name="TotpAppListScreen__add_authenticator_app">افزودن برنامه احراز هویت</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">برنامه‌های احراز هویت</string>
<string name="TotpAppListScreen__authenticator_apps">برنامه‌های احراز هویت</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">هیچ برنامه احراز هویتی وجود ندارد</string>
<string name="TotpAppListScreen__no_authenticator_apps">هیچ برنامه احراز هویتی وجود ندارد</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">«%1$s» اضافه شد</string>
<string name="TotpAppListScreen__added_s">«%1$s» اضافه شد</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">باز کردن گزینه‌های برنامه احراز هویت</string>
<string name="TotpAppListScreen__open_authenticator_app_options">باز کردن گزینه‌های برنامه احراز هویت</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">تغییر نام</string>
<string name="TotpAppListScreen__rename">تغییر نام</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">حذف</string>
<string name="TotpAppListScreen__remove">حذف</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">برنامه احراز هویت حذف شود؟</string>
<string name="TotpAppListScreen__remove_authenticator_app">برنامه احراز هویت حذف شود؟</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">برای حذف این روش احراز هویت، کد ۶ رقمی از برنامه احراز هویت شما مورد نیاز است.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">برای حذف این روش احراز هویت، کد ۶ رقمی از برنامه احراز هویت شما مورد نیاز است.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">افزودن برنامه احراز هویت امکان‌پذیر نیست</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">افزودن برنامه احراز هویت امکان‌پذیر نیست</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">نمی‌توانید بیش از %1$d برنامه احراز هویت اضافه کنید. ابتدا یکی را حذف کنید.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">نمی‌توانید بیش از %1$d برنامه احراز هویت اضافه کنید. ابتدا یکی را حذف کنید.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">برنامه احراز هویت حذف شد</string>
<string name="TotpAppListScreen__authenticator_app_removed">برنامه احراز هویت حذف شد</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">انتخاب یک نام</string>
<string name="TotpNameEntryScreen__choose_a_name">انتخاب یک نام</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">یک نام منحصربه‌فرد برای این برنامه احراز هویت انتخاب کنید.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">یک نام منحصربه‌فرد برای این برنامه احراز هویت انتخاب کنید.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">یک نام منحصربه‌فرد برای این برنامه احراز هویت انتخاب کنید تا بعداً بتوانید آن را شناسایی کنید.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">یک نام منحصربه‌فرد برای این برنامه احراز هویت انتخاب کنید تا بعداً بتوانید آن را شناسایی کنید.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">نام</string>
<string name="TotpNameEntryScreen__name">نام</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">بعدی</string>
<string name="TotpNameEntryScreen__next">بعدی</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">راه‌اندازی برنامه احراز هویت</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">راه‌اندازی برنامه احراز هویت</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">برنامه احراز هویت تغییر نام داد</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">برنامه احراز هویت تغییر نام داد</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Lue lisää</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Seuraa näitä ohjeita autentikointisovelluksen määrittämiseksi:</string>
<string name="TotpSetupScreen__follow_these_steps">Seuraa näitä ohjeita autentikointisovelluksen määrittämiseksi:</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Lue lisää</string>
<string name="TotpSetupScreen__learn_more">Lue lisää</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Vaihe 1</string>
<string name="TotpSetupScreen__step_1">Vaihe 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Asenna laitteelle luotettu autentikointisovellus.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Asenna laitteelle luotettu autentikointisovellus.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Vaihe 2</string>
<string name="TotpSetupScreen__step_2">Vaihe 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Avaa autentikointisovellus ja lisää se Signal-tilliisi napauttamalla alla olevaa painiketta.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Avaa autentikointisovellus ja lisää se Signal-tilliisi napauttamalla alla olevaa painiketta.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Avaa</string>
<string name="TotpSetupScreen__open">Avaa</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Voit myös kopioida avaimen ja määrittää sovelluksen käsin.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Voit myös kopioida avaimen ja määrittää sovelluksen käsin.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopioi</string>
<string name="TotpSetupScreen__copy">Kopioi</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Kopioitu leikepöydälle</string>
<string name="TotpSetupScreen__copied_to_clipboard">Kopioitu leikepöydälle</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Autentikointisovellusta ei löytynyt</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Autentikointisovellusta ei löytynyt</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Vaihe 3</string>
<string name="TotpSetupScreen__step_3">Vaihe 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopioi sovelluksen luoma koodi ja palaa tänne jatkaaksesi.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopioi sovelluksen luoma koodi ja palaa tänne jatkaaksesi.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Jatka</string>
<string name="TotpSetupScreen__continue">Jatka</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Poista</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Anna koodi</string>
<string name="TotpCodeEntryScreen__enter_your_code">Anna koodi</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Anna autentikointisovelluksen antama kuusinumeroinen koodi.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Anna autentikointisovelluksen antama kuusinumeroinen koodi.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Koodi</string>
<string name="TotpCodeEntryScreen__code">Koodi</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Valmis</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Valmis</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Autentikointisovellus</string>
<string name="TotpAppListScreen__authenticator_app">Autentikointisovellus</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Lue lisää</string>
<string name="TotpAppListScreen__learn_more">Lue lisää</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Käyttäjä %1$s lisätty</string>
<string name="TotpAppListScreen__added_s">Käyttäjä %1$s lisätty</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Nimeä uudelleen</string>
<string name="TotpAppListScreen__rename">Nimeä uudelleen</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Poista</string>
<string name="TotpAppListScreen__remove">Poista</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Valitse nimi</string>
<string name="TotpNameEntryScreen__choose_a_name">Valitse nimi</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nimi</string>
<string name="TotpNameEntryScreen__name">Nimi</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Seuraava</string>
<string name="TotpNameEntryScreen__next">Seuraava</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">En savoir plus</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Suivez les étapes ci-dessous pour configurer votre appli d\'authentification.</string>
<string name="TotpSetupScreen__follow_these_steps">Suivez les étapes ci-dessous pour configurer votre appli d\'authentification.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">En savoir plus</string>
<string name="TotpSetupScreen__learn_more">En savoir plus</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Étape 1</string>
<string name="TotpSetupScreen__step_1">Étape 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Installez une appli d\'authentification fiable sur votre appareil.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Installez une appli d\'authentification fiable sur votre appareil.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Étape 2</string>
<string name="TotpSetupScreen__step_2">Étape 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Appuyez sur le bouton ci-dessous pour ouvrir l\'appli d\'authentification et y ajouter votre compte Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Appuyez sur le bouton ci-dessous pour ouvrir l\'appli d\'authentification et y ajouter votre compte Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Ouvrir</string>
<string name="TotpSetupScreen__open">Ouvrir</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Vous pouvez aussi copier cette clé si vous préférez configurer l\'appli manuellement.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Vous pouvez aussi copier cette clé si vous préférez configurer l\'appli manuellement.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Copier</string>
<string name="TotpSetupScreen__copy">Copier</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Copié dans le presse-papiers</string>
<string name="TotpSetupScreen__copied_to_clipboard">Copié dans le presse-papiers</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Aucune appli d\'authentification n\'est disponible</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Aucune appli d\'authentification n\'est disponible</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Étape 3</string>
<string name="TotpSetupScreen__step_3">Étape 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Copiez le code généré par l\'appli d\'authentification et revenez à cet écran pour continuer.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Copiez le code généré par l\'appli d\'authentification et revenez à cet écran pour continuer.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Continuer</string>
<string name="TotpSetupScreen__continue">Continuer</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Retirer</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Saisissez votre code</string>
<string name="TotpCodeEntryScreen__enter_your_code">Saisissez votre code</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Saisissez le code à 6 chiffres généré par votre appli d\'authentification.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Saisissez le code à 6 chiffres généré par votre appli d\'authentification.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Code</string>
<string name="TotpCodeEntryScreen__code">Code</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">OK</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">OK</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Appli d\'authentification</string>
<string name="TotpAppListScreen__authenticator_app">Appli d\'authentification</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">En savoir plus</string>
<string name="TotpAppListScreen__learn_more">En savoir plus</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">%1$s a été ajouté.</string>
<string name="TotpAppListScreen__added_s">%1$s a été ajouté.</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Renommer</string>
<string name="TotpAppListScreen__rename">Renommer</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Retirer</string>
<string name="TotpAppListScreen__remove">Retirer</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Choisissez un nom</string>
<string name="TotpNameEntryScreen__choose_a_name">Choisissez un nom</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nom</string>
<string name="TotpNameEntryScreen__name">Nom</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Suivant</string>
<string name="TotpNameEntryScreen__next">Suivant</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -89,37 +89,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Tuilleadh faisnéise</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Lean na céimeanna seo a leanas le d\'aip fíordheimhnitheora a chumrú.</string>
<string name="TotpSetupScreen__follow_these_steps">Lean na céimeanna seo a leanas le d\'aip fíordheimhnitheora a chumrú.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Tuilleadh faisnéise</string>
<string name="TotpSetupScreen__learn_more">Tuilleadh faisnéise</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Céim 1</string>
<string name="TotpSetupScreen__step_1">Céim 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Suiteáil aip fíordheimhnitheora iontaofa ar do ghléas.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Suiteáil aip fíordheimhnitheora iontaofa ar do ghléas.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Céim 2</string>
<string name="TotpSetupScreen__step_2">Céim 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Oscail d\'aip fíordheimhnitheora tríd an gcnaipe thíos a thapáil lena cur le do chuntas Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Oscail d\'aip fíordheimhnitheora tríd an gcnaipe thíos a thapáil lena cur le do chuntas Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Oscail</string>
<string name="TotpSetupScreen__open">Oscail</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Nó is féidir leat an eochair seo a chóipeáil lena chumrú de láimh.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Nó is féidir leat an eochair seo a chóipeáil lena chumrú de láimh.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Cóipeáil</string>
<string name="TotpSetupScreen__copy">Cóipeáil</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Cóipeáilte chuig an ngearrthaisce</string>
<string name="TotpSetupScreen__copied_to_clipboard">Cóipeáilte chuig an ngearrthaisce</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Níor aimsíodh aip fíordheimhnitheora</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Níor aimsíodh aip fíordheimhnitheora</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Céim 3</string>
<string name="TotpSetupScreen__step_3">Céim 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Cóipeáil an cód a gineadh agus fill anseo le leanúint leis.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Cóipeáil an cód a gineadh agus fill anseo le leanúint leis.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Lean ar aghaidh</string>
<string name="TotpSetupScreen__continue">Lean ar aghaidh</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -149,60 +149,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Bain é</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Cuir isteach do chód</string>
<string name="TotpCodeEntryScreen__enter_your_code">Cuir isteach do chód</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Cuir isteach an cód 6 dhigit ó d\'aip fíordheimhnitheora.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Cuir isteach an cód 6 dhigit ó d\'aip fíordheimhnitheora.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Cód</string>
<string name="TotpCodeEntryScreen__code">Cód</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Déanta</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Déanta</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Aip fíordheimhnitheora</string>
<string name="TotpAppListScreen__authenticator_app">Aip fíordheimhnitheora</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Tuilleadh faisnéise</string>
<string name="TotpAppListScreen__learn_more">Tuilleadh faisnéise</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">%1$s curtha leis</string>
<string name="TotpAppListScreen__added_s">%1$s curtha leis</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Athainmnigh</string>
<string name="TotpAppListScreen__rename">Athainmnigh</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Bain é</string>
<string name="TotpAppListScreen__remove">Bain é</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Roghnaigh ainm</string>
<string name="TotpNameEntryScreen__choose_a_name">Roghnaigh ainm</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Ainm</string>
<string name="TotpNameEntryScreen__name">Ainm</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Ar aghaidh</string>
<string name="TotpNameEntryScreen__next">Ar aghaidh</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Máis información</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Configura a aplicación de autenticación</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Configura a aplicación de autenticación</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Sigue estes pasos para configurar a aplicación de autenticación.</string>
<string name="TotpSetupScreen__follow_these_steps">Sigue estes pasos para configurar a aplicación de autenticación.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Máis información</string>
<string name="TotpSetupScreen__learn_more">Máis información</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Primeiro paso</string>
<string name="TotpSetupScreen__step_1">Primeiro paso</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instala unha aplicación de autenticación de confianza no teu dispositivo.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instala unha aplicación de autenticación de confianza no teu dispositivo.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Segundo paso</string>
<string name="TotpSetupScreen__step_2">Segundo paso</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Abre a aplicación de autenticación premendo o botón de máis abaixo para engadir a túa conta de Signal.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Abre a aplicación de autenticación premendo o botón de máis abaixo para engadir a túa conta de Signal.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Abrir</string>
<string name="TotpSetupScreen__open">Abrir</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Ou podes copiar esta clave para configurala de forma manual.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Ou podes copiar esta clave para configurala de forma manual.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Copiar</string>
<string name="TotpSetupScreen__copy">Copiar</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Copiado no portapapeis</string>
<string name="TotpSetupScreen__copied_to_clipboard">Copiado no portapapeis</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Non se atopou unha aplicación de autenticación</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Non se atopou unha aplicación de autenticación</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Terceiro paso</string>
<string name="TotpSetupScreen__step_3">Terceiro paso</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Copia o código que se xerou e volve aquí para continuar.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Copia o código que se xerou e volve aquí para continuar.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Continuar</string>
<string name="TotpSetupScreen__continue">Continuar</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Eliminar</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Escribe o teu código</string>
<string name="TotpCodeEntryScreen__enter_your_code">Escribe o teu código</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Introduce o código de 6 díxitos da aplicación de autenticación.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Introduce o código de 6 díxitos da aplicación de autenticación.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Código</string>
<string name="TotpCodeEntryScreen__code">Código</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Feito</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Feito</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Aplicación de autenticación</string>
<string name="TotpAppListScreen__authenticator_app">Aplicación de autenticación</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Configura unha aplicación de autenticación para xerar códigos de verificación dun só uso</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Configura unha aplicación de autenticación para xerar códigos de verificación dun só uso</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Máis información</string>
<string name="TotpAppListScreen__learn_more">Máis información</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Engadir aplicación de autenticación</string>
<string name="TotpAppListScreen__add_authenticator_app">Engadir aplicación de autenticación</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Aplicacións de autenticación</string>
<string name="TotpAppListScreen__authenticator_apps">Aplicacións de autenticación</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Non se atoparon aplicacións de autenticación</string>
<string name="TotpAppListScreen__no_authenticator_apps">Non se atoparon aplicacións de autenticación</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Engadido «%1$s»</string>
<string name="TotpAppListScreen__added_s">Engadido «%1$s»</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Abrir opcións da aplicación de autenticación</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Abrir opcións da aplicación de autenticación</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Renomear</string>
<string name="TotpAppListScreen__rename">Renomear</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Eliminar</string>
<string name="TotpAppListScreen__remove">Eliminar</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Eliminar aplicación de autenticación?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Eliminar aplicación de autenticación?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">Para eliminar este método de autenticación necesitas o código de 6 díxitos da aplicación de autenticación.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">Para eliminar este método de autenticación necesitas o código de 6 díxitos da aplicación de autenticación.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Non se pode engadir a aplicación de autenticación</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Non se pode engadir a aplicación de autenticación</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Non podes engadir máis de %1$d aplicacións de autenticación. Tes que eliminar antes unha.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Non podes engadir máis de %1$d aplicacións de autenticación. Tes que eliminar antes unha.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Aplicación de autenticación eliminada</string>
<string name="TotpAppListScreen__authenticator_app_removed">Aplicación de autenticación eliminada</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Escolle un nome</string>
<string name="TotpNameEntryScreen__choose_a_name">Escolle un nome</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Ponlle un nome único a esta aplicación de autenticación.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Ponlle un nome único a esta aplicación de autenticación.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Escolle un nome único para esta aplicación de autenticación que che axude a identificala máis adiante.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Escolle un nome único para esta aplicación de autenticación que che axude a identificala máis adiante.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nome</string>
<string name="TotpNameEntryScreen__name">Nome</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Seguinte</string>
<string name="TotpNameEntryScreen__next">Seguinte</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Configuración da aplicación de autenticación</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Configuración da aplicación de autenticación</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Cambiouse o nome da aplicación de autenticación</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Cambiouse o nome da aplicación de autenticación</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">વધુ જાણો</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">તમારી પ્રમાણીકરણ ઍપ સેટ કરો</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">તમારી પ્રમાણીકરણ ઍપ સેટ કરો</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">તમારી પ્રમાણીકરણ ઍપ સેટ કરવા આ પગલાં અનુસરો.</string>
<string name="TotpSetupScreen__follow_these_steps">તમારી પ્રમાણીકરણ ઍપ સેટ કરવા આ પગલાં અનુસરો.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">વધુ જાણો</string>
<string name="TotpSetupScreen__learn_more">વધુ જાણો</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">પગલું 1</string>
<string name="TotpSetupScreen__step_1">પગલું 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">તમારા ડિવાઇસ પર વિશ્વસનીય પ્રમાણીકરણ ઍપ ઇન્સ્ટોલ કરો.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">તમારા ડિવાઇસ પર વિશ્વસનીય પ્રમાણીકરણ ઍપ ઇન્સ્ટોલ કરો.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">પગલું 2</string>
<string name="TotpSetupScreen__step_2">પગલું 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">તમારું Signal એકાઉન્ટ ઉમેરવા માટે નીચેના બટન પર ટેપ કરીને તમારી પ્રમાણીકરણ ઍપ ખોલો.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">તમારું Signal એકાઉન્ટ ઉમેરવા માટે નીચેના બટન પર ટેપ કરીને તમારી પ્રમાણીકરણ ઍપ ખોલો.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">ખોલો</string>
<string name="TotpSetupScreen__open">ખોલો</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">અથવા તમે જાતે સેટ અપ કરવા આ કી કૉપિ કરી શકો છો.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">અથવા તમે જાતે સેટ અપ કરવા આ કી કૉપિ કરી શકો છો.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">કૉપિ</string>
<string name="TotpSetupScreen__copy">કૉપિ</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">ક્લિપબોર્ડ પર કૉપિ કર્યું</string>
<string name="TotpSetupScreen__copied_to_clipboard">ક્લિપબોર્ડ પર કૉપિ કર્યું</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">કોઈ પ્રમાણીકરણ ઍપ મળી નહીં</string>
<string name="TotpSetupScreen__no_authenticator_app_found">કોઈ પ્રમાણીકરણ ઍપ મળી નહીં</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">પગલું 3</string>
<string name="TotpSetupScreen__step_3">પગલું 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">જનરેટ થયેલો કોડ કૉપિ કરો અને ચાલુ રાખવા અહીં પાછા આવો.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">જનરેટ થયેલો કોડ કૉપિ કરો અને ચાલુ રાખવા અહીં પાછા આવો.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">ચાલુ રાખો</string>
<string name="TotpSetupScreen__continue">ચાલુ રાખો</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">દૂર કરો</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">તમારો કોડ દાખલ કરો</string>
<string name="TotpCodeEntryScreen__enter_your_code">તમારો કોડ દાખલ કરો</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">તમારી પ્રમાણીકરણ ઍપમાંથી 6-અંકનો કોડ દાખલ કરો.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">તમારી પ્રમાણીકરણ ઍપમાંથી 6-અંકનો કોડ દાખલ કરો.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">કોડ</string>
<string name="TotpCodeEntryScreen__code">કોડ</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">થઈ ગયું</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">થઈ ગયું</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">પ્રમાણીકરણ ઍપ</string>
<string name="TotpAppListScreen__authenticator_app">પ્રમાણીકરણ ઍપ</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">વન-ટાઇમ વેરિફિકેશન કોડ જનરેટ કરવા પ્રમાણીકરણ ઍપને સેટઅપ કરો</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">વન-ટાઇમ વેરિફિકેશન કોડ જનરેટ કરવા પ્રમાણીકરણ ઍપને સેટઅપ કરો</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">વધુ જાણો</string>
<string name="TotpAppListScreen__learn_more">વધુ જાણો</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">પ્રમાણીકરણ ઍપ ઉમેરો</string>
<string name="TotpAppListScreen__add_authenticator_app">પ્રમાણીકરણ ઍપ ઉમેરો</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">પ્રમાણીકરણ ઍપ</string>
<string name="TotpAppListScreen__authenticator_apps">પ્રમાણીકરણ ઍપ</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">કોઈ પ્રમાણીકરણ ઍપ નથી</string>
<string name="TotpAppListScreen__no_authenticator_apps">કોઈ પ્રમાણીકરણ ઍપ નથી</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" ઉમેર્યા</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" ઉમેર્યા</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">પ્રમાણીકરણ ઍપ વિકલ્પો ખોલો</string>
<string name="TotpAppListScreen__open_authenticator_app_options">પ્રમાણીકરણ ઍપ વિકલ્પો ખોલો</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">નામ બદલો</string>
<string name="TotpAppListScreen__rename">નામ બદલો</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">દૂર કરો</string>
<string name="TotpAppListScreen__remove">દૂર કરો</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">પ્રમાણીકરણ ઍપ દૂર કરવી છે?</string>
<string name="TotpAppListScreen__remove_authenticator_app">પ્રમાણીકરણ ઍપ દૂર કરવી છે?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">આ પ્રમાણીકરણ પદ્ધતિને દૂર કરવા માટે તમારી પ્રમાણીકરણ ઍપમાંથી 6-અંકનો કોડ જરૂરી છે.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">આ પ્રમાણીકરણ પદ્ધતિને દૂર કરવા માટે તમારી પ્રમાણીકરણ ઍપમાંથી 6-અંકનો કોડ જરૂરી છે.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">પ્રમાણીકરણ ઍપ ઉમેરી શકતા નથી</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">પ્રમાણીકરણ ઍપ ઉમેરી શકતા નથી</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">તમે %1$dથી વધુ પ્રમાણીકરણ ઍપ ઉમેરી શકતા નથી. પહેલા એકને દૂર કરી જુઓ.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">તમે %1$dથી વધુ પ્રમાણીકરણ ઍપ ઉમેરી શકતા નથી. પહેલા એકને દૂર કરી જુઓ.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">પ્રમાણીકરણ ઍપ દૂર કરી</string>
<string name="TotpAppListScreen__authenticator_app_removed">પ્રમાણીકરણ ઍપ દૂર કરી</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">નામ પસંદ કરો</string>
<string name="TotpNameEntryScreen__choose_a_name">નામ પસંદ કરો</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">આ પ્રમાણીકરણ ઍપ માટે એક વિશિષ્ટ નામ પસંદ કરો.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">આ પ્રમાણીકરણ ઍપ માટે એક વિશિષ્ટ નામ પસંદ કરો.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">આ પ્રમાણીકરણ ઍપ માટે એક વિશિષ્ટ નામ પસંદ કરો જેથી તમે તેને પછીથી ઓળખી શકો.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">આ પ્રમાણીકરણ ઍપ માટે એક વિશિષ્ટ નામ પસંદ કરો જેથી તમે તેને પછીથી ઓળખી શકો.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">નામ</string>
<string name="TotpNameEntryScreen__name">નામ</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">આગળ</string>
<string name="TotpNameEntryScreen__next">આગળ</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">પ્રમાણીકરણ ઍપ સેટ અપ</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">પ્રમાણીકરણ ઍપ સેટ અપ</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">પ્રમાણીકરણ ઍપનું નામ બદલ્યું</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">પ્રમાણીકરણ ઍપનું નામ બદલ્યું</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">और जानें</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">अपना ऑथेंटिकेटर ऐप सेटअप करें</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">अपना ऑथेंटिकेटर ऐप सेटअप करें</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">अपना ऑथेंटिकेटर ऐप सेटअप करने के लिए इन चरणों का पालन करें।</string>
<string name="TotpSetupScreen__follow_these_steps">अपना ऑथेंटिकेटर ऐप सेटअप करने के लिए इन चरणों का पालन करें।</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">और जानें</string>
<string name="TotpSetupScreen__learn_more">और जानें</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">चरण 1</string>
<string name="TotpSetupScreen__step_1">चरण 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">अपने डिवाइस में कोई भरोसेमंद ऑथेंटिकेटर ऐप इंस्टॉल करें।</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">अपने डिवाइस में कोई भरोसेमंद ऑथेंटिकेटर ऐप इंस्टॉल करें।</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">चरण 2</string>
<string name="TotpSetupScreen__step_2">चरण 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">अपना Signal अकाउंट जोड़ने के लिए नीचे दिए गए बटन पर टैप करके अपना ऑथेंटिकेटर ऐप खोलें।</string>
<string name="TotpSetupScreen__open_your_authenticator_app">अपना Signal अकाउंट जोड़ने के लिए नीचे दिए गए बटन पर टैप करके अपना ऑथेंटिकेटर ऐप खोलें।</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">खोलें</string>
<string name="TotpSetupScreen__open">खोलें</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">या फिर इसे मैन्युअल तरीके से सेटअप करने के लिए यह \'की\' कॉपी करें।</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">या फिर इसे मैन्युअल तरीके से सेटअप करने के लिए यह \'की\' कॉपी करें।</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">कॉपी करें</string>
<string name="TotpSetupScreen__copy">कॉपी करें</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">क्लिपबोर्ड पर कॉपी किया गया</string>
<string name="TotpSetupScreen__copied_to_clipboard">क्लिपबोर्ड पर कॉपी किया गया</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">कोई ऑथेंटिकेटर ऐप नहीं मिला</string>
<string name="TotpSetupScreen__no_authenticator_app_found">कोई ऑथेंटिकेटर ऐप नहीं मिला</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">चरण 3</string>
<string name="TotpSetupScreen__step_3">चरण 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">जनरेट हुआ कोड कॉपी करें और यहां वापस आकर जारी रखें।</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">जनरेट हुआ कोड कॉपी करें और यहां वापस आकर जारी रखें।</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">जारी रखें</string>
<string name="TotpSetupScreen__continue">जारी रखें</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">हटाएं</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">अपना कोड डालें</string>
<string name="TotpCodeEntryScreen__enter_your_code">अपना कोड डालें</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">अपने ऑथेंटिकेटर ऐप में दिख रहा 6-अंकों वाला कोड डालें।</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">अपने ऑथेंटिकेटर ऐप में दिख रहा 6-अंकों वाला कोड डालें।</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">कोड</string>
<string name="TotpCodeEntryScreen__code">कोड</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">हो गया</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">हो गया</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">ऑथेंटिकेटर ऐप</string>
<string name="TotpAppListScreen__authenticator_app">ऑथेंटिकेटर ऐप</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">एक बार इस्तेमाल होने वाला वेरिफ़िकेशन कोड जनरेट करने के लिए, ऑथेंटिकेटर ऐप सेटअप करें</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">एक बार इस्तेमाल होने वाला वेरिफ़िकेशन कोड जनरेट करने के लिए, ऑथेंटिकेटर ऐप सेटअप करें</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">और जानें</string>
<string name="TotpAppListScreen__learn_more">और जानें</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">ऑथेंटिकेटर ऐप जोड़ें</string>
<string name="TotpAppListScreen__add_authenticator_app">ऑथेंटिकेटर ऐप जोड़ें</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">ऑथेंटिकेटर ऐप</string>
<string name="TotpAppListScreen__authenticator_apps">ऑथेंटिकेटर ऐप</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">कोई ऑथेंटिकेटर ऐप मौजूद नहीं है</string>
<string name="TotpAppListScreen__no_authenticator_apps">कोई ऑथेंटिकेटर ऐप मौजूद नहीं है</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\'%1$s\' को जोड़ा गया</string>
<string name="TotpAppListScreen__added_s">\'%1$s\' को जोड़ा गया</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">ऑथेंटिकेटर ऐप के विकल्प खोलें</string>
<string name="TotpAppListScreen__open_authenticator_app_options">ऑथेंटिकेटर ऐप के विकल्प खोलें</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">नाम बदलें</string>
<string name="TotpAppListScreen__rename">नाम बदलें</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">हटाएं</string>
<string name="TotpAppListScreen__remove">हटाएं</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">ऑथेंटिकेटर ऐप हटाना है?</string>
<string name="TotpAppListScreen__remove_authenticator_app">ऑथेंटिकेटर ऐप हटाना है?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">ऑथेंटिकेशन के इस तरीके को हटाने के लिए अपने ऑथेंटिकेटर ऐप में दिख रहा 6-अंकों वाला कोड डालें।</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">ऑथेंटिकेशन के इस तरीके को हटाने के लिए अपने ऑथेंटिकेटर ऐप में दिख रहा 6-अंकों वाला कोड डालें।</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">ऑथेंटिकेटर ऐप जोड़ना संभव नही है</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">ऑथेंटिकेटर ऐप जोड़ना संभव नही है</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">%1$d से ज़्यादा ऑथेंटिकेटर ऐप नहीं जोड़े जा सकते। पहले एक को हटाकर देखें।</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">%1$d से ज़्यादा ऑथेंटिकेटर ऐप नहीं जोड़े जा सकते। पहले एक को हटाकर देखें।</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">ऑथेंटिकेटर ऐप हटाया गया</string>
<string name="TotpAppListScreen__authenticator_app_removed">ऑथेंटिकेटर ऐप हटाया गया</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">कोई नाम चुनें</string>
<string name="TotpNameEntryScreen__choose_a_name">कोई नाम चुनें</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">इस ऑथेंटिकेटर ऐप के लिए एक यूनीक नाम चुनें।</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">इस ऑथेंटिकेटर ऐप के लिए एक यूनीक नाम चुनें।</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">इस ऑथेंटिकेटर ऐप के लिए एक यूनीक नाम चुनें, ताकि आप बाद में इसे पहचान सकें।</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">इस ऑथेंटिकेटर ऐप के लिए एक यूनीक नाम चुनें, ताकि आप बाद में इसे पहचान सकें।</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">नाम</string>
<string name="TotpNameEntryScreen__name">नाम</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">अगला</string>
<string name="TotpNameEntryScreen__next">अगला</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">ऑथेंटिकेटर ऐप सेटअप करें</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">ऑथेंटिकेटर ऐप सेटअप करें</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">ऑथेंटिकेटर ऐप का नाम बदला गया</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">ऑथेंटिकेटर ऐप का नाम बदला गया</string>
</resources>
@@ -86,37 +86,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Saznajte više</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Slijedite ove korake za postavljanje aplikacije za provjeru autentičnosti.</string>
<string name="TotpSetupScreen__follow_these_steps">Slijedite ove korake za postavljanje aplikacije za provjeru autentičnosti.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Saznajte više</string>
<string name="TotpSetupScreen__learn_more">Saznajte više</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">1. korak</string>
<string name="TotpSetupScreen__step_1">1. korak</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instalirajte pouzdanu aplikaciju za provjeru autentičnosti na svom uređaju.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instalirajte pouzdanu aplikaciju za provjeru autentičnosti na svom uređaju.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">2. korak</string>
<string name="TotpSetupScreen__step_2">2. korak</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Otvorite aplikaciju za provjeru autentičnosti dodirom na gumb ispod za dodavanje svog Signal računa.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Otvorite aplikaciju za provjeru autentičnosti dodirom na gumb ispod za dodavanje svog Signal računa.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Otvori</string>
<string name="TotpSetupScreen__open">Otvori</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Ili kopirajte ovaj ključ za ručno postavljanje.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Ili kopirajte ovaj ključ za ručno postavljanje.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Kopiraj</string>
<string name="TotpSetupScreen__copy">Kopiraj</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Kopirano u međuspremnik</string>
<string name="TotpSetupScreen__copied_to_clipboard">Kopirano u međuspremnik</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Nije pronađena aplikacija za provjeru autentičnosti</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Nije pronađena aplikacija za provjeru autentičnosti</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">3. korak</string>
<string name="TotpSetupScreen__step_3">3. korak</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Kopirajte generirani kôd i vratite se ovdje za nastavak.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Kopirajte generirani kôd i vratite se ovdje za nastavak.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Nastavi</string>
<string name="TotpSetupScreen__continue">Nastavi</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -146,60 +146,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Ukloni</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Unesite svoj kôd</string>
<string name="TotpCodeEntryScreen__enter_your_code">Unesite svoj kôd</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Unesite šesteroznamenkasti kôd iz aplikacije za provjeru autentičnosti.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Unesite šesteroznamenkasti kôd iz aplikacije za provjeru autentičnosti.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kôd</string>
<string name="TotpCodeEntryScreen__code">Kôd</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Gotovo</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Gotovo</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Aplikacija za provjeru autentičnosti</string>
<string name="TotpAppListScreen__authenticator_app">Aplikacija za provjeru autentičnosti</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Saznajte više</string>
<string name="TotpAppListScreen__learn_more">Saznajte više</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Dodan/a je \"%1$s\"</string>
<string name="TotpAppListScreen__added_s">Dodan/a je \"%1$s\"</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Preimenuj</string>
<string name="TotpAppListScreen__rename">Preimenuj</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Ukloni</string>
<string name="TotpAppListScreen__remove">Ukloni</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Odaberite naziv</string>
<string name="TotpNameEntryScreen__choose_a_name">Odaberite naziv</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Ime</string>
<string name="TotpNameEntryScreen__name">Ime</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Sljedeće</string>
<string name="TotpNameEntryScreen__next">Sljedeće</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Tudj meg többet</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Állítsd be a hitelesítő alkalmazásodat</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Állítsd be a hitelesítő alkalmazásodat</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">A hitelesítő alkalmazás beállításához kövesd az alábbi lépéseket.</string>
<string name="TotpSetupScreen__follow_these_steps">A hitelesítő alkalmazás beállításához kövesd az alábbi lépéseket.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Tudj meg többet</string>
<string name="TotpSetupScreen__learn_more">Tudj meg többet</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">1. lépés</string>
<string name="TotpSetupScreen__step_1">1. lépés</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Telepíts egy megbízható hitelesítő alkalmazást az eszközödre.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Telepíts egy megbízható hitelesítő alkalmazást az eszközödre.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">2. lépés</string>
<string name="TotpSetupScreen__step_2">2. lépés</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">A Signal fiókod hozzáadásához nyisd meg a hitelesítő alkalmazást az alábbi gombra koppintva.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">A Signal fiókod hozzáadásához nyisd meg a hitelesítő alkalmazást az alábbi gombra koppintva.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Megnyitás</string>
<string name="TotpSetupScreen__open">Megnyitás</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Vagy másold ki ezt a kulcsot a manuális beállításhoz.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Vagy másold ki ezt a kulcsot a manuális beállításhoz.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Másolás</string>
<string name="TotpSetupScreen__copy">Másolás</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Vágólapra másolva</string>
<string name="TotpSetupScreen__copied_to_clipboard">Vágólapra másolva</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Nem található hitelesítő alkalmazás</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Nem található hitelesítő alkalmazás</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">3. lépés</string>
<string name="TotpSetupScreen__step_3">3. lépés</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Másold ki a generált kódot, és térj vissza ide a folytatáshoz.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Másold ki a generált kódot, és térj vissza ide a folytatáshoz.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Folytatás</string>
<string name="TotpSetupScreen__continue">Folytatás</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Eltávolítás</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Add meg a kódod</string>
<string name="TotpCodeEntryScreen__enter_your_code">Add meg a kódod</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Add meg a 6 jegyű kódot a hitelesítő alkalmazásból.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Add meg a 6 jegyű kódot a hitelesítő alkalmazásból.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kód</string>
<string name="TotpCodeEntryScreen__code">Kód</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Kész</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Kész</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Hitelesítő alkalmazás</string>
<string name="TotpAppListScreen__authenticator_app">Hitelesítő alkalmazás</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Egyszer használatos ellenőrző kódok generálásához állíts be egy hitelesítő alkalmazást</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Egyszer használatos ellenőrző kódok generálásához állíts be egy hitelesítő alkalmazást</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Tudj meg többet</string>
<string name="TotpAppListScreen__learn_more">Tudj meg többet</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Hitelesítő alkalmazás hozzáadása</string>
<string name="TotpAppListScreen__add_authenticator_app">Hitelesítő alkalmazás hozzáadása</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Hitelesítő alkalmazások</string>
<string name="TotpAppListScreen__authenticator_apps">Hitelesítő alkalmazások</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Nincs hitelesítő alkalmazás</string>
<string name="TotpAppListScreen__no_authenticator_apps">Nincs hitelesítő alkalmazás</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" hozzáadva</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" hozzáadva</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Hitelesítő alkalmazás opciók megnyitása</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Hitelesítő alkalmazás opciók megnyitása</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Átnevezés</string>
<string name="TotpAppListScreen__rename">Átnevezés</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Eltávolítás</string>
<string name="TotpAppListScreen__remove">Eltávolítás</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Hitelesítő alkalmazás eltávolítása?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Hitelesítő alkalmazás eltávolítása?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">A hitelesítési módszer eltávolításához a hitelesítő alkalmazás 6 számjegyű kódjára van szükség.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">A hitelesítési módszer eltávolításához a hitelesítő alkalmazás 6 számjegyű kódjára van szükség.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Nem lehet hitelesítő alkalmazást hozzáadni</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Nem lehet hitelesítő alkalmazást hozzáadni</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Legfeljebb %1$d hitelesítő alkalmazást adhatsz hozzá. Először próbálj egyet eltávolítani.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Legfeljebb %1$d hitelesítő alkalmazást adhatsz hozzá. Először próbálj egyet eltávolítani.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Hitelesítő alkalmazás eltávolítva</string>
<string name="TotpAppListScreen__authenticator_app_removed">Hitelesítő alkalmazás eltávolítva</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Válassz egy nevet</string>
<string name="TotpNameEntryScreen__choose_a_name">Válassz egy nevet</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Válassz egy egyedi nevet ennek a hitelesítő alkalmazásnak.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Válassz egy egyedi nevet ennek a hitelesítő alkalmazásnak.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Válassz egy egyedi nevet ennek a hitelesítő alkalmazásnak, hogy később könnyebben azonosíthasd.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Válassz egy egyedi nevet ennek a hitelesítő alkalmazásnak, hogy később könnyebben azonosíthasd.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Név</string>
<string name="TotpNameEntryScreen__name">Név</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Tovább</string>
<string name="TotpNameEntryScreen__next">Tovább</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Hitelesítő alkalmazás beállítása</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Hitelesítő alkalmazás beállítása</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Hitelesítő alkalmazás átnevezve</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Hitelesítő alkalmazás átnevezve</string>
</resources>
@@ -77,37 +77,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Pelajari selengkapnya</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Siapkan aplikasi autentikator</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Siapkan aplikasi autentikator</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Ikuti langkah berikut untuk menyiapkan aplikasi autentikator.</string>
<string name="TotpSetupScreen__follow_these_steps">Ikuti langkah berikut untuk menyiapkan aplikasi autentikator.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Pelajari selengkapnya</string>
<string name="TotpSetupScreen__learn_more">Pelajari selengkapnya</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Langkah 1</string>
<string name="TotpSetupScreen__step_1">Langkah 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Instal aplikasi autentikator tepercaya di perangkat Anda.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Instal aplikasi autentikator tepercaya di perangkat Anda.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Langkah 2</string>
<string name="TotpSetupScreen__step_2">Langkah 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Buka aplikasi autentikator dengan mengetuk tombol di bawah ini untuk menambahkan akun Signal Anda.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Buka aplikasi autentikator dengan mengetuk tombol di bawah ini untuk menambahkan akun Signal Anda.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Buka</string>
<string name="TotpSetupScreen__open">Buka</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Anda juga dapat menyalin kunci ini untuk menyiapkannya secara manual.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Anda juga dapat menyalin kunci ini untuk menyiapkannya secara manual.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Salin</string>
<string name="TotpSetupScreen__copy">Salin</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Disalin ke papan klip</string>
<string name="TotpSetupScreen__copied_to_clipboard">Disalin ke papan klip</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Tidak ditemukan aplikasi autentikator</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Tidak ditemukan aplikasi autentikator</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Langkah 3</string>
<string name="TotpSetupScreen__step_3">Langkah 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Salin kode yang tersedia, lalu kembali ke sini untuk melanjutkan.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Salin kode yang tersedia, lalu kembali ke sini untuk melanjutkan.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Lanjut</string>
<string name="TotpSetupScreen__continue">Lanjut</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -137,60 +137,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Hapus</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Masukkan kode Anda</string>
<string name="TotpCodeEntryScreen__enter_your_code">Masukkan kode Anda</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Masukkan kode 6 digit dari aplikasi autentikator Anda.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Masukkan kode 6 digit dari aplikasi autentikator Anda.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Kode</string>
<string name="TotpCodeEntryScreen__code">Kode</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Selesai</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Selesai</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">Aplikasi autentikator</string>
<string name="TotpAppListScreen__authenticator_app">Aplikasi autentikator</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Siapkan aplikasi autentikator untuk mendapatkan kode verifikasi sekali pakai</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Siapkan aplikasi autentikator untuk mendapatkan kode verifikasi sekali pakai</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Pelajari selengkapnya</string>
<string name="TotpAppListScreen__learn_more">Pelajari selengkapnya</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Tambahkan aplikasi autentikator</string>
<string name="TotpAppListScreen__add_authenticator_app">Tambahkan aplikasi autentikator</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Aplikasi autentikator</string>
<string name="TotpAppListScreen__authenticator_apps">Aplikasi autentikator</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">Tidak ada aplikasi autentikator</string>
<string name="TotpAppListScreen__no_authenticator_apps">Tidak ada aplikasi autentikator</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Ditambahkan %1$s</string>
<string name="TotpAppListScreen__added_s">Ditambahkan %1$s</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Buka opsi aplikasi autentikator</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Buka opsi aplikasi autentikator</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Ubah nama</string>
<string name="TotpAppListScreen__rename">Ubah nama</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Hapus</string>
<string name="TotpAppListScreen__remove">Hapus</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Hapus aplikasi autentikator?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Hapus aplikasi autentikator?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">Untuk menghapus metode autentikasi ini, diperlukan kode 6 digit dari aplikasi autentikator Anda.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">Untuk menghapus metode autentikasi ini, diperlukan kode 6 digit dari aplikasi autentikator Anda.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Tidak bisa menambahkan aplikasi autentikator</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Tidak bisa menambahkan aplikasi autentikator</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">Anda tidak bisa menambahkan lebih dari %1$d aplikasi autentikator. Coba hapus salah satu terlebih dahulu.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">Anda tidak bisa menambahkan lebih dari %1$d aplikasi autentikator. Coba hapus salah satu terlebih dahulu.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Aplikasi autentikator dihapus</string>
<string name="TotpAppListScreen__authenticator_app_removed">Aplikasi autentikator dihapus</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Pilih nama</string>
<string name="TotpNameEntryScreen__choose_a_name">Pilih nama</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Pilih nama unik untuk aplikasi autentikator ini.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Pilih nama unik untuk aplikasi autentikator ini.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Pilih nama unik untuk aplikasi autentikator ini agar mudah dikenali nanti.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Pilih nama unik untuk aplikasi autentikator ini agar mudah dikenali nanti.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nama</string>
<string name="TotpNameEntryScreen__name">Nama</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Berikutnya</string>
<string name="TotpNameEntryScreen__next">Berikutnya</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Aplikasi autentikator telah disiapkan</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Aplikasi autentikator telah disiapkan</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Nama aplikasi autentikator diganti</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Nama aplikasi autentikator diganti</string>
</resources>
@@ -80,37 +80,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">Scopri di più</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">Set up your authenticator app</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">Segui questi passaggi per impostare l\'app di autenticazione.</string>
<string name="TotpSetupScreen__follow_these_steps">Segui questi passaggi per impostare l\'app di autenticazione.</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">Scopri di più</string>
<string name="TotpSetupScreen__learn_more">Scopri di più</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">Passaggio 1</string>
<string name="TotpSetupScreen__step_1">Passaggio 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">Installa un\'app sicura per l\'autenticazione sul tuo dispositivo.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">Installa un\'app sicura per l\'autenticazione sul tuo dispositivo.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">Passaggio 2</string>
<string name="TotpSetupScreen__step_2">Passaggio 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">Per aggiungere l\'account Signal alla tua app di autenticazione, tocca il pulsante in basso.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">Per aggiungere l\'account Signal alla tua app di autenticazione, tocca il pulsante in basso.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">Apri</string>
<string name="TotpSetupScreen__open">Apri</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">Oppure puoi copiare questa chiave per configurarla manualmente.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">Oppure puoi copiare questa chiave per configurarla manualmente.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">Copia</string>
<string name="TotpSetupScreen__copy">Copia</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">Copiato negli appunti</string>
<string name="TotpSetupScreen__copied_to_clipboard">Copiato negli appunti</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">Nessuna app di autenticazione trovata</string>
<string name="TotpSetupScreen__no_authenticator_app_found">Nessuna app di autenticazione trovata</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">Passaggio 3</string>
<string name="TotpSetupScreen__step_3">Passaggio 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">Copia il codice che viene generato dall\'app e torna qui per continuare.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">Copia il codice che viene generato dall\'app e torna qui per continuare.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">Continua</string>
<string name="TotpSetupScreen__continue">Continua</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -140,60 +140,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">Rimuovi</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">Inserisci il tuo codice</string>
<string name="TotpCodeEntryScreen__enter_your_code">Inserisci il tuo codice</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">Inserisci il codice a 6 cifre dalla tua app di autenticazione.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">Inserisci il codice a 6 cifre dalla tua app di autenticazione.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">Codice</string>
<string name="TotpCodeEntryScreen__code">Codice</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">Fatto</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">Fatto</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">App per l\'autenticazione</string>
<string name="TotpAppListScreen__authenticator_app">App per l\'autenticazione</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">Set up an authenticator app to generate one-time verification codes</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">Scopri di più</string>
<string name="TotpAppListScreen__learn_more">Scopri di più</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">Add authenticator app</string>
<string name="TotpAppListScreen__add_authenticator_app">Add authenticator app</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">Authenticator apps</string>
<string name="TotpAppListScreen__authenticator_apps">Authenticator apps</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">No authenticator apps</string>
<string name="TotpAppListScreen__no_authenticator_apps">No authenticator apps</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">Aggiunto \"%1$s\"</string>
<string name="TotpAppListScreen__added_s">Aggiunto \"%1$s\"</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">Open authenticator app options</string>
<string name="TotpAppListScreen__open_authenticator_app_options">Open authenticator app options</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">Rinomina</string>
<string name="TotpAppListScreen__rename">Rinomina</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">Rimuovi</string>
<string name="TotpAppListScreen__remove">Rimuovi</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">Remove authenticator app?</string>
<string name="TotpAppListScreen__remove_authenticator_app">Remove authenticator app?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">To remove this authentication method the 6-digit code from your authenticator app is required.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">Can\'t add authenticator app</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">You can\'t add more than %1$d authenticator apps. Try removing one first.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">Authenticator app removed</string>
<string name="TotpAppListScreen__authenticator_app_removed">Authenticator app removed</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">Scegli un nome</string>
<string name="TotpNameEntryScreen__choose_a_name">Scegli un nome</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">Choose a unique name for this authenticator app.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">Choose a unique name for this authenticator app to help you identify it later.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">Nome</string>
<string name="TotpNameEntryScreen__name">Nome</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">Avanti</string>
<string name="TotpNameEntryScreen__next">Avanti</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">Authenticator app set up</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">Authenticator app set up</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">Authenticator app renamed</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">Authenticator app renamed</string>
</resources>
@@ -86,37 +86,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">למידע נוסף</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">הגדרת אפליקציית האימות שלך</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">הגדרת אפליקציית האימות שלך</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">יש לבצע את השלבים הבאים כדי להגדיר אפליקציית אימות דו-שלבי:</string>
<string name="TotpSetupScreen__follow_these_steps">יש לבצע את השלבים הבאים כדי להגדיר אפליקציית אימות דו-שלבי:</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">למידע נוסף</string>
<string name="TotpSetupScreen__learn_more">למידע נוסף</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">שלב 1</string>
<string name="TotpSetupScreen__step_1">שלב 1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">להתקין אפליקציה אמינה של אימות דו-שלבי במכשיר שלך.</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">להתקין אפליקציה אמינה של אימות דו-שלבי במכשיר שלך.</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">שלב 2</string>
<string name="TotpSetupScreen__step_2">שלב 2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">לפתוח את אפליקציית האימות באמצעות לחיצה על הכפתור שלמטה כדי להוסיף את חשבון Signal שלך.</string>
<string name="TotpSetupScreen__open_your_authenticator_app">לפתוח את אפליקציית האימות באמצעות לחיצה על הכפתור שלמטה כדי להוסיף את חשבון Signal שלך.</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">פתיחה</string>
<string name="TotpSetupScreen__open">פתיחה</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">אפשר גם להעתיק את הקישור הזה כדי להגדיר באופן ידני.</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">אפשר גם להעתיק את הקישור הזה כדי להגדיר באופן ידני.</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">העתק</string>
<string name="TotpSetupScreen__copy">העתק</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">הועתק ללוח</string>
<string name="TotpSetupScreen__copied_to_clipboard">הועתק ללוח</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">לא נמצאה אפליקציית אימות</string>
<string name="TotpSetupScreen__no_authenticator_app_found">לא נמצאה אפליקציית אימות</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">שלב 3</string>
<string name="TotpSetupScreen__step_3">שלב 3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">להעתיק את הקוד שנוצר ולחזור לכאן כדי להמשיך.</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">להעתיק את הקוד שנוצר ולחזור לכאן כדי להמשיך.</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">המשך</string>
<string name="TotpSetupScreen__continue">המשך</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -146,60 +146,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">הסרה</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">הזנת הקוד שלך</string>
<string name="TotpCodeEntryScreen__enter_your_code">הזנת הקוד שלך</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">יש להזין קוד בן 6 ספרות מאפליקציית האימות שלך.</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">יש להזין קוד בן 6 ספרות מאפליקציית האימות שלך.</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">קוד</string>
<string name="TotpCodeEntryScreen__code">קוד</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">סיום</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">סיום</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">אפליקציית אימות דו-שלבי</string>
<string name="TotpAppListScreen__authenticator_app">אפליקציית אימות דו-שלבי</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">להגדיר אפליקציית אימות ליצירת קודי אימות חד–פעמיים</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">להגדיר אפליקציית אימות ליצירת קודי אימות חד–פעמיים</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">למידע נוסף</string>
<string name="TotpAppListScreen__learn_more">למידע נוסף</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">הוספת אפליקציית אימות</string>
<string name="TotpAppListScreen__add_authenticator_app">הוספת אפליקציית אימות</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">אפליקציות אימות דו–שלבי</string>
<string name="TotpAppListScreen__authenticator_apps">אפליקציות אימות דו–שלבי</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">אין אפליקציות אימות</string>
<string name="TotpAppListScreen__no_authenticator_apps">אין אפליקציות אימות</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">\"%1$s\" התווסף/ה</string>
<string name="TotpAppListScreen__added_s">\"%1$s\" התווסף/ה</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">פתיחת אפשרויות אפליקציית אימות</string>
<string name="TotpAppListScreen__open_authenticator_app_options">פתיחת אפשרויות אפליקציית אימות</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">שינוי שם</string>
<string name="TotpAppListScreen__rename">שינוי שם</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">הסרה</string>
<string name="TotpAppListScreen__remove">הסרה</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">להסיר אפליקציית אימות?</string>
<string name="TotpAppListScreen__remove_authenticator_app">להסיר אפליקציית אימות?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">כדי להסיר את שיטת האימות הזו, נדרש קוד בן 6 ספרות מאפליקציית האימות שלך.</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">כדי להסיר את שיטת האימות הזו, נדרש קוד בן 6 ספרות מאפליקציית האימות שלך.</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">לא ניתן להוסיף אפליקציית אימות</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">לא ניתן להוסיף אפליקציית אימות</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">לא ניתן להוסיף יותר מ–%1$d אפליקציות אימות. יש לנסות להסיר אחת קודם.</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">לא ניתן להוסיף יותר מ–%1$d אפליקציות אימות. יש לנסות להסיר אחת קודם.</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">אפליקציית אימות הוסרה</string>
<string name="TotpAppListScreen__authenticator_app_removed">אפליקציית אימות הוסרה</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">בחר שם</string>
<string name="TotpNameEntryScreen__choose_a_name">בחר שם</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">בחירת שם ייחודי לאפליקציית האימות הזו.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">בחירת שם ייחודי לאפליקציית האימות הזו.</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">בחירת שם ייחודי לאפליקציית האימות הזו שיעזור לך לזהות אותה בהמשך.</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">בחירת שם ייחודי לאפליקציית האימות הזו שיעזור לך לזהות אותה בהמשך.</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">שם</string>
<string name="TotpNameEntryScreen__name">שם</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">הבא</string>
<string name="TotpNameEntryScreen__next">הבא</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">הגדרות אפליקציית אימות</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">הגדרות אפליקציית אימות</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">שונה שם אפליקציית האימות</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">שונה שם אפליקציית האימות</string>
</resources>
@@ -77,37 +77,37 @@
<!-- Clickable text that takes the user to a support article -->
<string name="AccountSettingsFragment__learn_more">詳しく見る</string>
<!-- AuthenticatorSetupScreen -->
<!-- TotpSetupScreen -->
<!-- Title of the screen that walks the user through setting up an authenticator app -->
<string name="AuthenticatorSetupScreen__set_up_your_authenticator_app">認証アプリを設定しましょう</string>
<string name="TotpSetupScreen__set_up_your_authenticator_app">認証アプリを設定しましょう</string>
<!-- Instructions shown at the top of the authenticator app setup screen -->
<string name="AuthenticatorSetupScreen__follow_these_steps">以下の手順に従って認証アプリを設定してください。</string>
<string name="TotpSetupScreen__follow_these_steps">以下の手順に従って認証アプリを設定してください。</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorSetupScreen__learn_more">詳しく見る</string>
<string name="TotpSetupScreen__learn_more">詳しく見る</string>
<!-- Header of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_1">ステップ1</string>
<string name="TotpSetupScreen__step_1">ステップ1</string>
<!-- Body of the first step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__install_a_trusted_authenticator_app">ご利用の端末に、信頼できる認証アプリをインストールしてください。</string>
<string name="TotpSetupScreen__install_a_trusted_authenticator_app">ご利用の端末に、信頼できる認証アプリをインストールしてください。</string>
<!-- Header of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_2">ステップ2</string>
<string name="TotpSetupScreen__step_2">ステップ2</string>
<!-- Body of the second step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__open_your_authenticator_app">下のボタンをタップして認証アプリを開き、Signalアカウントを追加してください。</string>
<string name="TotpSetupScreen__open_your_authenticator_app">下のボタンをタップして認証アプリを開き、Signalアカウントを追加してください。</string>
<!-- Button that opens the user\'s authenticator app -->
<string name="AuthenticatorSetupScreen__open">開く</string>
<string name="TotpSetupScreen__open">開く</string>
<!-- Text above the setup key explaining that it can be entered by hand instead -->
<string name="AuthenticatorSetupScreen__or_you_can_copy_this_key">または、以下のキーをコピーして手動でセットアップすることもできます。</string>
<string name="TotpSetupScreen__or_you_can_copy_this_key">または、以下のキーをコピーして手動でセットアップすることもできます。</string>
<!-- Button that copies the setup key to the clipboard -->
<string name="AuthenticatorSetupScreen__copy">コピー</string>
<string name="TotpSetupScreen__copy">コピー</string>
<!-- Toast shown after the setup key has been copied to the clipboard -->
<string name="AuthenticatorSetupScreen__copied_to_clipboard">クリップボードにコピーしました</string>
<string name="TotpSetupScreen__copied_to_clipboard">クリップボードにコピーしました</string>
<!-- Toast shown when there is no app installed that can handle the authenticator setup link -->
<string name="AuthenticatorSetupScreen__no_authenticator_app_found">認証アプリが見つかりませんでした</string>
<string name="TotpSetupScreen__no_authenticator_app_found">認証アプリが見つかりませんでした</string>
<!-- Header of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__step_3">ステップ3</string>
<string name="TotpSetupScreen__step_3">ステップ3</string>
<!-- Body of the third step of authenticator app setup -->
<string name="AuthenticatorSetupScreen__copy_the_code_thats_generated">生成されたコードをコピーして、ここに戻り続行してください。</string>
<string name="TotpSetupScreen__copy_the_code_thats_generated">生成されたコードをコピーして、ここに戻り続行してください。</string>
<!-- Button that advances from the setup instructions to entering a code -->
<string name="AuthenticatorSetupScreen__continue">続行</string>
<string name="TotpSetupScreen__continue">続行</string>
<!-- PasskeysScreen -->
<!-- Title of the screen where the user sets up passkeys -->
@@ -137,60 +137,60 @@
<!-- Menu option that removes a passkey -->
<string name="PasskeysScreen__remove">削除</string>
<!-- AuthenticatorCodeEntryScreen -->
<!-- TotpCodeEntryScreen -->
<!-- Title of the screen where the user enters the code from their authenticator app -->
<string name="AuthenticatorCodeEntryScreen__enter_your_code">コードを入力してください</string>
<string name="TotpCodeEntryScreen__enter_your_code">コードを入力してください</string>
<!-- Instructions shown above the code entry field -->
<string name="AuthenticatorCodeEntryScreen__enter_the_6_digit_code">認証アプリに表示された6桁のコードを入力してください。</string>
<string name="TotpCodeEntryScreen__enter_the_6_digit_code">認証アプリに表示された6桁のコードを入力してください。</string>
<!-- Label of the code entry field -->
<string name="AuthenticatorCodeEntryScreen__code">コード</string>
<string name="TotpCodeEntryScreen__code">コード</string>
<!-- Button that submits the entered code -->
<string name="AuthenticatorCodeEntryScreen__done">完了</string>
<!-- AuthenticatorAppsScreen -->
<string name="TotpCodeEntryScreen__done">完了</string>
<!-- TotpAppListScreen -->
<!-- Title of the screen listing the authenticator apps on the account -->
<string name="AuthenticatorAppsScreen__authenticator_app">認証アプリ</string>
<string name="TotpAppListScreen__authenticator_app">認証アプリ</string>
<!-- Description of what an authenticator app is for, shown at the top of the screen -->
<string name="AuthenticatorAppsScreen__set_up_an_authenticator_app">ワンタイム確認コードを生成するために認証アプリを設定してください</string>
<string name="TotpAppListScreen__set_up_an_authenticator_app">ワンタイム確認コードを生成するために認証アプリを設定してください</string>
<!-- Clickable text that takes the user to a support article -->
<string name="AuthenticatorAppsScreen__learn_more">詳しく見る</string>
<string name="TotpAppListScreen__learn_more">詳しく見る</string>
<!-- Button that starts setting up another authenticator app -->
<string name="AuthenticatorAppsScreen__add_authenticator_app">認証アプリを追加</string>
<string name="TotpAppListScreen__add_authenticator_app">認証アプリを追加</string>
<!-- Section header above the list of configured authenticator apps -->
<string name="AuthenticatorAppsScreen__authenticator_apps">認証アプリ</string>
<string name="TotpAppListScreen__authenticator_apps">認証アプリ</string>
<!-- Shown in place of the list when no authenticator apps are configured -->
<string name="AuthenticatorAppsScreen__no_authenticator_apps">認証アプリが設定されていません</string>
<string name="TotpAppListScreen__no_authenticator_apps">認証アプリが設定されていません</string>
<!-- Subtitle of an authenticator app row saying when it was configured. Placeholder is a date or time. -->
<string name="AuthenticatorAppsScreen__added_s">「%1$s」を追加しました</string>
<string name="TotpAppListScreen__added_s">「%1$s」を追加しました</string>
<!-- Content description of the button that opens an authenticator app\'s options -->
<string name="AuthenticatorAppsScreen__open_authenticator_app_options">認証アプリのオプションを開く</string>
<string name="TotpAppListScreen__open_authenticator_app_options">認証アプリのオプションを開く</string>
<!-- Menu option that renames an authenticator app -->
<string name="AuthenticatorAppsScreen__rename">名前を変更する</string>
<string name="TotpAppListScreen__rename">名前を変更する</string>
<!-- Menu option that removes an authenticator app -->
<string name="AuthenticatorAppsScreen__remove">削除</string>
<string name="TotpAppListScreen__remove">削除</string>
<!-- Title of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__remove_authenticator_app">認証アプリを削除しますか?</string>
<string name="TotpAppListScreen__remove_authenticator_app">認証アプリを削除しますか?</string>
<!-- Body of the dialog confirming removal of an authenticator app -->
<string name="AuthenticatorAppsScreen__to_remove_this_authentication_method">この認証方法を削除するには、認証アプリの6桁のコードが必要です。</string>
<string name="TotpAppListScreen__to_remove_this_authentication_method">この認証方法を削除するには、認証アプリの6桁のコードが必要です。</string>
<!-- Title of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__cant_add_authenticator_app">認証アプリを追加できません</string>
<string name="TotpAppListScreen__cant_add_authenticator_app">認証アプリを追加できません</string>
<!-- Body of the dialog shown when the account already has as many authenticator apps as it\'s allowed -->
<string name="AuthenticatorAppsScreen__you_cant_add_more_than_d">%1$dつを超える数の認証アプリは追加できません。まず1つを削除してください。</string>
<string name="TotpAppListScreen__you_cant_add_more_than_d">%1$dつを超える数の認証アプリは追加できません。まず1つを削除してください。</string>
<!-- Toast shown after an authenticator app has been removed -->
<string name="AuthenticatorAppsScreen__authenticator_app_removed">認証アプリが削除されました</string>
<string name="TotpAppListScreen__authenticator_app_removed">認証アプリが削除されました</string>
<!-- AuthenticatorNameScreen -->
<!-- TotpNameEntryScreen -->
<!-- Title of the screen where the user names an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_name">名前を選択してください</string>
<string name="TotpNameEntryScreen__choose_a_name">名前を選択してください</string>
<!-- Instructions shown above the name field when renaming an authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name">この認証アプリには覚えやすい名称をつけてください。</string>
<string name="TotpNameEntryScreen__choose_a_unique_name">この認証アプリには覚えやすい名称をつけてください。</string>
<!-- Instructions shown above the name field when naming a newly configured authenticator app -->
<string name="AuthenticatorNameScreen__choose_a_unique_name_to_help_you_identify_it">この認証アプリには、後で分かりやすいように覚えやすい名称をつけてください。</string>
<string name="TotpNameEntryScreen__choose_a_unique_name_to_help_you_identify_it">この認証アプリには、後で分かりやすいように覚えやすい名称をつけてください。</string>
<!-- Label of the name field -->
<string name="AuthenticatorNameScreen__name">名前</string>
<string name="TotpNameEntryScreen__name">名前</string>
<!-- Button that submits the entered name -->
<string name="AuthenticatorNameScreen__next">次へ</string>
<string name="TotpNameEntryScreen__next">次へ</string>
<!-- Toast shown after an authenticator app has been successfully set up -->
<string name="AuthenticatorNameScreen__authenticator_app_set_up">認証アプリを設定しました</string>
<string name="TotpNameEntryScreen__authenticator_app_set_up">認証アプリを設定しました</string>
<!-- Toast shown after an authenticator app has been renamed -->
<string name="AuthenticatorNameScreen__authenticator_app_renamed">認証アプリの名前を変更しました</string>
<string name="TotpNameEntryScreen__authenticator_app_renamed">認証アプリの名前を変更しました</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More