mirror of
https://github.com/bitwarden/android.git
synced 2025-12-10 20:07:59 -06:00
[PM-25133] Plural forms (#5773)
Co-authored-by: Patrick Honkonen <1883101+SaintPatrck@users.noreply.github.com> Co-authored-by: Patrick Honkonen <phonkonen@bitwarden.com>
This commit is contained in:
parent
aa39e6c6be
commit
41e499fdf5
@ -5,8 +5,10 @@ import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.base.util.isValidEmail
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength
|
||||
@ -321,8 +323,11 @@ class CompleteRegistrationViewModel @Inject constructor(
|
||||
it.copy(
|
||||
dialog = CompleteRegistrationDialog.Error(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.master_password_length_val_message_x
|
||||
.asText(MIN_PASSWORD_LENGTH),
|
||||
message = BitwardenPlurals.master_password_length_val_message_x
|
||||
.asPluralsText(
|
||||
quantity = MIN_PASSWORD_LENGTH,
|
||||
args = arrayOf(MIN_PASSWORD_LENGTH),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -24,11 +24,12 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.util.asText
|
||||
@ -154,7 +155,11 @@ private fun MinimumCharacterCount(
|
||||
}
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text(
|
||||
text = stringResource(BitwardenString.minimum_characters, minimumCharacterCount),
|
||||
text = pluralStringResource(
|
||||
id = BitwardenPlurals.minimum_characters,
|
||||
count = minimumCharacterCount,
|
||||
formatArgs = arrayOf(minimumCharacterCount),
|
||||
),
|
||||
color = BitwardenTheme.colorScheme.text.secondary,
|
||||
style = BitwardenTheme.typography.labelSmall,
|
||||
)
|
||||
|
||||
@ -5,8 +5,10 @@ import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.base.util.orNullIfBlank
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.ForcePasswordResetReason
|
||||
import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength
|
||||
@ -199,8 +201,11 @@ class ResetPasswordViewModel @Inject constructor(
|
||||
it.copy(
|
||||
dialogState = ResetPasswordState.DialogState.Error(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.master_password_length_val_message_x
|
||||
.asText(MIN_PASSWORD_LENGTH),
|
||||
message = BitwardenPlurals.master_password_length_val_message_x
|
||||
.asPluralsText(
|
||||
quantity = MIN_PASSWORD_LENGTH,
|
||||
args = arrayOf(MIN_PASSWORD_LENGTH),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -4,8 +4,10 @@ import android.os.Parcelable
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.LogoutReason
|
||||
@ -111,8 +113,11 @@ class SetPasswordViewModel @Inject constructor(
|
||||
it.copy(
|
||||
dialogState = SetPasswordState.DialogState.Error(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.master_password_length_val_message_x
|
||||
.asText(MIN_PASSWORD_LENGTH),
|
||||
message = BitwardenPlurals.master_password_length_val_message_x
|
||||
.asPluralsText(
|
||||
quantity = MIN_PASSWORD_LENGTH,
|
||||
args = arrayOf(MIN_PASSWORD_LENGTH),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -14,8 +14,10 @@ import com.bitwarden.network.model.PolicyTypeJson
|
||||
import com.bitwarden.ui.platform.base.BackgroundEvent
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.bitwarden.vault.CipherView
|
||||
import com.bitwarden.vault.DecryptCipherListResult
|
||||
@ -1945,7 +1947,11 @@ class VaultAddEditViewModel @Inject constructor(
|
||||
is BreachCountResult.Success -> {
|
||||
VaultAddEditState.DialogState.Generic(
|
||||
message = if (result.breachCount > 0) {
|
||||
BitwardenString.password_exposed.asText(result.breachCount)
|
||||
BitwardenPlurals.password_exposed
|
||||
.asPluralsText(
|
||||
quantity = result.breachCount,
|
||||
args = arrayOf(result.breachCount),
|
||||
)
|
||||
} else {
|
||||
BitwardenString.password_safe.asText()
|
||||
},
|
||||
|
||||
@ -13,8 +13,10 @@ import com.bitwarden.ui.platform.base.BackgroundEvent
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.bitwarden.ui.util.concat
|
||||
import com.bitwarden.vault.CipherView
|
||||
@ -978,7 +980,10 @@ class VaultItemViewModel @Inject constructor(
|
||||
is BreachCountResult.Success -> {
|
||||
VaultItemState.DialogState.Generic(
|
||||
message = if (result.breachCount > 0) {
|
||||
BitwardenString.password_exposed.asText(result.breachCount)
|
||||
BitwardenPlurals.password_exposed.asPluralsText(
|
||||
quantity = result.breachCount,
|
||||
args = arrayOf(result.breachCount),
|
||||
)
|
||||
} else {
|
||||
BitwardenString.password_safe.asText()
|
||||
},
|
||||
|
||||
@ -5,7 +5,9 @@ import app.cash.turbine.test
|
||||
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
|
||||
import com.bitwarden.data.datasource.disk.base.FakeDispatcherManager
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||
import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength.LEVEL_0
|
||||
@ -590,7 +592,10 @@ class CompleteRegistrationViewModelTest : BaseViewModelTest() {
|
||||
passwordInput = input,
|
||||
dialog = CompleteRegistrationDialog.Error(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.master_password_length_val_message_x.asText(12),
|
||||
message = BitwardenPlurals.master_password_length_val_message_x.asPluralsText(
|
||||
quantity = 12,
|
||||
args = arrayOf(12),
|
||||
),
|
||||
),
|
||||
)
|
||||
viewModel.trySendAction(CompleteRegistrationAction.CallToActionClick)
|
||||
|
||||
@ -3,7 +3,9 @@ package com.x8bit.bitwarden.ui.auth.feature.resetPassword
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import app.cash.turbine.test
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.ForcePasswordResetReason
|
||||
import com.x8bit.bitwarden.data.auth.datasource.sdk.model.PasswordStrength
|
||||
@ -133,8 +135,10 @@ class ResetPasswordViewModelTest : BaseViewModelTest() {
|
||||
resetReason = ForcePasswordResetReason.ADMIN_FORCE_PASSWORD_RESET,
|
||||
dialogState = ResetPasswordState.DialogState.Error(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.master_password_length_val_message_x
|
||||
.asText(MIN_PASSWORD_LENGTH),
|
||||
message = BitwardenPlurals.master_password_length_val_message_x.asPluralsText(
|
||||
quantity = MIN_PASSWORD_LENGTH,
|
||||
args = arrayOf(MIN_PASSWORD_LENGTH),
|
||||
),
|
||||
),
|
||||
passwordInput = password,
|
||||
passwordStrengthState = PasswordStrengthState.WEAK_1,
|
||||
|
||||
@ -3,7 +3,9 @@ package com.x8bit.bitwarden.ui.auth.feature.setpassword
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import app.cash.turbine.test
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||
import com.x8bit.bitwarden.data.auth.repository.model.LogoutReason
|
||||
@ -87,8 +89,10 @@ class SetPasswordViewModelTest : BaseViewModelTest() {
|
||||
DEFAULT_STATE.copy(
|
||||
dialogState = SetPasswordState.DialogState.Error(
|
||||
title = BitwardenString.an_error_has_occurred.asText(),
|
||||
message = BitwardenString.master_password_length_val_message_x
|
||||
.asText(MIN_PASSWORD_LENGTH),
|
||||
message = BitwardenPlurals.master_password_length_val_message_x.asPluralsText(
|
||||
quantity = MIN_PASSWORD_LENGTH,
|
||||
args = arrayOf(MIN_PASSWORD_LENGTH),
|
||||
),
|
||||
),
|
||||
passwordInput = password,
|
||||
retypePasswordInput = password,
|
||||
|
||||
@ -20,8 +20,10 @@ import com.bitwarden.network.model.SyncResponseJson
|
||||
import com.bitwarden.send.SendView
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.bitwarden.vault.CipherListView
|
||||
import com.bitwarden.vault.CipherView
|
||||
@ -2439,7 +2441,10 @@ class VaultAddEditViewModelTest : BaseViewModelTest() {
|
||||
assertEquals(
|
||||
loginState.copy(
|
||||
dialog = VaultAddEditState.DialogState.Generic(
|
||||
message = BitwardenString.password_exposed.asText(breachCount),
|
||||
message = BitwardenPlurals.password_exposed.asPluralsText(
|
||||
quantity = breachCount,
|
||||
args = arrayOf(breachCount),
|
||||
),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
|
||||
@ -13,8 +13,10 @@ import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenPlurals
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.util.Text
|
||||
import com.bitwarden.ui.util.asPluralsText
|
||||
import com.bitwarden.ui.util.asText
|
||||
import com.bitwarden.ui.util.concat
|
||||
import com.bitwarden.vault.CipherView
|
||||
@ -1289,7 +1291,10 @@ class VaultItemViewModelTest : BaseViewModelTest() {
|
||||
assertEquals(
|
||||
loginState.copy(
|
||||
dialog = VaultItemState.DialogState.Generic(
|
||||
message = BitwardenString.password_exposed.asText(breachCount),
|
||||
message = BitwardenPlurals.password_exposed.asPluralsText(
|
||||
quantity = breachCount,
|
||||
args = arrayOf(breachCount),
|
||||
),
|
||||
),
|
||||
),
|
||||
awaitItem(),
|
||||
|
||||
@ -115,3 +115,11 @@ fun @receiver:StringRes Int.asText(): Text = ResText(this)
|
||||
* Convert a resource Id to [Text] with format args.
|
||||
*/
|
||||
fun @receiver:StringRes Int.asText(vararg args: Any): Text = ResArgsText(this, args.asList())
|
||||
|
||||
/**
|
||||
* Convert a resource Id to [Text] with quantity and format args.
|
||||
*/
|
||||
fun @receiver:PluralsRes Int.asPluralsText(
|
||||
quantity: Int,
|
||||
vararg args: Any,
|
||||
): Text = PluralsText(id = this, quantity = quantity, args = args.asList())
|
||||
|
||||
@ -110,7 +110,10 @@
|
||||
<string name="master_password_description">The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it.</string>
|
||||
<string name="master_password_hint">Master password hint (optional)</string>
|
||||
<string name="master_password_hint_description">A master password hint can help you remember your password if you forget it.</string>
|
||||
<string name="master_password_length_val_message_x">Master password must be at least %1$s characters long.</string>
|
||||
<plurals name="master_password_length_val_message_x">
|
||||
<item quantity="one">Master password must be at least %d character long.</item>
|
||||
<item quantity="other">Master password must be at least %d characters long.</item>
|
||||
</plurals>
|
||||
<string name="min_numbers">Minimum numbers</string>
|
||||
<string name="min_special">Minimum special</string>
|
||||
<string name="never">Never</string>
|
||||
@ -309,7 +312,10 @@ Scanning will happen automatically.</string>
|
||||
<string name="personal_details">Personal Details</string>
|
||||
<string name="contact_info">Contact Info</string>
|
||||
<string name="check_password_for_data_breaches">Check password for data breaches</string>
|
||||
<string name="password_exposed">This password has been exposed %1$s time(s) in data breaches. You should change it.</string>
|
||||
<plurals name="password_exposed">
|
||||
<item quantity="one">This password has been exposed %d time in data breaches. You should change it.</item>
|
||||
<item quantity="other">This password has been exposed %d times in data breaches. You should change it.</item>
|
||||
</plurals>
|
||||
<string name="password_safe">This password was not found in any known data breaches. It should be safe to use.</string>
|
||||
<string name="identity_name">Identity name</string>
|
||||
<string name="value">Value</string>
|
||||
@ -749,7 +755,10 @@ Do you want to switch to this account?</string>
|
||||
<string name="bitwarden_cannot_reset_a_lost_or_forgotten_master_password">Bitwarden cannot reset a lost or forgotten master password.</string>
|
||||
<string name="choose_your_master_password">Choose your master password</string>
|
||||
<string name="choose_a_unique_and_strong_password_to_keep_your_information_safe">Choose a unique and strong password to keep your information safe.</string>
|
||||
<string name="minimum_characters">%1$s characters</string>
|
||||
<plurals name="minimum_characters">
|
||||
<item quantity="one">%d character</item>
|
||||
<item quantity="other">%d characters</item>
|
||||
</plurals>
|
||||
<string name="expired_link">Expired link</string>
|
||||
<string name="please_restart_registration_or_try_logging_in">Please restart registration or try logging in. You may already have an account.</string>
|
||||
<string name="restart_registration">Restart registration</string>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user