mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-09-19 16:24:41 +01:00
Add basic TOTP support with mocked creation.
This commit is contained in:
committed by
Alex Hart
parent
6a032e4f27
commit
62897a309c
+1
-1
@@ -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
-3
@@ -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
|
||||
|
||||
|
||||
+8
-5
@@ -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 {
|
||||
|
||||
-46
@@ -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 } }
|
||||
}
|
||||
-75
@@ -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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
-81
@@ -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()) }
|
||||
}
|
||||
}
|
||||
-56
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-72
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-56
@@ -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()
|
||||
}
|
||||
}
|
||||
-73
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-47
@@ -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)
|
||||
}
|
||||
}
|
||||
-25
@@ -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)
|
||||
}
|
||||
-71
@@ -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()
|
||||
}
|
||||
}
|
||||
+92
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
+86
@@ -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
|
||||
}
|
||||
}
|
||||
+75
@@ -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()
|
||||
}
|
||||
}
|
||||
+109
@@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+83
@@ -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) }
|
||||
}
|
||||
}
|
||||
+62
@@ -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()
|
||||
}
|
||||
}
|
||||
+100
@@ -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)
|
||||
}
|
||||
}
|
||||
+44
@@ -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)
|
||||
}
|
||||
}
|
||||
+243
@@ -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
|
||||
}
|
||||
}
|
||||
+17
-17
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+95
@@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -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>
|
||||
|
||||
+17
-6
@@ -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
|
||||
|
||||
-195
@@ -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
|
||||
}
|
||||
}
|
||||
-125
@@ -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
|
||||
}
|
||||
}
|
||||
-134
@@ -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
|
||||
}
|
||||
}
|
||||
-60
@@ -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)
|
||||
}
|
||||
}
|
||||
-109
@@ -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
|
||||
}
|
||||
}
|
||||
+129
@@ -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
|
||||
}
|
||||
+280
@@ -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
|
||||
}
|
||||
}
|
||||
+154
@@ -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
|
||||
}
|
||||
}
|
||||
+191
@@ -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
|
||||
}
|
||||
}
|
||||
+55
@@ -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)
|
||||
}
|
||||
}
|
||||
+178
@@ -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
|
||||
}
|
||||
}
|
||||
+182
@@ -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)
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -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(
|
||||
|
||||
+4
-2
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+9
-6
@@ -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 = {}
|
||||
)
|
||||
|
||||
+2
-1
@@ -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
|
||||
)
|
||||
|
||||
|
||||
-30
@@ -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
|
||||
}
|
||||
-36
@@ -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
|
||||
}
|
||||
-27
@@ -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
|
||||
}
|
||||
-31
@@ -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
|
||||
}
|
||||
}
|
||||
-19
@@ -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)"
|
||||
}
|
||||
-13
@@ -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"})"
|
||||
}
|
||||
+4
-4
@@ -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)"
|
||||
}
|
||||
+33
@@ -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
|
||||
}
|
||||
+36
@@ -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
|
||||
}
|
||||
+131
-73
@@ -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())
|
||||
)
|
||||
+17
-4
@@ -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
|
||||
+24
@@ -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
|
||||
}
|
||||
+5
-5
@@ -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
|
||||
}
|
||||
+46
-18
@@ -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 = {}
|
||||
)
|
||||
}
|
||||
+32
@@ -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
|
||||
}
|
||||
}
|
||||
+10
-7
@@ -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
|
||||
}
|
||||
+5
-5
@@ -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
|
||||
}
|
||||
+22
-22
@@ -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 = {}
|
||||
)
|
||||
}
|
||||
+24
@@ -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)"
|
||||
}
|
||||
+10
-10
@@ -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
|
||||
}
|
||||
+10
-7
@@ -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
|
||||
}
|
||||
+83
-42
@@ -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">Aç</string>
|
||||
<string name="TotpSetupScreen__open">Aç</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
Reference in New Issue
Block a user