Localize auth screens (login, verify email, reset password) EN/RU
Some checks failed
Android CI / android (push) Has started running
Android Release / release (push) Has been cancelled
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-11 06:07:55 +03:00
parent e0728ac067
commit e591a3fa8d
5 changed files with 109 additions and 34 deletions

View File

@@ -20,13 +20,15 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import ru.daemonlord.messenger.R
@Composable
fun LoginScreen(
state: AuthUiState,
headerTitle: String = "Messenger Login",
headerTitle: String = "",
onEmailChanged: (String) -> Unit,
onNameChanged: (String) -> Unit,
onUsernameChanged: (String) -> Unit,
@@ -42,6 +44,7 @@ fun LoginScreen(
) {
val isTabletLayout = LocalConfiguration.current.screenWidthDp >= 840
val isBusy = state.isLoading
val resolvedHeaderTitle = headerTitle.ifBlank { stringResource(id = R.string.auth_header_login) }
Box(
modifier = Modifier
@@ -58,16 +61,16 @@ fun LoginScreen(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
text = headerTitle,
text = resolvedHeaderTitle,
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(bottom = 14.dp),
)
val subtitle = when (state.step) {
AuthStep.EMAIL -> "Enter your email to continue"
AuthStep.PASSWORD -> "Enter password for ${state.email}"
AuthStep.REGISTER -> "Create account for ${state.email}"
AuthStep.OTP -> "Two-factor authentication is enabled"
AuthStep.EMAIL -> stringResource(id = R.string.auth_subtitle_enter_email)
AuthStep.PASSWORD -> stringResource(id = R.string.auth_subtitle_enter_password, state.email)
AuthStep.REGISTER -> stringResource(id = R.string.auth_subtitle_create_account, state.email)
AuthStep.OTP -> stringResource(id = R.string.auth_subtitle_2fa_enabled)
}
Text(
text = subtitle,
@@ -81,7 +84,7 @@ fun LoginScreen(
OutlinedTextField(
value = state.email,
onValueChange = onEmailChanged,
label = { Text(text = "Email") },
label = { Text(text = stringResource(id = R.string.auth_label_email)) },
singleLine = true,
enabled = !isBusy,
modifier = Modifier
@@ -96,7 +99,7 @@ fun LoginScreen(
if (isBusy) {
CircularProgressIndicator(strokeWidth = 2.dp, modifier = Modifier.padding(2.dp))
} else {
Text("Continue")
Text(stringResource(id = R.string.auth_continue))
}
}
}
@@ -106,7 +109,7 @@ fun LoginScreen(
value = state.email,
onValueChange = {},
readOnly = true,
label = { Text(text = "Email") },
label = { Text(text = stringResource(id = R.string.auth_label_email)) },
singleLine = true,
modifier = Modifier
.fillMaxWidth()
@@ -119,14 +122,14 @@ fun LoginScreen(
.align(Alignment.Start)
.padding(bottom = 6.dp),
) {
Text("Change email")
Text(stringResource(id = R.string.auth_change_email))
}
if (state.step == AuthStep.REGISTER) {
OutlinedTextField(
value = state.name,
onValueChange = onNameChanged,
label = { Text(text = "Name") },
label = { Text(text = stringResource(id = R.string.auth_label_name)) },
singleLine = true,
enabled = !isBusy,
modifier = Modifier
@@ -136,7 +139,7 @@ fun LoginScreen(
OutlinedTextField(
value = state.username,
onValueChange = onUsernameChanged,
label = { Text(text = "Username") },
label = { Text(text = stringResource(id = R.string.auth_label_username)) },
singleLine = true,
enabled = !isBusy,
modifier = Modifier
@@ -149,7 +152,7 @@ fun LoginScreen(
OutlinedTextField(
value = state.password,
onValueChange = onPasswordChanged,
label = { Text(text = "Password") },
label = { Text(text = stringResource(id = R.string.auth_label_password)) },
visualTransformation = PasswordVisualTransformation(),
singleLine = true,
enabled = !isBusy,
@@ -167,13 +170,19 @@ fun LoginScreen(
.align(Alignment.Start)
.padding(bottom = 4.dp),
) {
Text(if (state.useRecoveryCode) "Use OTP code" else "Use recovery code")
Text(
if (state.useRecoveryCode) {
stringResource(id = R.string.auth_use_otp_code)
} else {
stringResource(id = R.string.auth_use_recovery_code)
},
)
}
if (state.useRecoveryCode) {
OutlinedTextField(
value = state.recoveryCode,
onValueChange = onRecoveryCodeChanged,
label = { Text(text = "Recovery code") },
label = { Text(text = stringResource(id = R.string.auth_label_recovery_code)) },
singleLine = true,
enabled = !isBusy,
modifier = Modifier
@@ -184,7 +193,7 @@ fun LoginScreen(
OutlinedTextField(
value = state.otpCode,
onValueChange = onOtpCodeChanged,
label = { Text(text = "2FA code") },
label = { Text(text = stringResource(id = R.string.auth_label_2fa_code)) },
singleLine = true,
enabled = !isBusy,
modifier = Modifier
@@ -204,10 +213,10 @@ fun LoginScreen(
} else {
Text(
when (state.step) {
AuthStep.PASSWORD -> "Sign in"
AuthStep.REGISTER -> "Create account"
AuthStep.OTP -> "Confirm 2FA"
AuthStep.EMAIL -> "Continue"
AuthStep.PASSWORD -> stringResource(id = R.string.auth_sign_in)
AuthStep.REGISTER -> stringResource(id = R.string.auth_create_account)
AuthStep.OTP -> stringResource(id = R.string.auth_confirm_2fa)
AuthStep.EMAIL -> stringResource(id = R.string.auth_continue)
}
)
}
@@ -237,13 +246,13 @@ fun LoginScreen(
enabled = !isBusy,
modifier = Modifier.padding(top = 8.dp),
) {
Text(text = "Verify email by token")
Text(text = stringResource(id = R.string.auth_verify_email_by_token))
}
TextButton(
onClick = onOpenResetPassword,
enabled = !isBusy,
) {
Text(text = "Forgot password")
Text(text = stringResource(id = R.string.auth_forgot_password))
}
}
}

View File

@@ -23,9 +23,11 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ru.daemonlord.messenger.R
import ru.daemonlord.messenger.ui.account.AccountViewModel
@Composable
@@ -51,11 +53,11 @@ fun ResetPasswordRoute(
.then(if (isTabletLayout) Modifier.widthIn(max = 620.dp) else Modifier),
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
Text("Password reset", style = MaterialTheme.typography.headlineSmall)
Text(stringResource(id = R.string.auth_password_reset_title), style = MaterialTheme.typography.headlineSmall)
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Email") },
label = { Text(stringResource(id = R.string.auth_label_email)) },
modifier = Modifier.fillMaxWidth(),
)
Button(
@@ -63,12 +65,12 @@ fun ResetPasswordRoute(
modifier = Modifier.fillMaxWidth(),
enabled = !state.isSaving && email.isNotBlank(),
) {
Text("Send reset link")
Text(stringResource(id = R.string.auth_send_reset_link))
}
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("New password") },
label = { Text(stringResource(id = R.string.auth_new_password)) },
modifier = Modifier.fillMaxWidth(),
)
Button(
@@ -80,7 +82,7 @@ fun ResetPasswordRoute(
modifier = Modifier.fillMaxWidth(),
enabled = !state.isSaving && !token.isNullOrBlank() && password.length >= 8,
) {
Text("Reset with token")
Text(stringResource(id = R.string.auth_reset_with_token))
}
if (state.isSaving) {
CircularProgressIndicator()
@@ -92,7 +94,7 @@ fun ResetPasswordRoute(
Text(state.errorMessage!!, color = MaterialTheme.colorScheme.error)
}
Button(onClick = onBackToLogin, modifier = Modifier.fillMaxWidth()) {
Text("Back to login")
Text(stringResource(id = R.string.auth_back_to_login))
}
}
}

View File

@@ -24,9 +24,11 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ru.daemonlord.messenger.R
import ru.daemonlord.messenger.ui.account.AccountViewModel
@Composable
@@ -59,11 +61,11 @@ fun VerifyEmailRoute(
.then(if (isTabletLayout) Modifier.widthIn(max = 620.dp) else Modifier),
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
Text("Verify email", style = MaterialTheme.typography.headlineSmall)
Text(stringResource(id = R.string.auth_verify_email_title), style = MaterialTheme.typography.headlineSmall)
OutlinedTextField(
value = editableToken,
onValueChange = { editableToken = it },
label = { Text("Verification token") },
label = { Text(stringResource(id = R.string.auth_verification_token)) },
modifier = Modifier.fillMaxWidth(),
)
Button(
@@ -71,12 +73,12 @@ fun VerifyEmailRoute(
enabled = !state.isSaving && editableToken.isNotBlank(),
modifier = Modifier.fillMaxWidth(),
) {
Text("Verify")
Text(stringResource(id = R.string.auth_verify))
}
OutlinedTextField(
value = resendEmail,
onValueChange = { resendEmail = it },
label = { Text("Email for resend") },
label = { Text(stringResource(id = R.string.auth_email_for_resend)) },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
)
@@ -85,7 +87,7 @@ fun VerifyEmailRoute(
enabled = !state.isSaving && resendEmail.isNotBlank(),
modifier = Modifier.fillMaxWidth(),
) {
Text("Resend verification link")
Text(stringResource(id = R.string.auth_resend_verification_link))
}
if (state.isSaving) {
CircularProgressIndicator()
@@ -97,7 +99,7 @@ fun VerifyEmailRoute(
Text(state.errorMessage!!, color = MaterialTheme.colorScheme.error)
}
Button(onClick = onBackToLogin, modifier = Modifier.fillMaxWidth()) {
Text("Back to login")
Text(stringResource(id = R.string.auth_back_to_login))
}
}
}

View File

@@ -177,4 +177,35 @@
<string name="privacy_everyone">все</string>
<string name="privacy_contacts">контакты</string>
<string name="privacy_nobody">никто</string>
<string name="auth_header_login">Вход в Messenger</string>
<string name="auth_subtitle_enter_email">Введите email для продолжения</string>
<string name="auth_subtitle_enter_password">Введите пароль для %1$s</string>
<string name="auth_subtitle_create_account">Создайте аккаунт для %1$s</string>
<string name="auth_subtitle_2fa_enabled">Включена двухфакторная аутентификация</string>
<string name="auth_label_email">Email</string>
<string name="auth_label_name">Имя</string>
<string name="auth_label_username">Имя пользователя</string>
<string name="auth_label_password">Пароль</string>
<string name="auth_label_recovery_code">Код восстановления</string>
<string name="auth_label_2fa_code">Код 2FA</string>
<string name="auth_continue">Продолжить</string>
<string name="auth_change_email">Изменить email</string>
<string name="auth_use_otp_code">Использовать OTP-код</string>
<string name="auth_use_recovery_code">Использовать код восстановления</string>
<string name="auth_sign_in">Войти</string>
<string name="auth_create_account">Создать аккаунт</string>
<string name="auth_confirm_2fa">Подтвердить 2FA</string>
<string name="auth_verify_email_by_token">Подтвердить email по токену</string>
<string name="auth_forgot_password">Забыли пароль</string>
<string name="auth_verify_email_title">Подтверждение email</string>
<string name="auth_verification_token">Токен подтверждения</string>
<string name="auth_verify">Подтвердить</string>
<string name="auth_email_for_resend">Email для повторной отправки</string>
<string name="auth_resend_verification_link">Отправить ссылку повторно</string>
<string name="auth_back_to_login">Назад ко входу</string>
<string name="auth_password_reset_title">Сброс пароля</string>
<string name="auth_send_reset_link">Отправить ссылку сброса</string>
<string name="auth_new_password">Новый пароль</string>
<string name="auth_reset_with_token">Сбросить по токену</string>
</resources>

View File

@@ -177,4 +177,35 @@
<string name="privacy_everyone">everyone</string>
<string name="privacy_contacts">contacts</string>
<string name="privacy_nobody">nobody</string>
<string name="auth_header_login">Messenger Login</string>
<string name="auth_subtitle_enter_email">Enter your email to continue</string>
<string name="auth_subtitle_enter_password">Enter password for %1$s</string>
<string name="auth_subtitle_create_account">Create account for %1$s</string>
<string name="auth_subtitle_2fa_enabled">Two-factor authentication is enabled</string>
<string name="auth_label_email">Email</string>
<string name="auth_label_name">Name</string>
<string name="auth_label_username">Username</string>
<string name="auth_label_password">Password</string>
<string name="auth_label_recovery_code">Recovery code</string>
<string name="auth_label_2fa_code">2FA code</string>
<string name="auth_continue">Continue</string>
<string name="auth_change_email">Change email</string>
<string name="auth_use_otp_code">Use OTP code</string>
<string name="auth_use_recovery_code">Use recovery code</string>
<string name="auth_sign_in">Sign in</string>
<string name="auth_create_account">Create account</string>
<string name="auth_confirm_2fa">Confirm 2FA</string>
<string name="auth_verify_email_by_token">Verify email by token</string>
<string name="auth_forgot_password">Forgot password</string>
<string name="auth_verify_email_title">Verify email</string>
<string name="auth_verification_token">Verification token</string>
<string name="auth_verify">Verify</string>
<string name="auth_email_for_resend">Email for resend</string>
<string name="auth_resend_verification_link">Resend verification link</string>
<string name="auth_back_to_login">Back to login</string>
<string name="auth_password_reset_title">Password reset</string>
<string name="auth_send_reset_link">Send reset link</string>
<string name="auth_new_password">New password</string>
<string name="auth_reset_with_token">Reset with token</string>
</resources>