halkyon/packages/halkyon_app/lib/l10n/halkyon_app_en.arb

1589 lines
63 KiB
Text
Raw Normal View History

{
"@@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",
"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.",
"@accountRemoveMessage": {
"placeholders": {
"name": {
"type": "String"
}
}
},
"accountRemoveConfirm": "Remove",
"accountSignedInOn": "Signed in on {instance}",
"@accountSignedInOn": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"accountSwitch": "Switch account",
"accountSignOut": "Sign out",
"accountDelete": "Delete account",
"accountDeleteTitle": "Delete your account?",
"accountSignOutFailed": "Couldn't sign out on this device. Try again.",
"accountDeleteFailed": "Couldn't delete your account: the instance wasn't reached. Try again.",
"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"
}
}
},
"startOtherInstance": "Use another instance",
"startNoWay": "{instance} offers no way to create an account.",
"@startNoWay": {
"description": "On the start screen, where the instance offers neither SimpleLogin nor a password (ADR 0020, D4): nobody can make an account there.",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"startSignUpsApproved": "New accounts on {instance} wait until its operator approves them.",
"@startSignUpsApproved": {
"description": "On the start screen, where new accounts wait for the operator's approval (Halkyon Learn's ADR 0021, D19).",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"startSignUpsClosed": "{instance} takes no new accounts: sign in with yours.",
"@startSignUpsClosed": {
"description": "On the start screen, where the operator takes no new accounts (D19); Create an account is gone.",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"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"
}
}
},
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"syncMismatchMore": "More",
"startSignIn": "Sign in",
"startCreateAccount": "Create an account",
"waitWaiting": "Your account waits until the operator of {instance} approves it.",
"@waitWaiting": {
"description": "On the wait screen of a new account (D31), under its handle.",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"waitSuspended": "The operator of {instance} has suspended your account. Only they can lift it.",
"@waitSuspended": {
"description": "On the wait screen of a suspended account (D31).",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"waitApproved": "The operator of {instance} has approved your account. Sign in once more, as you did before.",
"@waitApproved": {
"description": "On the wait screen once the account is approved (D31), above Sign in.",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"waitEnded": "This sign-up has ended: the operator of {instance} refused it, or it waited too long.",
"@waitEnded": {
"description": "On the wait screen once the instance knows the wait no more: refused, past its 14 days, or its pass past its 30 (D31).",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"waitBack": "Back to the start",
"@waitBack": {
"description": "The button of an ended wait: the start screen."
},
"waitMatchingCode": "Matching code",
"@waitMatchingCode": {
"description": "Above the four words the operator reads out for the person to match (D33)."
},
"waitMatchingNote": "When the operator of {instance} reads you four words, check that they are these. Never read them out yourself: Halkyon never asks anyone to.",
"@waitMatchingNote": {
"description": "Under the matching code (D33): the operator reads, the person confirms, so nobody posing as the operator learns the words.",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"waitCheckNow": "Check now",
"@waitCheckNow": {
"description": "Asks the instance at once where the wait stands; it asks every 30 seconds by itself."
},
"waitUnreachable": "{instance} couldn't be reached. It's asked again every 30 seconds.",
"@waitUnreachable": {
"description": "On the wait screen, when asking where the wait stands failed.",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"waitDelete": "Delete this account",
"@waitDelete": {
"description": "On the wait screen of a new account: deletes it with its pass (D31)."
},
"waitDeleteTitle": "Delete this account?",
"@waitDeleteTitle": {
"description": "The question before a waiting account is deleted."
},
"waitDeleteMessage": "It goes with everything it has, and nobody can sign in to it again.",
"@waitDeleteMessage": {
"description": "Under that question."
},
"waitDeleteFailed": "Couldn't delete the account. Try again.",
"@waitDeleteFailed": {
"description": "On the wait screen, when deleting the account failed."
},
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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"
}
}
},
feat(base)!: a handle at password sign-up (ADR 0020, D26, D28–D30) Every new account gets a handle, and an account without one gets its first as it sets a password. The handle is private until its person goes public (D5). - `passwordSignIn.signUp` takes a handle. `passwordSignIn.checkHandle` says whether a sign-up could take one, only while that sign-up's mailed code waits (`codeExpired` otherwise), counted per code request (30 an hour) and per network (60) (D29). Members ask the register. - `password.set` takes the first handle of an account without one (D28); `SignInWays.handle` tells the app whether there is one. - Each checks the handle before the code is used, so a refusal leaves the code for another try. An existing account at the address keeps its own handle where it has one, and the typed handle is still checked, so the answer says nothing about the address. - `first_handle.dart` holds what SimpleLogin, the keys and passwords share: `refusalOfNewHandle`, `insertFirstProfile`, `hasHandle`. - halkyon_app: one `HandleField` with its `HandleCheckCubit` (asked 300 ms after typing pauses, only about the handle typed last; the instance's suggestion is free without asking) (D30). The password setup asks for the handle between the phrase check and the code, and a refusal at the code sends back to it. SimpleLogin's sign-up and keys steps use the same field and now check as it is typed. - The module's README and ADR 0020 (D29, D30, the built state) amended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 18:09:04 +02:00
"passwordHandleIntro": "A code is on its way to {address}. Meanwhile, choose your handle: others find you by it. It stays private until you publish something or fill in your profile, and can change until your first publish.",
"@passwordHandleIntro": {
"placeholders": {
"address": {
"type": "String"
}
}
},
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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",
"passwordAuthenticatorKeyCopied": "Key copied. It's taken off the clipboard again in a minute.",
"@passwordAuthenticatorKeyCopied": {
"description": "After the authenticator's key was copied during its setup; the app empties the clipboard 60 seconds later."
},
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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.",
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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.",
"passwordPhraseNotAWord": "Not a word a recovery phrase is made of",
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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.",
"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.",
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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.",
feat(app): sign in with a password and TOTP on the device ADR 0017, step 3: halkyon_app's side, which Learn and Todo take. - The account's cryptography on the device (`SodiumAccountCrypto`): halkyon_keys and SRP's client half, each step on an isolate of its own. sodium hands out results as views of native memory its finalizers free once the isolate that made them ends, so everything crossing back is copied first: a view read freed memory and crashed the process. - `PasswordGateway` on the module's endpoints (steps without a session through a client holding none; an authenticator set up with a session granted but not yet the device's), and `PasswordRepository` running the flows: signing in (M2 checked, the keys opened before anything is trusted), signing up, a password for someone signed in, an account never finished, the authenticators, recovery codes, changing the password, a new recovery phrase, and getting back in. - The unlocked keys in the system's keyring per instance and person (`SecureAccountKeyStore`), gone once another person signs in or nobody, and with the instance's removal. - The screens: the start screen's Sign in and Create an account (and when GitHub sign-in ends), the sign-in sheet (codes, recovery codes, an account never finished, a lost authenticator), the account's setup (the recovery phrase shown once, three random words typed back before anything reaches the instance; the authenticator's QR code, drawn with pub.dev's qr; the recovery codes), getting back in, and the account section (`AccountSecuritySection`). - `FileSaver` moves from Learn into halkyon_app, for the phrase and the codes in Todo too; `AppDependencies` names it and `passwords`. - halkyon_keys rebuilds account keys from the secret keys a device kept; the key proof's message is in halkyon_base_client, checked against the register's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 15:42:45 +02:00
"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.",
"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.",
"signUpsClosed": "This instance takes no new accounts.",
"@signUpsClosed": {
"description": "A sign-up refused: the operator takes no new accounts (D19)."
},
feat(app,learn,todo): the operator's "This instance" card, screen and badge (ADR 0021, step 1) Whoever operates the instance approves, refuses and suspends accounts and names other operators in the app (D21 to D24, D34): - halkyon_app: InstanceOperatorRepository on ServerpodInstanceOperatorGateway (the module's instanceOperator endpoint; refusals as OperatorFailed: notFound, isOperator, lastOperator, notAllowed for 401 and 403, failed), in AppDependencies. OperatingCubit counts the accounts that wait: asked as the person's app opens, after every change, and every 5 minutes only while they operate the instance, so nobody else's app keeps asking. InstanceOperatorCard (or its tiles) and WaitingAccountsBadge show nothing at all for anyone else. InstanceOperatorScreen, laid out as Settings: the accounts that wait, each showing its four words to read out before Approve (D33), Refuse for new ones after asking; who operates, Take back after asking, the last always kept; Name an operator by handle; Find an account by the start of its handle, with Suspend after asking and Name as operator. English and German texts ("Admin" as the role word in German). - Learn: the card right after the Sync card in Settings, which the cogs' count leads to as their dot leads to Sync; the count on the Settings cogs of Home and Profile. - Todo: the tiles in the account sheet and the count on its button. Todo's server is a member, whose `operating()` is always null, so nothing shows there until it holds the register. Tests: the gateway's mapping, the repository, both cubits with their denials, the card, the badge and the screen; Learn's Settings shows the card and the count to an operator and neither to anyone else. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 15:55:28 +01:00
"signUpsTooManyWaiting": "Too many new accounts already wait for approval. Try again later.",
"@signUpsTooManyWaiting": {
"description": "A sign-up refused: ten new accounts wait for the operator's approval already (D19)."
},
"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"
}
}
fix(auth): codes wait after ten wrong in a row, and the owner is told Whoever knew the password could guess codes at 10 an hour forever, unnoticed, each guess checked against every authenticator (the second reading's M4). Every code an account's second factor refuses after a right password (sign-in, a phrase's reset, a change) or from a signed-in device (removing an authenticator, new recovery codes, the code from one confirmed before) now counts, per account, from every network; after every tenth in a row no code is taken (codesWait, saying until when), an hour, then twice as long each time, a day at the most (longestCodeWait, second_factor_waits.dart): at a day, ten guesses a day still have about a 1 % chance a year against one authenticator, so the first wait mails the owner that someone knows their password. The instance keeps no address, so sign-in and the phrase's reset now send the address the device typed (and its language), used only for that mail after its hash is checked against the account's. A code accepted clears it all. Migration (module, Learn's and Todo's servers, Learn's device schema): CREATE TABLE "second_factor_failures" ("id" bigserial PRIMARY KEY, "authUserId" uuid NOT NULL, "failures" bigint NOT NULL, "waits" bigint NOT NULL, "waitUntil" timestamp, "updatedAt" timestamp NOT NULL) with a unique index on "authUserId": a new table, nothing touched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 21:47:38 +02:00
},
"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"
}
}
},
fix(auth): a session's wrong codes end the session, not the account's codes Wrong codes for removing an authenticator, new recovery codes or confirming one counted toward the account's waits (the re-review's third finding): a stolen session alone, without the password, could keep the owner's codes waiting for up to a day at a time, renewed without end, holding them out of signing in and of changing the password, the way to end that session, and nobody was mailed. Those codes now count per session, where the session is (the register's own, or a member's, which forwards the code): each try counted before its code is checked (one statement, so tries sent at once count each), a code accepted clearing the count, and the tenth wrong in a row ending the session (sessionEnded; the device says it was signed out). A try that checked no code (a refusal of something else) is taken back. The account's waits now count only codes after a right password, and the per-account ten tries an hour, which a session could fill as well, go. Migration (module, Learn's and Todo's servers, Learn's device schema): CREATE TABLE "session_code_failures" ("id" bigserial PRIMARY KEY, "sessionId" uuid NOT NULL, "authUserId" uuid NOT NULL, "failures" bigint NOT NULL, "updatedAt" timestamp NOT NULL) with a unique index on "sessionId": a new table, nothing touched. Its rows go with a code accepted, with the person, and hourly once their session is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-20 22:53:20 +02:00
"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",
"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.",
feat(app): signing in with SimpleLogin, its sheet and the start screen's offer (ADR 0020) Where the instance offers SimpleLogin, the start screen offers it first, saying that the instance keeps only the SimpleLogin ID, and opens a sheet that waits for SimpleLogin's page in the browser (Cancel ends the wait), then: for someone new, the choice between creating an account (the suggested handle or another, checked with the instance, the password twice, the recovery phrase shown once and three of its words typed back, nothing reaching the instance before) and linking theirs again with its handle and recovery phrase; for an account, its password opening its keys; for an account of before, the keys made with the handle it lacks. SimpleLoginCubit holds the steps, each refusal shown where it is mended (a handle's on the handle, a sign-in to begin again on the browser's), and closing the sheet stops waiting on the loopback. The suggested handle is never checked: the instance suggests none that anybody has, and every answer about a handle counts against its limit (D5). The fake's handle rule is now the module's. Learn and Todo build it with SimpleLogin's browser (halkyon_oidc_flutter, now a direct dependency of both, with their names on the loopback's page), their schemes and their loopback ports (43823, 43824), as the instance's forwarding page has them. Their tests offer no SimpleLogin; halkyon_app's test the sheet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 01:21:29 +02:00
"passwordSignedInBefore": "Only a device signed in since then can dismiss this warning: sign in again on this one, or change your password.",
"simpleLoginContinue": "Continue with SimpleLogin",
"simpleLoginNote": "SimpleLogin is Proton's sign-in, and a Proton account works there too. It learns that you use {instance}, which keeps only your SimpleLogin ID: your name suggests a handle once, and nothing else is kept.",
"@simpleLoginNote": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"simpleLoginTitle": "Sign in with SimpleLogin",
"simpleLoginAddTitle": "Add SimpleLogin",
"simpleLoginInBrowser": "Continue in your browser.",
"simpleLoginNewcomerTitle": "New here?",
"simpleLoginNewcomerIntro": "Your SimpleLogin account has no account on {instance} yet.",
"@simpleLoginNewcomerIntro": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"simpleLoginCreateHint": "Choose a handle and a password; you get a recovery phrase.",
"simpleLoginHaveOne": "I already have one",
"simpleLoginHaveOneHint": "Link it again with your handle and your recovery phrase.",
feat(base)!: a handle at password sign-up (ADR 0020, D26, D28–D30) Every new account gets a handle, and an account without one gets its first as it sets a password. The handle is private until its person goes public (D5). - `passwordSignIn.signUp` takes a handle. `passwordSignIn.checkHandle` says whether a sign-up could take one, only while that sign-up's mailed code waits (`codeExpired` otherwise), counted per code request (30 an hour) and per network (60) (D29). Members ask the register. - `password.set` takes the first handle of an account without one (D28); `SignInWays.handle` tells the app whether there is one. - Each checks the handle before the code is used, so a refusal leaves the code for another try. An existing account at the address keeps its own handle where it has one, and the typed handle is still checked, so the answer says nothing about the address. - `first_handle.dart` holds what SimpleLogin, the keys and passwords share: `refusalOfNewHandle`, `insertFirstProfile`, `hasHandle`. - halkyon_app: one `HandleField` with its `HandleCheckCubit` (asked 300 ms after typing pauses, only about the handle typed last; the instance's suggestion is free without asking) (D30). The password setup asks for the handle between the phrase check and the code, and a refusal at the code sends back to it. SimpleLogin's sign-up and keys steps use the same field and now check as it is typed. - The module's README and ADR 0020 (D29, D30, the built state) amended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 18:09:04 +02:00
"handleIntro": "Others find you by your handle. It stays private until you publish something or fill in your profile, and can change until your first publish.",
"handleLabel": "Handle",
"handleFree": "@{handle} is free",
"@handleFree": {
feat(app): signing in with SimpleLogin, its sheet and the start screen's offer (ADR 0020) Where the instance offers SimpleLogin, the start screen offers it first, saying that the instance keeps only the SimpleLogin ID, and opens a sheet that waits for SimpleLogin's page in the browser (Cancel ends the wait), then: for someone new, the choice between creating an account (the suggested handle or another, checked with the instance, the password twice, the recovery phrase shown once and three of its words typed back, nothing reaching the instance before) and linking theirs again with its handle and recovery phrase; for an account, its password opening its keys; for an account of before, the keys made with the handle it lacks. SimpleLoginCubit holds the steps, each refusal shown where it is mended (a handle's on the handle, a sign-in to begin again on the browser's), and closing the sheet stops waiting on the loopback. The suggested handle is never checked: the instance suggests none that anybody has, and every answer about a handle counts against its limit (D5). The fake's handle rule is now the module's. Learn and Todo build it with SimpleLogin's browser (halkyon_oidc_flutter, now a direct dependency of both, with their names on the loopback's page), their schemes and their loopback ports (43823, 43824), as the instance's forwarding page has them. Their tests offer no SimpleLogin; halkyon_app's test the sheet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 01:21:29 +02:00
"placeholders": {
"handle": {
"type": "String"
}
}
},
feat(base)!: a handle at password sign-up (ADR 0020, D26, D28–D30) Every new account gets a handle, and an account without one gets its first as it sets a password. The handle is private until its person goes public (D5). - `passwordSignIn.signUp` takes a handle. `passwordSignIn.checkHandle` says whether a sign-up could take one, only while that sign-up's mailed code waits (`codeExpired` otherwise), counted per code request (30 an hour) and per network (60) (D29). Members ask the register. - `password.set` takes the first handle of an account without one (D28); `SignInWays.handle` tells the app whether there is one. - Each checks the handle before the code is used, so a refusal leaves the code for another try. An existing account at the address keeps its own handle where it has one, and the typed handle is still checked, so the answer says nothing about the address. - `first_handle.dart` holds what SimpleLogin, the keys and passwords share: `refusalOfNewHandle`, `insertFirstProfile`, `hasHandle`. - halkyon_app: one `HandleField` with its `HandleCheckCubit` (asked 300 ms after typing pauses, only about the handle typed last; the instance's suggestion is free without asking) (D30). The password setup asks for the handle between the phrase check and the code, and a refusal at the code sends back to it. SimpleLogin's sign-up and keys steps use the same field and now check as it is typed. - The module's README and ADR 0020 (D29, D30, the built state) amended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 18:09:04 +02:00
"handleChecking": "Checking…",
feat(app): signing in with SimpleLogin, its sheet and the start screen's offer (ADR 0020) Where the instance offers SimpleLogin, the start screen offers it first, saying that the instance keeps only the SimpleLogin ID, and opens a sheet that waits for SimpleLogin's page in the browser (Cancel ends the wait), then: for someone new, the choice between creating an account (the suggested handle or another, checked with the instance, the password twice, the recovery phrase shown once and three of its words typed back, nothing reaching the instance before) and linking theirs again with its handle and recovery phrase; for an account, its password opening its keys; for an account of before, the keys made with the handle it lacks. SimpleLoginCubit holds the steps, each refusal shown where it is mended (a handle's on the handle, a sign-in to begin again on the browser's), and closing the sheet stops waiting on the loopback. The suggested handle is never checked: the instance suggests none that anybody has, and every answer about a handle counts against its limit (D5). The fake's handle rule is now the module's. Learn and Todo build it with SimpleLogin's browser (halkyon_oidc_flutter, now a direct dependency of both, with their names on the loopback's page), their schemes and their loopback ports (43823, 43824), as the instance's forwarding page has them. Their tests offer no SimpleLogin; halkyon_app's test the sheet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 01:21:29 +02:00
"simpleLoginPasswordIntro": "Choose a password: you type it when you sign in on another device. It never leaves this device: the instance can't read it, and can't reset it without what it protects being lost.",
"simpleLoginCreate": "Create the account",
"simpleLoginUnlockTitle": "Your password",
"simpleLoginUnlockIntroAs": "Signed in with SimpleLogin as @{handle}. Your password opens your keys on this device.",
"@simpleLoginUnlockIntroAs": {
"placeholders": {
"handle": {
"type": "String"
}
}
},
"simpleLoginUnlockIntro": "Signed in with SimpleLogin. Your password opens your keys on this device.",
"simpleLoginOpen": "Open",
"simpleLoginMendTitle": "Link your account",
"simpleLoginMendIntro": "Your SimpleLogin account isn't the one your account knows any more. Link them again with your handle and your recovery phrase: your other devices are then signed out.",
"simpleLoginMend": "Link",
"simpleLoginWrongPassword": "The password isn't right.",
"simpleLoginMendDoesNotFit": "The handle or the recovery phrase isn't right.",
"simpleLoginForgotTitle": "A new password",
"simpleLoginForgotIntro": "Your recovery phrase opens your keys, which your new password then protects. Everything stays; your other devices are signed out.",
"simpleLoginForgotDoesNotFit": "The recovery phrase isn't right.",
feat(app): a reset of the keys without the phrase, its banner, and the keys' proof key for a password that signs in (ADR 0020, D31–D35) SimpleLogin's sheet, its password and its recovery phrase both lost: under the lost-password step's phrase field, Lost your recovery phrase too? says what stays and what is lost and asks for new keys (`keys.startReset`) with the sign-in of a moment ago, which the device then drops. The next sign-in says when while it waits, and once due offers new keys, the sign-up's own password and phrase steps (`keys.completeReset`), or the password, which calls it off (D31). Every app's home shows `KeysResetBanner` where "too old" shows, and the account section's SimpleLogin row the same words (`KeysResetNotice`), each with Call it off, the password's proof alone (`keys.callOffResets`, D32), and, once due on a device that holds the keys, Finish here, which wraps the same keys anew (D33, D35). Both show only a reset of an account that signs in with SimpleLogin alone; ADR 0017's resets show in its own section, which now shares `AlertBox` with them. An account whose password signs in has no Forgot your password? there, and is asked its password and a code once while its keys lack the proof key, at a sign-in or on adding SimpleLogin (`password.setProofKey`, D34). `PasswordUnlock` carries the proof key, which its forgetting leaves, and the keys' password proves for a purpose given. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 22:37:17 +02:00
"simpleLoginResetWaiting": "New keys were asked for: from {date}, a SimpleLogin sign-in can set them up. Your password opening your keys calls it off.",
"@simpleLoginResetWaiting": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"simpleLoginPhraseLost": "Lost your recovery phrase too?",
"simpleLoginResetTitle": "New keys",
"simpleLoginResetIntro": "Without your password or your recovery phrase, nobody can open your keys, not even {instance}. New ones can be set up 72 hours from now, when you sign in with SimpleLogin again. Your handle, your profile and what you published stay; what was encrypted under your old keys is lost, unless you finish on a device still signed in, which keeps them.",
"@simpleLoginResetIntro": {
"placeholders": {
"instance": {
"type": "String"
}
}
},
"simpleLoginResetIntroDevices": "Meanwhile your signed-in devices show the reset, and your password calls it off there, should someone else have asked for it.",
"simpleLoginResetAsk": "Ask for new keys",
"simpleLoginResetAskedTitle": "New keys asked for",
"simpleLoginResetAskedIntro": "From {date}, sign in with SimpleLogin again to set them up. Should you find your password or your recovery phrase before then, opening your keys with it calls the reset off.",
"@simpleLoginResetAskedIntro": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"simpleLoginResetDueTitle": "Your new keys",
"simpleLoginResetDueIntro": "The new keys you asked for can be set up now. Or open your old keys with your password, which calls the reset off.",
"simpleLoginResetNewKeys": "Set up new keys",
"simpleLoginResetNewKeysHint": "A new password and recovery phrase. What was encrypted under your old keys is lost, unless you finish on a device still signed in.",
"simpleLoginResetHavePassword": "I have my password",
"simpleLoginResetHavePasswordHint": "Your keys open, and stay.",
"simpleLoginResetKeepIntro": "Choose a new password: your keys stay, under it and a new recovery phrase, so nothing is lost. Your other devices are signed out.",
"simpleLoginResetFinish": "Set up the keys",
"simpleLoginProofKeyTitle": "Your password and a code",
"simpleLoginProofKeyIntroAs": "Signed in with SimpleLogin as @{handle}. Your account also signs in with a password: type it and a code from your authenticator once, and your password opens your keys after SimpleLogin from then on.",
"@simpleLoginProofKeyIntroAs": {
"placeholders": {
"handle": {
"type": "String"
}
}
},
"simpleLoginProofKeyIntro": "Your account also signs in with a password: type it and a code from your authenticator once, and your password opens your keys after SimpleLogin from then on.",
"simpleLoginResetBanner": "New keys were asked for with your SimpleLogin account: from {date}, whoever has it can set them up. Unless that was you, call it off with your password.",
"@simpleLoginResetBanner": {
"placeholders": {
"date": {
"type": "String"
}
}
},
"simpleLoginResetBannerDue": "New keys were asked for with your SimpleLogin account, and whoever has it can set them up now. Unless that was you, call it off with your password.",
"simpleLoginResetBannerDueHere": "New keys were asked for with your SimpleLogin account and can be set up now. If that was you, finish here: your keys stay. If not, call it off with your password.",
"simpleLoginResetFinishHere": "Finish here",
"simpleLoginCallOffIntro": "Your password calls off the reset of your keys.",
"simpleLoginResetCalledOff": "Reset called off.",
"simpleLoginResetFinished": "New password and recovery phrase set.",
feat(app): signing in with SimpleLogin, its sheet and the start screen's offer (ADR 0020) Where the instance offers SimpleLogin, the start screen offers it first, saying that the instance keeps only the SimpleLogin ID, and opens a sheet that waits for SimpleLogin's page in the browser (Cancel ends the wait), then: for someone new, the choice between creating an account (the suggested handle or another, checked with the instance, the password twice, the recovery phrase shown once and three of its words typed back, nothing reaching the instance before) and linking theirs again with its handle and recovery phrase; for an account, its password opening its keys; for an account of before, the keys made with the handle it lacks. SimpleLoginCubit holds the steps, each refusal shown where it is mended (a handle's on the handle, a sign-in to begin again on the browser's), and closing the sheet stops waiting on the loopback. The suggested handle is never checked: the instance suggests none that anybody has, and every answer about a handle counts against its limit (D5). The fake's handle rule is now the module's. Learn and Todo build it with SimpleLogin's browser (halkyon_oidc_flutter, now a direct dependency of both, with their names on the loopback's page), their schemes and their loopback ports (43823, 43824), as the instance's forwarding page has them. Their tests offer no SimpleLogin; halkyon_app's test the sheet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 01:21:29 +02:00
"simpleLoginUnavailable": "This instance doesn't offer sign-in with SimpleLogin.",
"simpleLoginDenied": "SimpleLogin's sign-in was declined, so nothing was shared.",
"simpleLoginNoBrowser": "There's no browser to open SimpleLogin's page in.",
"simpleLoginStartAgain": "The sign-in took too long, or another one took its place. Begin it again.",
"simpleLoginRejected": "SimpleLogin didn't confirm the sign-in. Begin it again.",
"simpleLoginProviderUnavailable": "The instance can't reach SimpleLogin right now. Try again later.",
"simpleLoginTakenByAnotherPerson": "This SimpleLogin account belongs to another account here.",
"simpleLoginOtherIdentityLinked": "Your account has another SimpleLogin account already.",
"simpleLoginTooManyAttempts": "Too many sign-ins began from this network. Try again in an hour.",
feat(base)!: a handle at password sign-up (ADR 0020, D26, D28–D30) Every new account gets a handle, and an account without one gets its first as it sets a password. The handle is private until its person goes public (D5). - `passwordSignIn.signUp` takes a handle. `passwordSignIn.checkHandle` says whether a sign-up could take one, only while that sign-up's mailed code waits (`codeExpired` otherwise), counted per code request (30 an hour) and per network (60) (D29). Members ask the register. - `password.set` takes the first handle of an account without one (D28); `SignInWays.handle` tells the app whether there is one. - Each checks the handle before the code is used, so a refusal leaves the code for another try. An existing account at the address keeps its own handle where it has one, and the typed handle is still checked, so the answer says nothing about the address. - `first_handle.dart` holds what SimpleLogin, the keys and passwords share: `refusalOfNewHandle`, `insertFirstProfile`, `hasHandle`. - halkyon_app: one `HandleField` with its `HandleCheckCubit` (asked 300 ms after typing pauses, only about the handle typed last; the instance's suggestion is free without asking) (D30). The password setup asks for the handle between the phrase check and the code, and a refusal at the code sends back to it. SimpleLogin's sign-up and keys steps use the same field and now check as it is typed. - The module's README and ADR 0020 (D29, D30, the built state) amended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-24 18:09:04 +02:00
"handleInvalid": "A handle is 1 to 30 letters (a to z), digits or underscores.",
"handleReserved": "This handle is kept for the instance.",
"handleTaken": "Someone else has this handle.",
"handleTooManyChecks": "Too many handles were tried. Try again in an hour.",
"simpleLoginSectionTitle": "SimpleLogin",
"simpleLoginSignsYouIn": "Signs you in",
"simpleLoginAddHint": "Sign in with SimpleLogin, or with your Proton account.",
feat(app,learn,todo): the operator's "This instance" card, screen and badge (ADR 0021, step 1) Whoever operates the instance approves, refuses and suspends accounts and names other operators in the app (D21 to D24, D34): - halkyon_app: InstanceOperatorRepository on ServerpodInstanceOperatorGateway (the module's instanceOperator endpoint; refusals as OperatorFailed: notFound, isOperator, lastOperator, notAllowed for 401 and 403, failed), in AppDependencies. OperatingCubit counts the accounts that wait: asked as the person's app opens, after every change, and every 5 minutes only while they operate the instance, so nobody else's app keeps asking. InstanceOperatorCard (or its tiles) and WaitingAccountsBadge show nothing at all for anyone else. InstanceOperatorScreen, laid out as Settings: the accounts that wait, each showing its four words to read out before Approve (D33), Refuse for new ones after asking; who operates, Take back after asking, the last always kept; Name an operator by handle; Find an account by the start of its handle, with Suspend after asking and Name as operator. English and German texts ("Admin" as the role word in German). - Learn: the card right after the Sync card in Settings, which the cogs' count leads to as their dot leads to Sync; the count on the Settings cogs of Home and Profile. - Todo: the tiles in the account sheet and the count on its button. Todo's server is a member, whose `operating()` is always null, so nothing shows there until it holds the register. Tests: the gateway's mapping, the repository, both cubits with their denials, the card, the badge and the screen; Learn's Settings shows the card and the count to an operator and neither to anyone else. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 15:55:28 +01:00
"simpleLoginAdded": "SimpleLogin added.",
"operatorTitle": "This instance",
"@operatorTitle": {
"description": "The card and screen for whoever operates the instance (ADR 0021, D34)."
},
"operatorAccounts": "Accounts and operators",
"@operatorAccounts": {
"description": "The tile leading to the operator's screen."
},
"operatorWaitingCount": "{count, plural, =0{Nobody waits for approval} =1{1 account waits for approval} other{{count} accounts wait for approval}}",
"@operatorWaitingCount": {
"description": "How many accounts wait for the operator; also the badge's label.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"operatorWaitingTitle": "Waiting",
"@operatorWaitingTitle": {
"description": "The card of accounts that wait for approval, new or suspended."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"operatorOperatorsCount": "{count, plural, =1{1 operator} other{{count} operators}}",
"@operatorOperatorsCount": {
"description": "How many operate the instance, in the overview's row.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"operatorAccountsTitle": "Accounts",
"@operatorAccountsTitle": {
"description": "The overview's row leading to every account, and that screen's title."
},
"operatorAccountsCount": "{count, plural, =1{1 account} other{{count} accounts}}",
"@operatorAccountsCount": {
"description": "How many accounts the instance has.",
"placeholders": {
"count": {
"type": "int"
}
}
},
feat(app,learn,todo): the operator's "This instance" card, screen and badge (ADR 0021, step 1) Whoever operates the instance approves, refuses and suspends accounts and names other operators in the app (D21 to D24, D34): - halkyon_app: InstanceOperatorRepository on ServerpodInstanceOperatorGateway (the module's instanceOperator endpoint; refusals as OperatorFailed: notFound, isOperator, lastOperator, notAllowed for 401 and 403, failed), in AppDependencies. OperatingCubit counts the accounts that wait: asked as the person's app opens, after every change, and every 5 minutes only while they operate the instance, so nobody else's app keeps asking. InstanceOperatorCard (or its tiles) and WaitingAccountsBadge show nothing at all for anyone else. InstanceOperatorScreen, laid out as Settings: the accounts that wait, each showing its four words to read out before Approve (D33), Refuse for new ones after asking; who operates, Take back after asking, the last always kept; Name an operator by handle; Find an account by the start of its handle, with Suspend after asking and Name as operator. English and German texts ("Admin" as the role word in German). - Learn: the card right after the Sync card in Settings, which the cogs' count leads to as their dot leads to Sync; the count on the Settings cogs of Home and Profile. - Todo: the tiles in the account sheet and the count on its button. Todo's server is a member, whose `operating()` is always null, so nothing shows there until it holds the register. Tests: the gateway's mapping, the repository, both cubits with their denials, the card, the badge and the screen; Learn's Settings shows the card and the count to an operator and neither to anyone else. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 15:55:28 +01:00
"operatorNobodyWaits": "Nobody waits.",
"@operatorNobodyWaits": {
"description": "The waiting card, empty."
},
"operatorNoHandle": "No handle yet",
"@operatorNoHandle": {
"description": "An account without a handle, where its handle would be."
},
"operatorNewSince": "New, waiting since {date}",
"@operatorNewSince": {
"description": "A new account that waits, and since when.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"operatorSuspendedSince": "Suspended since {date}",
"@operatorSuspendedSince": {
"description": "A suspended account, and since when.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"operatorApproveNote": "Read them these four words, and approve only once they confirm these are on their screen.",
"@operatorApproveNote": {
"description": "Before approving: the words prove it is their account that waits (D33)."
},
"operatorApprove": "Approve",
"@operatorApprove": {
"description": "Approves a waiting account."
},
"operatorRefuse": "Refuse",
"@operatorRefuse": {
"description": "Refuses a new account: deleted."
},
"operatorRefuseTitle": "Refuse this account?",
"@operatorRefuseTitle": {
"description": "The question before refusing."
},
"operatorRefuseMessage": "It is deleted with everything it has. They can sign up again.",
"@operatorRefuseMessage": {
"description": "What refusing does."
},
"operatorOperatorsTitle": "Operators",
"@operatorOperatorsTitle": {
"description": "The card of who operates the instance."
},
"operatorTakeBack": "Take back",
"@operatorTakeBack": {
"description": "Takes back the operator's role."
},
"operatorTakeBackTitle": "Take back the role?",
"@operatorTakeBackTitle": {
"description": "The question before taking the role back."
},
"operatorTakeBackMessage": "They keep their account, but no longer approve, refuse or suspend accounts here.",
"@operatorTakeBackMessage": {
"description": "What taking the role back does."
},
"operatorAppoint": "Name an operator",
"@operatorAppoint": {
"description": "Names an account an operator, by its handle."
},
"operatorAppointMessage": "They approve, refuse and suspend accounts here, and name operators, as you do.",
"@operatorAppointMessage": {
"description": "What an operator may do."
},
"operatorAppointConfirm": "Name",
"@operatorAppointConfirm": {
"description": "Confirms naming an operator."
},
"operatorHandle": "Handle",
"@operatorHandle": {
"description": "The field for an account's handle."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"operatorHandleSuggested": "Only handles there are here are suggested.",
"@operatorHandleSuggested": {
"description": "Below a field suggesting handles as they are typed."
feat(app,learn,todo): the operator's "This instance" card, screen and badge (ADR 0021, step 1) Whoever operates the instance approves, refuses and suspends accounts and names other operators in the app (D21 to D24, D34): - halkyon_app: InstanceOperatorRepository on ServerpodInstanceOperatorGateway (the module's instanceOperator endpoint; refusals as OperatorFailed: notFound, isOperator, lastOperator, notAllowed for 401 and 403, failed), in AppDependencies. OperatingCubit counts the accounts that wait: asked as the person's app opens, after every change, and every 5 minutes only while they operate the instance, so nobody else's app keeps asking. InstanceOperatorCard (or its tiles) and WaitingAccountsBadge show nothing at all for anyone else. InstanceOperatorScreen, laid out as Settings: the accounts that wait, each showing its four words to read out before Approve (D33), Refuse for new ones after asking; who operates, Take back after asking, the last always kept; Name an operator by handle; Find an account by the start of its handle, with Suspend after asking and Name as operator. English and German texts ("Admin" as the role word in German). - Learn: the card right after the Sync card in Settings, which the cogs' count leads to as their dot leads to Sync; the count on the Settings cogs of Home and Profile. - Todo: the tiles in the account sheet and the count on its button. Todo's server is a member, whose `operating()` is always null, so nothing shows there until it holds the register. Tests: the gateway's mapping, the repository, both cubits with their denials, the card, the badge and the screen; Learn's Settings shows the card and the count to an operator and neither to anyone else. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 15:55:28 +01:00
},
"operatorFoundNone": "No account's handle starts like this.",
"@operatorFoundNone": {
"description": "A search that found nothing."
},
"operatorMadeOn": "Since {date}",
"@operatorMadeOn": {
"description": "When an account was made.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"operatorIsOperator": "Operator",
"@operatorIsOperator": {
"description": "A tag: the account operates the instance."
},
"operatorIsWaiting": "Waiting",
"@operatorIsWaiting": {
"description": "A tag: the account waits for approval."
},
"operatorIsSuspended": "Suspended",
"@operatorIsSuspended": {
"description": "A tag: the account is suspended."
},
"operatorSuspend": "Suspend",
"@operatorSuspend": {
"description": "Suspends an account."
},
"operatorSuspendTitle": "Suspend this account?",
"@operatorSuspendTitle": {
"description": "The question before suspending."
},
"operatorSuspendMessage": "They are signed out everywhere and can't sign in until you approve them again. Nothing they have is deleted.",
"@operatorSuspendMessage": {
"description": "What suspending does."
},
"operatorMakeOperator": "Name as operator",
"@operatorMakeOperator": {
"description": "Names a found account an operator."
},
"operatorNotFound": "That account isn't there any more, or doesn't wait.",
"@operatorNotFound": {
"description": "Refused: no such account, or it doesn't wait."
},
"operatorIsOperatorProblem": "An operator can't be suspended. Take back their role first.",
"@operatorIsOperatorProblem": {
"description": "Refused: suspending an operator."
},
"operatorLastOperator": "The instance needs at least one operator.",
"@operatorLastOperator": {
"description": "Refused: taking back the last operator's role."
},
"operatorNotAllowed": "Only the instance's operators can do this.",
"@operatorNotAllowed": {
"description": "Refused: the person doesn't operate the instance."
},
"operatorFailed": "That didn't work. Try again.",
"@operatorFailed": {
"description": "Any other failure."
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
},
"operatorAssistantNotSet": "That assistant isn't set up here any more.",
"@operatorAssistantNotSet": {
"description": "The assistant asked for is no longer in deploy/assistants.env."
},
"operatorInvalidLimit": "A limit can't be below zero.",
"@operatorInvalidLimit": {
"description": "A limit below 0 was refused."
},
"assistantGrantsTitle": "Assistants",
"@assistantGrantsTitle": {
"description": "The operator's card of the assistants granted (Halkyon Learn's ADR 0021)."
},
"assistantGrantsNone": "Nobody has an assistant yet.",
"@assistantGrantsNone": {
"description": "No assistant is granted to anyone."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantSetCount": "{count, plural, =0{None set up} =1{1 assistant} other{{count} assistants}}",
"@assistantSetCount": {
"description": "How many assistants are set up, in the overview's row.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"assistantPeopleCount": "{count, plural, =0{nobody granted} =1{1 person} other{{count} people}}",
"@assistantPeopleCount": {
"description": "How many people have an assistant, after how many are set up.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"assistantSetUpTitle": "Set up here",
"@assistantSetUpTitle": {
"description": "The card of the assistants set up in deploy/assistants.env."
},
"assistantPeopleTitle": "People",
"@assistantPeopleTitle": {
"description": "The card, and the sheet section, of the people granted assistants."
},
"assistantGranteesFoundNone": "Nobody with an assistant has a handle starting like this.",
"@assistantGranteesFoundNone": {
"description": "No person granted one matches the start of a handle typed."
},
"assistantUnpriced": "No prices: counts its tokens only",
"@assistantUnpriced": {
"description": "An assistant set up without prices, which a budget counts in tokens alone."
},
"assistantEffort": "{effort, select, low{low} medium{medium} high{high} xhigh{extra high} max{max} other{{effort}}}",
"@assistantEffort": {
"description": "How much a model thinks before it answers, as a word in a sentence.",
"placeholders": {
"effort": {
"type": "String"
}
}
},
"assistantEffortName": "{effort, select, low{Low} medium{Medium} high{High} xhigh{Extra high} max{Max} other{{effort}}}",
"@assistantEffortName": {
"description": "How much a model thinks before it answers, as a name standing alone, as in a menu.",
"placeholders": {
"effort": {
"type": "String"
}
}
},
"assistantEffortSetUp": "Effort {effort}, up to {max}",
"@assistantEffortSetUp": {
"description": "An assistant's effort unless asked otherwise, and the highest a question may ask.",
"placeholders": {
"effort": {
"type": "String"
},
"max": {
"type": "String"
}
}
},
"assistantEffortFixed": "Effort {effort}",
"@assistantEffortFixed": {
"description": "An assistant's effort, the only one it takes.",
"placeholders": {
"effort": {
"type": "String"
}
}
},
"assistantNameUnset": "{name} (no longer set up)",
"@assistantNameUnset": {
"description": "An assistant granted that is no longer set up.",
"placeholders": {
"name": {
"type": "String"
}
}
},
"assistantNotAgreedCount": "{count, plural, =1{1 not agreed to yet} other{{count} not agreed to yet}}",
"@assistantNotAgreedCount": {
"description": "How many of a person's assistants they haven't agreed to yet.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"assistantGrant": "Grant assistants",
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"@assistantGrant": {
"description": "Opens the sheet granting an assistant to an account."
},
"assistantGrantSave": "Grant",
"@assistantGrantSave": {
"description": "The grant sheet's button."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantGrantChange": "Change assistants",
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"@assistantGrantChange": {
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"description": "The sheet changing a person's assistants and budget, and a person's menu item."
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
},
"assistantGrantLimitHelper": "Empty for none. Days and months are UTC's.",
"@assistantGrantLimitHelper": {
"description": "Under the limit fields: the instance counts by UTC days and months (D42)."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantGrantBudget": "Budget, for all of them together",
"@assistantGrantBudget": {
"description": "The sheet's section of a person's budget."
},
"assistantGrantMoneyDaily": "Money a day",
"@assistantGrantMoneyDaily": {
"description": "A budget field."
},
"assistantGrantMoneyMonthly": "Money a month",
"@assistantGrantMoneyMonthly": {
"description": "A budget field."
},
"assistantGrantTokensDaily": "Tokens a day",
"@assistantGrantTokensDaily": {
"description": "A budget field."
},
"assistantGrantTokensMonthly": "Tokens a month",
"@assistantGrantTokensMonthly": {
"description": "A budget field."
},
"assistantGrantMoneyNote": "Money counts the assistants with prices, tokens count every one. Whichever runs out first stops them.",
"@assistantGrantMoneyNote": {
"description": "Below the budget fields."
},
"assistantGrantReplaces": "{count, plural, =1{Granting replaces the budget this person has:} other{Granting replaces the budgets these people have:}}",
"@assistantGrantReplaces": {
"description": "Before the people whose budget a grant replaces, each with theirs.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"assistantGrantUnsetDropped": "Saving takes back what is no longer set up: {names}.",
"@assistantGrantUnsetDropped": {
"description": "Changing a person's assistants drops those no longer set up.",
"placeholders": {
"names": {
"type": "String"
}
}
},
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"assistantGrantLimitInvalid": "Not a number this takes",
"@assistantGrantLimitInvalid": {
"description": "A limit typed that is no amount or number of tokens."
},
"assistantGrantTokens": "tokens",
"@assistantGrantTokens": {
"description": "After a limit in tokens, for an assistant without prices."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantGrantNote": "They agree once to what goes where before they ask one. Assistants they have already stay. You see how much they use, never what they ask.",
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"@assistantGrantNote": {
"description": "In the grant sheet: consent (D40) and what the operator sees (D3)."
},
"assistantPerDay": "{amount} a day",
"@assistantPerDay": {
"description": "A daily limit.",
"placeholders": {
"amount": {
"type": "String"
}
}
},
"assistantPerMonth": "{amount} a month",
"@assistantPerMonth": {
"description": "A monthly limit.",
"placeholders": {
"amount": {
"type": "String"
}
}
},
"assistantNoLimits": "No limits",
"@assistantNoLimits": {
"description": "A grant without limits."
},
"assistantRevoke": "Take back",
"@assistantRevoke": {
"description": "A grant's menu item."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantRevokeAllTitle": "Take back every assistant?",
"@assistantRevokeAllTitle": {
"description": "Asks before taking every assistant back from a person."
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantRevokeMessage": "They can no longer ask any of them, and their budget goes. What they used stays counted.",
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"@assistantRevokeMessage": {
"description": "Under the question taking a grant back."
},
"assistantUseByMonth": "Use by month",
"@assistantUseByMonth": {
"description": "Opens everyone's figures (D3)."
},
"assistantUseTitle": "Use of assistants",
"@assistantUseTitle": {
"description": "The title of the figures' screen and sheet."
},
"assistantUseNone": "Nothing used in this month.",
"@assistantUseNone": {
"description": "A month without use."
},
"assistantUseKept": "Counted per UTC day, kept for this month and the two before. Never what was asked.",
"@assistantUseKept": {
"description": "Under the figures: what is counted and for how long (D41, D42)."
},
"assistantRequests": "{count, plural, =1{1 request} other{{count} requests}}",
"@assistantRequests": {
"description": "How many requests were counted.",
"placeholders": {
"count": {
"type": "int"
}
}
},
"assistantTokens": "{amount} tokens",
"@assistantTokens": {
"description": "How many tokens were counted, the number formatted.",
"placeholders": {
"amount": {
"type": "String"
}
}
},
"assistantsTitle": "Assistants",
"@assistantsTitle": {
"description": "Settings' card of the assistants a person may ask (Halkyon Learn's ADR 0021, point 9)."
},
"assistantModelAt": "{model} at {host}",
"@assistantModelAt": {
"description": "Which model answers, and the host that receives what is asked.",
"placeholders": {
"model": {
"type": "String"
},
"host": {
"type": "String"
}
}
},
"assistantLeftToday": "{left} of {limit} left today",
"@assistantLeftToday": {
"description": "What is left of a day's limit.",
"placeholders": {
"left": {
"type": "String"
},
"limit": {
"type": "String"
}
}
},
"assistantLeftThisMonth": "{left} of {limit} left this month",
"@assistantLeftThisMonth": {
"description": "What is left of a month's limit.",
"placeholders": {
"left": {
"type": "String"
},
"limit": {
"type": "String"
}
}
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantYourBudget": "Your budget, for all of them",
"@assistantYourBudget": {
"description": "The person's budget for all their assistants."
},
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"assistantAgree": "Read and agree",
"@assistantAgree": {
"description": "Opens the consent sheet of an assistant not agreed to yet."
},
"assistantYourUse": "Your use",
"@assistantYourUse": {
"description": "Opens the person's own figures."
},
"assistantPrivacyPage": "What goes where on {instance}",
"@assistantPrivacyPage": {
"description": "Opens the instance's privacy page (D39).",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"assistantOwnTitle": "With your own key",
"@assistantOwnTitle": {
"description": "Above a person's own assistants (point 10)."
},
"assistantOwnAdd": "Add an assistant with your own key",
"@assistantOwnAdd": {
"description": "Opens the sheet adding an assistant with a personal key."
},
"assistantOwnNote": "The app asks your provider directly: this instance sees neither your key nor your questions, and counts nothing. The key is kept in your settings, encrypted on your devices.",
"@assistantOwnNote": {
"description": "What a personal key means (D5, D6)."
},
"assistantOwnEdit": "Your own key",
"@assistantOwnEdit": {
"description": "The personal key sheet's title."
},
"assistantOwnName": "Name",
"@assistantOwnName": {
"description": "The name the person gives their assistant."
},
"assistantOwnProtocol": "API",
"@assistantOwnProtocol": {
"description": "Above the choice of protocol."
},
"assistantOwnBaseUrl": "Address",
"@assistantOwnBaseUrl": {
"description": "The provider's address field."
},
"assistantOwnBaseUrlHelper": "Empty for the provider's own. Mistral, OpenRouter or a model of your own: its address with /v1.",
"@assistantOwnBaseUrlHelper": {
"description": "Under the address field: which services take which address."
},
"assistantOwnBaseUrlInvalid": "Only https, or http on your own network",
"@assistantOwnBaseUrlInvalid": {
"description": "An address the app refuses: keys and questions would travel in the clear."
},
"assistantOwnModel": "Model",
"@assistantOwnModel": {
"description": "The model's name at the provider."
},
"assistantOwnKey": "Key",
"@assistantOwnKey": {
"description": "The API key field."
},
"assistantOwnKeyHelper": "Empty for a model of your own that takes none.",
"@assistantOwnKeyHelper": {
"description": "Under the key field."
},
"assistantOwnImages": "Reads images",
"@assistantOwnImages": {
"description": "Whether the model reads images (D12)."
},
"assistantOwnSave": "Save",
"@assistantOwnSave": {
"description": "The personal key sheet's button."
},
"assistantOwnRemove": "Remove",
"@assistantOwnRemove": {
"description": "Removes an assistant with a personal key."
},
"assistantOwnRemoveTitle": "Remove {name}?",
"@assistantOwnRemoveTitle": {
"description": "Asks before removing an assistant with a personal key.",
"placeholders": {
"name": {
"type": "String"
}
}
},
"assistantOwnRemoveMessage": "Its key goes from your settings on every device.",
"@assistantOwnRemoveMessage": {
"description": "Under the question removing a personal key."
},
"assistantOwnRefused": "The key wasn't kept: this device can't encrypt your settings yet. Open your account's keys here first.",
"@assistantOwnRefused": {
"description": "A personal key refused, as the settings wouldn't be sealed."
},
"assistantOwnNotAllowed": "Whoever runs {instance} doesn't allow own keys here, so the app doesn't ask these.",
"@assistantOwnNotAllowed": {
"description": "Below the person's own assistants, where the operator doesn't allow them (ADR 0021, D6).",
"placeholders": {
"instance": {
"type": "String",
"example": "learn.halkyon.eu"
}
}
},
"assistantConsentTitle": "Before you ask {name}",
"@assistantConsentTitle": {
"description": "The consent sheet's title (D40).",
"placeholders": {
"name": {
"type": "String"
}
}
},
"assistantConsentModel": "It answers with the model {model} at {host}.",
"@assistantConsentModel": {
"description": "Who answers (D27).",
"placeholders": {
"model": {
"type": "String"
},
"host": {
"type": "String"
}
}
},
"assistantConsentProvider": "It holds for every assistant at {host}.",
"@assistantConsentProvider": {
"description": "An agreement is to what goes where, so it covers every assistant of the provider (Halkyon Learn's ADR 0021, D66).",
"placeholders": {
"host": {
"type": "String"
}
}
},
"assistantConsentWhatGoes": "Only what you send goes there: your question, what you pick of what it is about, and what it looks up where you let it. The provider's own terms apply to it.",
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"@assistantConsentWhatGoes": {
"description": "What goes to the provider (D27)."
},
"assistantConsentImages": "It reads the images you add.",
"@assistantConsentImages": {
"description": "For an assistant that reads images (D12)."
},
"assistantConsentInstance": "It passes through {instance} on its way, which keeps none of it.",
"@assistantConsentInstance": {
"description": "The instance sees it in passing and keeps nothing (D27).",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"assistantConsentOperator": "Whoever runs {instance} sees how much you use it (requests, tokens, cost), never what you ask.",
"@assistantConsentOperator": {
"description": "The operator's figures (D3).",
"placeholders": {
"instance": {
"type": "String"
}
}
},
"assistantConsentConversations": "Your conversations are kept encrypted: only your devices can read them.",
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"@assistantConsentConversations": {
"description": "Conversations are sealed on the devices (D13)."
},
"assistantConsentAgree": "Agree",
"@assistantConsentAgree": {
"description": "The consent sheet's button."
},
"assistantConsentAgreedOn": "You agreed on {date}.",
"@assistantConsentAgreedOn": {
"description": "An assistant agreed to, and when.",
"placeholders": {
"date": {
"type": "String"
}
}
},
"assistantProblemNotGranted": "This assistant isn't granted to you any more.",
"@assistantProblemNotGranted": {
"description": "notGranted."
},
"assistantProblemNotAgreed": "Agree to what goes where first.",
"@assistantProblemNotAgreed": {
"description": "notAgreed."
},
feat(app): the operator's overview of screens, grants to several people at once with one budget each, assistants by provider Halkyon Learn's ADR 0021, D57 to D63, on halkyon_base's budgets and effort: - The operator's screen is an overview (Waiting, Operators, Accounts, Assistants, each with its count) whose rows open screens of their own, read 50 at a time as they scroll (OperatorListCubit, OperatorPage), so hundreds of accounts push nothing else down (D62). - A handle is picked among the accounts there are (AccountSuggestionField): appointing an operator and granting take no other (D61). - AssistantGrantsScreen replaces AssistantGrantsCard: the assistants set up by provider, with their efforts and prices; the people granted, found by their handle's start; one sheet granting several assistants, a provider's at once, to several people, each with one budget in money and tokens a day and a month, or changing one person's (D58, D59). - Assistants are grouped by provider wherever they are listed, each under its name with a dot in its colour (ProviderLabel, D60). - AssistantsCard shows what is left of the person's budget for all their assistants together; the months of the figures run oldest first (D57). - AssistantChoice says the efforts a question may ask at and the ceiling on output each asks for (D63); a person's own key gets none and keeps 4,096 tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-26 16:05:49 +01:00
"assistantProblemInvalidEffort": "It doesn't think at this effort.",
"@assistantProblemInvalidEffort": {
"description": "A question asked an effort its assistant does not take."
},
feat(app,learn,todo): the assistants in Settings and on the operator's screen ADR 0021, step 2's app half. halkyon_app asks the module's assistant endpoints (ServerpodAssistantGateway, ServerpodAssistantOperatorGateway) and a person's own provider directly (halkyon_llm), behind AssistantRepository: an AssistantChoice is a GrantedAssistant, asked through the instance, which counts it, or a PersonalAssistant with the person's own key, which the instance never sees. assistant_messages.dart turns a conversation into the endpoint's models and back. AssistantsCard, for an app's settings: what is granted and left of its limits, agreed to once on a sheet saying what goes where, the person's use by UTC month, the instance's privacy page, and their own assistants where the operator allows own keys (kept ones stay listed, unasked, where it doesn't). AssistantGrantsCard on InstanceOperatorScreen: grants by handle with their limits in the pricing's unit, changed and taken back after asking, everyone's use by month; a found account's menu grants too. Nothing shows where nothing is offered or can be read. package:halkyon_app/assistant_models.dart holds the models in pure Dart. Learn keeps own assistants in the person's settings (ownAssistants, schema 12, SettingsOwnAssistants); SettingsRepository.update refuses (OwnAssistantRefused) to write a key where the settings would not be sealed (SettingsGateway.seals). Learn depends on halkyon_llm directly. Todo wires the gateways; a member offers no assistant. No feature asks an assistant yet (step 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-25 18:59:41 +01:00
"assistantProblemLimitReached": "Its limit is reached until {time}.",
"@assistantProblemLimitReached": {
"description": "limitReached, with when it resets.",
"placeholders": {
"time": {
"type": "String"
}
}
},
"assistantProblemLimitReachedNow": "Its limit is reached for now.",
"@assistantProblemLimitReachedNow": {
"description": "Refused: a limit is reached, the instance not saying until when."
},
"assistantProblemImagesNotRead": "It reads no images.",
"@assistantProblemImagesNotRead": {
"description": "imagesNotRead."
},
"assistantProblemMalformed": "This question can't be sent.",
"@assistantProblemMalformed": {
"description": "malformed."
},
"assistantProblemTooLarge": "This question is too long, or holds too many or too large images.",
"@assistantProblemTooLarge": {
"description": "tooLarge."
},
"assistantProblemTooManyAtOnce": "Wait for the answers on their way first.",
"@assistantProblemTooManyAtOnce": {
"description": "tooManyAtOnce."
},
"assistantProblemProviderKey": "The provider refused the key.",
"@assistantProblemProviderKey": {
"description": "providerKey."
},
"assistantProblemProviderBusy": "The provider is busy. Try again in a moment.",
"@assistantProblemProviderBusy": {
"description": "providerBusy."
},
"assistantProblemProviderRefused": "The provider refused this question.",
"@assistantProblemProviderRefused": {
"description": "providerRefused."
},
"assistantProblemProviderFailed": "The provider failed. Try again.",
"@assistantProblemProviderFailed": {
"description": "providerFailed."
},
"assistantProblemNotAllowed": "Only people it is granted to can do this.",
"@assistantProblemNotAllowed": {
"description": "notAllowed."
},
"assistantProblemFailed": "That didn't work. Try again.",
"@assistantProblemFailed": {
"description": "failed."
},
"whatsNewTitle": "What's new",
"@whatsNewTitle": {
"description": "The sheet listing what changed in the app after an update, and its entry in Settings."
},
"whatsNewVersion": "Version {version}",
"@whatsNewVersion": {
"description": "Above a release's changes in What's new.",
"placeholders": {
"version": {
"type": "String"
}
}
},
"profileIdentified": "Your progress is kept with your account.",
"profileProblemAvatarInvalid": "This picture can't be used: choose a PNG, JPEG, WebP or GIF image.",
"profileProblemBioTooLong": "At most 500 characters.",
"profileProblemDisplayNameTooLong": "At most 30 characters.",
"profileProblemHandleInvalid": "A handle is 1 to 30 letters (a to z), digits or underscores.",
"profileProblemHandleReserved": "This handle is kept for the instance.",
"profileProblemHandleTaken": "Someone else has this handle.",
"profileProblemLinkInvalid": "Links start with https:// or http://.",
"profileProblemPublished": "You have published: your handle can't change, nor your profile go.",
"profileProblemTooManyHandleChecks": "Too many handles were tried. Try again in an hour.",
"profileProblemTooManyLinkChecks": "The links were checked too often. Try again in an hour.",
"profileProblemTooManyLinks": "At most 4 links.",
"profileSheetNotFound": "Nobody on this instance has this handle.",
"profileSheetTitle": "Profile",
"profileSheetUnreachable": "The profile couldn’t be loaded. Check your connection.",
"profileSignInWays": "Ways to sign in",
"profileTabProfile": "Profile",
"profileTitle": "Profile",
"profileWayEmail": "Email address",
"profileWayLinked": "Signs you in",
"publicProfileAddLink": "Add link",
"publicProfileAddress": "Others find you as @{address}",
"@publicProfileAddress": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"publicProfileAddressPrivate": "Private until you fill in your profile or publish something; then others find you as @{address}.",
"@publicProfileAddressPrivate": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"publicProfileBio": "Bio",
"publicProfileCheckLinks": "Check links",
"publicProfileChoosePicture": "Choose picture",
"publicProfileDisplayName": "Display name",
"publicProfileDisplayNameHint": "The name shown beside your handle",
"publicProfileFailed": "Couldn't reach the instance. Try again.",
"publicProfileHandle": "Handle",
"publicProfileHandleChangeTitle": "Change your handle",
"publicProfileHandleChecking": "Checking…",
"publicProfileHandleChoose": "Choose a handle",
"publicProfileHandleChooseTitle": "Choose your handle",
"publicProfileHandleConfirmChange": "Change",
"publicProfileHandleConfirmChoose": "Choose",
"publicProfileHandleDialogText": "Others find you by your handle. You can change it until you first publish a studyset.",
"publicProfileHandleFirst": "Choose your handle first: your profile is made with it, and saves as you write from then on.",
"publicProfileHandleFixed": "Fixed since you published: others refer to it.",
"publicProfileHandleFree": "@{handle} is free",
"@publicProfileHandleFree": {
"placeholders": {
"handle": {
"type": "String"
}
}
},
"publicProfileHandleHint": "Letters, digits and underscores, up to 30",
"publicProfileHandleYours": "This is your handle",
"publicProfileIntro": "How others see you once you publish: the handle they find you by, your name, a few words and links. It saves as you write, once you have chosen your handle.",
"publicProfileLinkHint": "https://…",
"publicProfileLinkVerified": "Links back to your profile",
"publicProfileLinks": "Links",
"publicProfileLinksChecked": "{count, plural, =1{Checked: {verified} of 1 link links back to your profile.} other{Checked: {verified} of {count} links link back to your profile.}}",
"@publicProfileLinksChecked": {
"placeholders": {
"count": {
"type": "int"
},
"verified": {
"type": "int"
}
}
},
"publicProfileLinksHint": "Your site or other accounts, up to 4.",
"publicProfilePage": "Your profile page: {url}",
"@publicProfilePage": {
"placeholders": {
"url": {
"type": "String"
}
}
},
"publicProfilePageCopied": "Address copied.",
"publicProfilePageCopy": "Copy the address",
"publicProfilePicture": "Picture",
"publicProfilePictureLater": "Choose your handle to add a picture.",
"publicProfilePictureType": "Images",
"publicProfileRemove": "Remove profile",
"publicProfileRemoveLink": "Remove link",
"publicProfileRemoveMessage": "Your display name, bio, links and picture are removed. Your handle stays yours and private until you fill in your profile again or publish something.",
"publicProfileRemovePicture": "Remove picture",
"publicProfileRemoveTitle": "Remove your public profile?",
"publicProfileRemoved": "Profile removed.",
"publicProfileRetry": "Retry",
"publicProfileSavedNow": "Saved",
"publicProfileSaving": "Saving…",
"publicProfileTitle": "Public profile",
"publicProfileUnreachable": "Your public profile can't be reached right now.",
"publicProfileVerifyHint": "A link gets a checkmark once its page links back to your profile page with rel=\"me\", as Mastodon checks links.",
"profileAccount": "Account",
"profileSheetLinkVerified": "Links back to this profile",
"speechNoRecognizer": "This device has no speech recognition installed. Install one, such as FUTO Voice Input or Google's speech services, then try again.",
"@speechNoRecognizer": {"description": "Shown when the microphone is tapped on a device without any speech recognition app (as GrapheneOS without Google's services), with a hint how to get one."}
}