fix: translate the auth server's answer to a wrong email or password

A password sign-in refused with INVALID_EMAIL_OR_PASSWORD showed the server's English
message in every app, and a failed mobile sign-in without a message fell back to a
hard-coded English line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DIYgod
2026-10-19 09:29:14 +08:00
co-authored by Claude Opus 5.5
parent 0e734ca2e9
commit 022993669d
8 changed files with 24 additions and 1 deletions
+5 -1
View File
@@ -69,7 +69,11 @@ async function signInWithEmail(
return false
}
} catch (error) {
Alert.alert(error instanceof Error ? error.message : "Unable to sign in")
Alert.alert(
error instanceof Error
? error.message
: i18next.t("auth.error.sign_in_failed", { ns: "common" }),
)
return false
}
+1
View File
@@ -3,6 +3,7 @@
"app.copied_to_clipboard": "Copied to clipboard",
"app.request_timeout": "The server took too long to respond. Please try again.",
"auth.error.account_not_linked": "This email belongs to a Folo account that isn't verified yet. Sign in to it once with a magic link on app.folo.is (leave the password empty), then try this sign-in method again.",
"auth.error.invalid_email_or_password": "Incorrect email or password.",
"auth.error.invalid_token": "This link is invalid or has expired. Please request a new one.",
"auth.error.sign_in_failed": "Couldn't sign in. Please try again.",
"auth.error.too_many_requests": "Too many requests. Please try again later.",
+1
View File
@@ -3,6 +3,7 @@
"app.copied_to_clipboard": "Copié dans le presse-papiers",
"app.request_timeout": "Le serveur a mis trop de temps à répondre. Veuillez réessayer.",
"auth.error.account_not_linked": "Cet email appartient à un compte Folo qui n'est pas encore vérifié. Connectez-vous-y une fois avec un lien magique sur app.folo.is (laissez le mot de passe vide), puis réessayez ce mode de connexion.",
"auth.error.invalid_email_or_password": "Email ou mot de passe incorrect.",
"auth.error.invalid_token": "Ce lien est invalide ou a expiré. Veuillez en demander un nouveau.",
"auth.error.sign_in_failed": "Connexion impossible. Veuillez réessayer.",
"auth.error.too_many_requests": "Trop de requêtes. Veuillez réessayer plus tard.",
+1
View File
@@ -3,6 +3,7 @@
"app.copied_to_clipboard": "クリップボードにコピーしました",
"app.request_timeout": "サーバーの応答に時間がかかりすぎました。しばらくしてからもう一度お試しください。",
"auth.error.account_not_linked": "このメールアドレスの Folo アカウントはまだ確認されていません。app.folo.is でマジックリンクを使って一度ログインしてから(パスワードは空欄のまま)、このログイン方法をもう一度お試しください。",
"auth.error.invalid_email_or_password": "メールアドレスまたはパスワードが正しくありません。",
"auth.error.invalid_token": "このリンクは無効か、有効期限が切れています。新しいリンクをリクエストしてください。",
"auth.error.sign_in_failed": "ログインできませんでした。もう一度お試しください。",
"auth.error.too_many_requests": "リクエストが多すぎます。しばらくしてからもう一度お試しください。",
+1
View File
@@ -3,6 +3,7 @@
"app.copied_to_clipboard": "已复制到剪贴板",
"app.request_timeout": "服务器响应超时,请稍后重试。",
"auth.error.account_not_linked": "此邮箱对应的 Folo 账号尚未验证。请先在 app.folo.is 用魔法链接登录一次(密码留空),再使用这种登录方式。",
"auth.error.invalid_email_or_password": "邮箱或密码不正确。",
"auth.error.invalid_token": "此链接无效或已过期,请重新获取。",
"auth.error.sign_in_failed": "登录失败,请重试。",
"auth.error.too_many_requests": "请求过于频繁,请稍后再试。",
+1
View File
@@ -3,6 +3,7 @@
"app.copied_to_clipboard": "已複製到剪貼簿",
"app.request_timeout": "伺服器回應逾時,請稍後再試。",
"auth.error.account_not_linked": "此電子信箱對應的 Folo 帳號尚未驗證。請先在 app.folo.is 用魔法連結登入一次(密碼留空),再使用這種登入方式。",
"auth.error.invalid_email_or_password": "電子信箱或密碼不正確。",
"auth.error.invalid_token": "此連結無效或已過期,請重新取得。",
"auth.error.sign_in_failed": "登入失敗,請再試一次。",
"auth.error.too_many_requests": "請求過於頻繁,請稍後再試。",
@@ -13,6 +13,9 @@ describe("getAuthErrorMessageKey", () => {
expect(getAuthErrorMessageKey("INVALID_TOKEN")).toBe("auth.error.invalid_token")
expect(getAuthErrorMessageKey("TOKEN_EXPIRED")).toBe("auth.error.invalid_token")
expect(getAuthErrorMessageKey("account_not_linked")).toBe("auth.error.account_not_linked")
expect(getAuthErrorMessageKey("INVALID_EMAIL_OR_PASSWORD")).toBe(
"auth.error.invalid_email_or_password",
)
})
it("names none for any other code", () => {
@@ -60,6 +63,15 @@ describe("describeAuthError", () => {
)
})
it("translates a password sign-in the server refused for the email or the password", () => {
expect(
describeAuthError(
{ code: "INVALID_EMAIL_OR_PASSWORD", message: "Invalid email or password", status: 401 },
translate,
),
).toBe("translated auth.error.invalid_email_or_password")
})
it("keeps what the server said about anything else", () => {
expect(
describeAuthError(
@@ -6,6 +6,8 @@
const AUTH_ERROR_MESSAGE_KEYS = {
// A provider's account for an email whose Folo account is not verified yet
account_not_linked: "auth.error.account_not_linked",
// A password sign-in with an email that has no account, or with the wrong password
INVALID_EMAIL_OR_PASSWORD: "auth.error.invalid_email_or_password",
// A sign-in or verification link that was used already, or is not one at all
INVALID_TOKEN: "auth.error.invalid_token",
TOKEN_EXPIRED: "auth.error.invalid_token",