halkyon/packages/halkyon_app/lib/l10n/halkyon_app_en.arb
Tizian 「ティツィアーン」 19aabb0266
fix(app): GitHub's refusals say why, and no hint adds GitHub where passwords are offered
Where an instance offers password sign-in, GitHub is added to nobody (ADR
0017, D2), yet the start screen still said "then add GitHub" after a GitHub
account nobody has, and every refusal but an unknown account read
"Couldn't sign in with GitHub." (the end-to-end test of 21 Oct).

- The gateway tells from one read of the basics whether GitHub signs in and
  whether it is added to people (`gitHubOffer`, in place of
  `gitHubClientId`); the GitHub bloc keeps it (`Ready.linking`) for the
  profile, with why an attempt failed (`Ready.problem`).
- The instance's `usePassword`, `deprecated` and `ended` become problems of
  their own (`gitHubSignInProblemOf`), worded by `gitHubProblemText` and on
  the start screen; an anonymous person refused a link is told the GitHub
  account is nobody's and offered the password instead.
- Where passwords are offered, the start screen offers an account to create
  in place of the app's hint on adding GitHub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-23 14:13:06 +02:00

541 lines
23 KiB
Text

{
"@@locale": "en",
"tryAgain": "Try again",
"instanceWelcome": "Welcome to {app}",
"@instanceWelcome": {
"description": "Screen readers hear it for the wordmark on the first start.",
"placeholders": {
"app": {
"type": "String"
}
}
},
"instanceBuiltInTagline": "Comes with the app",
"instanceAnother": "Another instance",
"instanceAnotherTagline": "Enter its address",
"instanceAddress": "Instance address",
"instanceAddressInvalid": "This isn't an address.",
"instanceAddressInsecure": "{app} reaches instances over HTTPS only, so that nobody on the way reads or changes what it sends. Ask for the instance's HTTPS address.",
"@instanceAddressInsecure": {
"placeholders": {
"app": {
"type": "String"
}
}
},
"instanceInsecure": "{name} is reached over plain HTTP, where anyone on the way could read and change what {app} sends, so {app} no longer opens it. Its account stays on {name} and on this device. Use another instance, or remove it from this device.",
"@instanceInsecure": {
"placeholders": {
"name": {
"type": "String"
},
"app": {
"type": "String"
}
}
},
"instanceInsecureUseAnother": "Use another instance",
"instanceInsecureRemove": "Remove from this device",
"instanceAddressRequired": "Enter the address of an instance.",
"instanceContinue": "Continue",
"instanceUnreachable": "No instance of {app} answers at {name}.",
"@instanceUnreachable": {
"placeholders": {
"app": {
"type": "String"
},
"name": {
"type": "String"
}
}
},
"instanceUseBuiltIn": "Use {name}",
"@instanceUseBuiltIn": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"instanceOpenFailed": "Couldn't open the app on {name}.",
"@instanceOpenFailed": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"instanceDataAndBackupsIn": "Data and backups: {place}",
"@instanceDataAndBackupsIn": {
"placeholders": {
"place": {
"type": "String"
}
}
},
"instanceDataIn": "Data: {place}",
"@instanceDataIn": {
"placeholders": {
"place": {
"type": "String"
}
}
},
"instanceBackupsIn": "Backups: {place}",
"@instanceBackupsIn": {
"placeholders": {
"place": {
"type": "String"
}
}
},
"instanceNoBackups": "No backups",
"instanceEuropeanUnion": "European Union",
"instanceCountryInEu": "{country} (EU)",
"@instanceCountryInEu": {
"description": "A country of the European Union, where an instance keeps data: Germany (EU).",
"placeholders": {
"country": {
"type": "String"
}
}
},
"instanceSubdivisionOf": "{subdivision}, {country}",
"@instanceSubdivisionOf": {
"description": "A state or region with its country, where an instance keeps data: California, United States.",
"placeholders": {
"subdivision": {
"type": "String"
},
"country": {
"type": "String"
}
}
},
"accountsTitle": "Accounts",
"accountAdd": "Add account",
"accountAddSubtitle": "Choose the instance for the account to add.",
"accountSignedIn": "Signed in",
"accountAnonymous": "Anonymous",
"accountRemoveTooltip": "Remove account",
"accountRemoveTitle": "Remove account?",
"accountRemoveMessage": "Removes the account on {name} from this device, with all the device holds of it. What it synced stays on {name}: sign in there again to have it. An anonymous account can't be signed into again.",
"@accountRemoveMessage": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"accountRemoveConfirm": "Remove",
"accountSignedInOn": "Signed in on {instance}",
"@accountSignedInOn": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"accountAnonymousOn": "Anonymous on {instance}",
"@accountAnonymousOn": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"accountSwitch": "Switch account",
"accountSignOut": "Sign out",
"accountSignOutTitle": "Sign out?",
"accountDelete": "Delete account",
"accountDeleteTitle": "Delete your account?",
"aboutSourceCode": "The source of what this instance runs:",
"aboutSourceUnreachable": "Couldn't reach this instance to ask where its source is.",
"sessionUnreachable": "Couldn't reach the server.",
"personDataFailed": "Couldn't open this device's data.",
"startSignedOut": "Signed out",
"startOn": "Start on {instance}:",
"@startOn": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"startWithGitHub": "Sign in with GitHub",
"startWithoutAccount": "Start without an account",
"startAnonymous": "Progress is saved on this device. Sign in to keep it.",
"startGitHubFailed": "Couldn't sign in with GitHub.",
"startNoGitHubAccount": "No account here signs in with this GitHub account yet.",
"gitHubCreateAccountInstead": "Create an account with your email address and a password instead.",
"@gitHubCreateAccountInstead": {
"description": "Said after a GitHub account nobody on the instance signs in with, where people sign in with a password and GitHub is added to nobody (ADR 0017)."
},
"gitHubNoAccountSetUpPassword": "No account here signs in with this GitHub account yet. To keep your progress, set up a password instead.",
"@gitHubNoAccountSetUpPassword": {
"description": "An anonymous person signed in with a GitHub account nobody here has, where GitHub is added to nobody: the password set up below keeps their account."
},
"gitHubUsePassword": "This account signs in with its email address and password now, not with GitHub.",
"gitHubDeprecated": "GitHub can't be added as a way to sign in any more: your email address and password are.",
"gitHubEnded": "Sign-in with GitHub has ended on this instance.",
"startOtherInstance": "Use another instance",
"syncTitle": "Sync",
"syncNow": "Sync now",
"syncStateSyncing": "Syncing…",
"syncStateSynced": "Everything synced",
"syncStateFailing": "Sync is failing",
"syncStateNotYet": "Not synced yet",
"syncStateMismatch": "This app can't sync with {server}",
"@syncStateMismatch": {
"placeholders": {
"server": {
"type": "String"
}
}
},
"syncMismatchDetail": "Update the app. If it is up to date, the server needs an update. What you do meanwhile stays on this device and syncs afterwards.",
"syncLastCompleted": "Last completed at {time}",
"@syncLastCompleted": {
"placeholders": {
"time": {
"type": "String"
}
}
},
"syncLastFailed": "Last attempt failed at {time}",
"@syncLastFailed": {
"placeholders": {
"time": {
"type": "String"
}
}
},
"syncNoRunYet": "No sync has completed since the app started",
"syncPending": "{count, plural, =1{1 change waits to sync} other{{count} changes wait to sync}}",
"@syncPending": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"syncTroubleLabel": "Sync needs attention",
"syncMismatchBanner": "This app can't sync with {server} any more. Update it to keep syncing.",
"@syncMismatchBanner": {
"placeholders": {
"server": {
"type": "String"
}
}
},
"syncMismatchMore": "More",
"startSignIn": "Sign in",
"startCreateAccount": "Create an account",
"startGitHubEnds": "Sign-in with GitHub ends on {date}.",
"@startGitHubEnds": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordAddress": "Email address",
"passwordPassword": "Password",
"passwordNewPassword": "New password",
"passwordCurrent": "Current password",
"passwordRepeat": "New password again",
"passwordsDiffer": "The two passwords differ.",
"passwordShow": "Show password",
"passwordHide": "Hide password",
"passwordContinue": "Continue",
"passwordBack": "Back",
"passwordDone": "Done",
"passwordSave": "Save as a file",
"passwordQrCode": "QR code for your authenticator app",
"passwordMailCode": "Code from the email",
"passwordMailCodeSent": "We emailed a code to {address}. It's valid for 15 minutes.",
"@passwordMailCodeSent": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"passwordResendCode": "Send a new code",
"passwordTotpCode": "Code from your authenticator app",
"passwordRecoveryCode": "Recovery code",
"passwordUseRecoveryCode": "Use a recovery code instead",
"passwordUseTotpCode": "Use your authenticator app instead",
"passwordUnlocking": "Unlocking your password on this device…",
"passwordMakingKeys": "Making your keys on this device…",
"passwordSignInTitle": "Sign in",
"passwordSignInAction": "Sign in",
"passwordSignInIntro": "With the email address and password of your account on {instance}.",
"@passwordSignInIntro": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"passwordSecondFactorIntro": "Enter the code your authenticator app shows for {instance}.",
"@passwordSecondFactorIntro": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"passwordRecoveryCodeIntro": "Enter one of the recovery codes you kept. Each signs in once.",
"passwordForgot": "Forgot your password?",
"passwordOtherPassword": "Change the address or password",
"passwordLostAuthenticator": "Lost your authenticator?",
"passwordLostAuthenticatorTitle": "Lost authenticator",
"passwordLostAuthenticatorIntro": "With a recovery code you sign in as usual. Without one, ask to reset your authenticators: it takes effect 72 hours later, and signing in with a code before then stops it.",
"passwordResetWithMail": "Reset with a code by email",
"passwordResetWithMailHint": "We email a code to {address}.",
"@passwordResetWithMailHint": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"passwordResetWithPhrase": "Reset with your recovery phrase",
"passwordResetWithPhraseHint": "The 24 words you wrote down.",
"passwordSignInWithoutCode": "Sign in without a code",
"passwordSignInWithoutCodeHint": "Once a reset you asked for has taken effect.",
"passwordResetAction": "Reset",
"passwordAuthenticatorResetAt": "Your authenticators are reset on {date}. We emailed you: if it wasn't you, sign in with a code before then to stop it. After that, sign in with your password alone and set up a new authenticator.",
"@passwordAuthenticatorResetAt": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordUnfinishedIntro": "Your account was never finished. We emailed a code to {address}: with it, you sign in and set up an authenticator.",
"@passwordUnfinishedIntro": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"passwordPhraseField": "Recovery phrase",
"passwordPhraseFieldHint": "The 24 words, with spaces between them",
"passwordPhraseFieldIntro": "Enter your recovery phrase: it proves the account is yours.",
"passwordAuthenticatorTitle": "Set up an authenticator",
"passwordAuthenticatorIntro": "Every sign-in takes a code from an authenticator app, such as Aegis, 2FAS or Proton Authenticator. Scan this code with it, or type in the key.",
"passwordAuthenticatorKey": "Key",
"passwordAuthenticatorOpen": "Open in your authenticator app",
"passwordAuthenticatorNoApp": "No app on this device opens it. Scan the code or type in the key.",
"passwordAuthenticatorCodeIntro": "Then enter the code it shows.",
"passwordAuthenticatorOwnerIntro": "To add it, confirm it is you: your password and a code from an authenticator you added before.",
"passwordExistingCode": "Code from an authenticator you added before",
"passwordRecoveryCodesTitle": "Recovery codes",
"passwordRecoveryCodesIntro": "Each signs in once in place of a code from your authenticator, should you lose it. Keep them where only you find them: they're shown only now.",
"passwordCodesKept": "I've kept them",
"passwordPhraseTitle": "Your recovery phrase",
"passwordPhraseIntro": "These 24 words open your account's keys should you forget your password: without them, what's encrypted is lost. Write them down in order, and keep them where only you find them. They're shown only now.",
"passwordPhraseWrittenDown": "I've written it down",
"passwordPhraseCheckTitle": "Check your recovery phrase",
"passwordPhraseCheckIntro": "Type the words asked for, from what you wrote down.",
"passwordPhraseWord": "Word {number}",
"@passwordPhraseWord": {
"placeholders": {
"number": {
"type": "int"
}
}
},
"passwordPhraseWrong": "These aren't the words. Look again at what you wrote down.",
"passwordPhraseShowAgain": "Show the phrase again",
"passwordCreateTitle": "Create an account",
"passwordCreateIntro": "On {instance}, with your email address, a password, and an authenticator app for the code every sign-in takes.",
"@passwordCreateIntro": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"passwordSetUpTitle": "Set up a password",
"passwordSetUpIntro": "Sign in with your email address, a password and an authenticator app, on this device and others. Everything you have stays.",
"passwordChooseIntro": "Choose a password. It never leaves this device: the instance can't read it, and can't reset it without what it protects being lost.",
"passwordFinishResetTitle": "Finish the reset",
"passwordFinishResetIntro": "72 hours after you asked to reset your account, finish it here with a new code by email.",
"passwordFinishResetHavePhrase": "I have my recovery phrase",
"passwordFinishResetKeepsKeys": "Your account keeps its keys: nothing encrypted is lost.",
"passwordFinishResetNewKeys": "Without your recovery phrase, your account gets new keys: what was encrypted with the old ones is lost.",
"passwordRecoveryTitle": "Get back into your account",
"passwordRecoveryWithPhrase": "I have my recovery phrase",
"passwordRecoveryWithPhraseHint": "Set a new password at once. Everything stays.",
"passwordRecoveryWithPhraseIntro": "Your recovery phrase opens your account's keys, which your new password then protects. A code from your authenticator, or a recovery code, confirms it.",
"passwordRecoveryNoCodeHint": "Lost your authenticator as well? Reset your account 72 hours later with your recovery phrase: it keeps everything.",
"passwordRecoveryWithoutPhrase": "Reset my account",
"passwordRecoveryWithoutPhraseHint": "Takes effect 72 hours later. Without your recovery phrase, what's encrypted is lost.",
"passwordRecoveryStartIntro": "We email a code to your address. Your account can then be reset 72 hours later; signing in with your password before then stops it.",
"passwordRecoveryFinish": "Finish a reset",
"passwordRecoveryFinishHint": "72 hours after you asked for it.",
"passwordResetStarted": "Your account can be reset from {date}. We emailed you: if it wasn't you, sign in with your password before then to stop it.",
"@passwordResetStarted": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordSectionTitle": "Password and authenticator",
"passwordSectionFailed": "Couldn't read how your account signs in.",
"passwordSectionGitHubEnds": "Sign-in with GitHub ends on {date}. Set up a password before then to keep your account.",
"@passwordSectionGitHubEnds": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordSectionSetUp": "Set up a password",
"passwordSectionSetUpHint": "Sign in with your email address, a password and an authenticator app.",
"passwordSectionUnfinished": "Finish setting up: add an authenticator",
"passwordSectionUnfinishedHint": "Your password signs in once an authenticator is set up.",
"passwordSectionChange": "Change password",
"passwordSectionKeysMissing": "Sign in on this device with your password to change it.",
"passwordSectionNotConfirmed": "Not set up yet",
"passwordSectionRemove": "Remove {name}?",
"@passwordSectionRemove": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"passwordSectionRemoveIntro": "Enter your password and a code from one of your authenticators to confirm.",
"passwordSectionRemoveAction": "Remove",
"passwordSectionAddAuthenticator": "Add an authenticator",
"passwordSectionRecoveryCodes": "New recovery codes",
"passwordSectionRecoveryCodesHint": "The old ones stop working.",
"passwordSectionNewPhrase": "New recovery phrase",
"passwordSectionPhraseHint": "Your old phrase stops working.",
"passwordChangeTitle": "Change password",
"passwordChangeIntro": "Your other devices are signed out. Your keys stay: nothing is lost.",
"passwordChangeAction": "Change password",
"passwordChanged": "Password changed. Your other devices are signed out.",
"passwordNewCodesIntro": "Enter your password and a code from your authenticator app. Your old recovery codes stop working.",
"passwordNewPhraseIntro": "Your new recovery phrase. Write the 24 words down in order: once you confirm it, your old phrase opens nothing any more.",
"passwordPhraseKept": "New recovery phrase set. The old one no longer works.",
"passwordWrongCredentials": "The address, the password or the code isn't right.",
"passwordTooManyAttempts": "Too many attempts. Try again in an hour.",
"passwordSetupIncomplete": "Your account was never finished: set up an authenticator.",
"passwordNotDue": "This takes effect on {date}.",
"@passwordNotDue": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordNotDueYet": "This hasn't taken effect yet.",
"passwordNoReset": "No reset waits for this address.",
"passwordExists": "This address's account has a password already. Sign in with it, or get back in if you've forgotten it.",
"passwordAddressTaken": "This address belongs to another account.",
"passwordNoAddress": "Your account has no email address yet.",
"passwordNoPassword": "This account has no password.",
"passwordWrongCode": "This code isn't right. Enter the one your app shows now.",
"passwordLastAuthenticator": "Your last authenticator can't go: every sign-in needs one.",
"passwordTooManyAuthenticators": "Your account has as many authenticators as it may. Remove one first.",
"passwordUnknownAuthenticator": "This authenticator is gone.",
"passwordInvalidSetup": "The instance didn't accept what this device made. Update the app, or try again.",
"passwordChallengeExpired": "That took too long. Try again.",
"passwordUnavailable": "This instance offers no password sign-in.",
"passwordNotAnAddress": "This isn't an email address.",
"passwordTooManyCodes": "Too many codes asked for. Try again in an hour.",
"passwordWrongMailCode": "This code isn't right.",
"passwordTooManyMailTries": "Too many wrong codes. Ask for a new one.",
"passwordMailCodeExpired": "This code is no longer valid. Ask for a new one.",
"passwordMailFailed": "The instance couldn't send the email. Try again later.",
"passwordOtherAddressLinked": "Your account has another email address.",
"passwordNotAPhrase": "This isn't a recovery phrase: check every word and their number.",
"passwordPhraseDoesNotFit": "The address or the recovery phrase isn't right.",
"passwordUnusable": "This password can't be used: it's empty, or holds characters that aren't text.",
"passwordInstanceUnproven": "The instance couldn't prove it knows your password, so this device trusts nothing it says. Try again; if it happens again, the instance isn't the one it claims to be.",
"passwordKeysMissing": "Your account's keys aren't on this device. Sign out and in again with your password here.",
"passwordUnsafeCosts": "The instance asked for your password to be checked in a way no account uses, so nothing was sent. If it happens again, the instance isn't the one it claims to be.",
"passwordFailed": "Couldn't reach the instance. Check the connection and try again.",
"passwordMinLength": "At least {count} characters",
"@passwordMinLength": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"passwordTooShort": "A new password needs at least {count} characters: should the instance's database ever leak, a short one is guessed first.",
"@passwordTooShort": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"passwordCodesWait": "Too many wrong codes in a row: no code is taken until {date}. If they weren't yours, someone knows your password: change it then.",
"@passwordCodesWait": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordDeleteIntro": "Your account goes with everything in it, in every service of this instance. To confirm, type your password and a code from your authenticator app.",
"passwordSessionEnded": "Too many wrong codes in a row from this device: it was signed out. Sign in again with your password and a code.",
"passwordAddressUnknown": "Enter your account's email address: the code goes there.",
"passwordDeleteIntroByMail": "Your account goes with everything in it, in every service of this instance. None of its authenticators works now, so a code by mail confirms it: type your password, then the code we email to your address.",
"passwordDeleteSendCode": "Email me a code",
"passwordSignInAgain": "To give an account that signs in with GitHub its password, sign in with GitHub again first: it has been more than a few minutes.",
"passwordSignInWithGitHubAgain": "Sign in with GitHub again",
"passwordOfferTitle": "Set up a password",
"passwordOfferBody": "Sign-in with GitHub is ending. Set up a password and an authenticator app to keep your account.",
"passwordOfferLater": "Later",
"passwordAuthenticatorPasswordIntro": "To add it, confirm it is you with your password.",
"passwordWarningTitle": "Someone tried your password",
"passwordWarningBody": "On {date}, a device signed in to your account sent a wrong password or code ten times in a row, and was signed out. If that wasn't you, someone else may have that device or its session: change your password.",
"@passwordWarningBody": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordWarningDismiss": "Dismiss",
"passwordWarningLater": "Remind me later",
"passwordResetsTitle": "A reset is waiting",
"passwordResetsAuthenticator": "Your authenticators will be removed on {date}: someone asked with your password. If that wasn't you, call it off and change your password.",
"@passwordResetsAuthenticator": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordResetsAccount": "Your account will get a new password and new keys on {date}, and what is encrypted under the old ones will be lost: someone asked with a code by mail. If that wasn't you, call it off.",
"@passwordResetsAccount": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordResetsCallOff": "Call it off",
"passwordCallOffTitle": "Call off the reset",
"passwordCallOffIntro": "Your password and a code call off every reset waiting.",
"passwordSectionGitHubEndsDeletes": "Sign-in with GitHub ends on {date}. Set up a password before then: an account without one is deleted 30 days later, with everything in it.",
"@passwordSectionGitHubEndsDeletes": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"passwordSignedInBefore": "Only a device signed in since then can dismiss this warning: sign in again on this one, or change your password."
}