gsmol/locales/en-US/main.ftl

450 lines
23 KiB
Text
Raw Permalink Normal View History

2026-10-09 13:47:42 +03:00
## Loaded once at startup by `src/i18n.rs`; every user-facing string in
## the app lives here, grouped by the feature it belongs to.
## Seed parsing — restoring an identity from a pasted seed
seed-bad-hex = That's not valid hex. Check for typos or extra characters.
seed-wrong-length = A seed is 32 bytes. Check you copied the whole thing.
## Local files — errors reading/writing the key and its sidecars
file-error = { $path }: { $reason }
key-file-wrong-length = { $path }: not a 32-byte secret
## Compose — validating a typed `Key: value` header row
compose-header-colon-missing = Headers need a colon, like `Key: value`.
compose-header-reserved-key = { $key } is set automatically and can't be changed.
compose-header-invalid-key = Keys can be 1 to 64 letters, digits, and dashes.
compose-header-value-multiline = Values need to stay on one line.
compose-header-duplicate-key = { $key } is set twice. Remove one of them.
compose-headers-too-large = Your headers take up too much space. Remove some and try again.
compose-headers-too-many = You have too many headers. Remove some and try again.
## Contacts — importing a smol:// address
contacts-import-needs-key = Import needs a smol:// address that includes a key.
## Mail — opening a message by id
mail-message-id-wrong-length = Message IDs are 64 hex characters.
mail-message-id-wrong-bytes = Message IDs are 32 bytes.
mail-message-not-found = Message not found.
## Fetch — the status note after a fetch completes
##
## Split from one selector into one message per combination of "N
## rejected" and "(cancelled)" that can apply; the caller in ops.rs
## picks the id to match, since a flat message can't branch on a
## variable itself.
fetch-result-note-rejected = { $total } fetched, { $stored } stored, { $rejected } rejected
fetch-result-note-cancelled = { $total } fetched, { $stored } stored (cancelled)
fetch-result-note-rejected-cancelled = { $total } fetched, { $stored } stored, { $rejected } rejected (cancelled)
fetch-result-note-plain = { $total } fetched, { $stored } stored
mail-envelope-id-mismatch-error = id does not match the envelope
mail-fetch-summary-counts = { $stored } new, { $rejected } rejected
mail-fetch-summary-verified-one = { $verified } sender verified from a signed Reply-To
mail-fetch-summary-verified-other = { $verified } senders verified from a signed Reply-To
mail-fetch-summary-left-on-server = left on the server
## Send — the status note after a send completes
##
## Split from one selector into one message per combination of
## trust-change clause and accept-token clause that can apply; the
## caller in ops.rs picks the id to match. Any warning fumi itself
## reports is appended separately in code, since that text is fumi's
## own and not part of this catalogue.
send-result-note-token = Sent to { $address } ({ $bytes } bytes), accept token attached
send-result-note-unverified = Sent to { $address } ({ $bytes } bytes); new contact learned from an unpinned server (unverified)
send-result-note-unverified-token = Sent to { $address } ({ $bytes } bytes), accept token attached; new contact learned from an unpinned server (unverified)
send-result-note-tofu = Sent to { $address } ({ $bytes } bytes); new contact learned (trust on first use)
send-result-note-tofu-token = Sent to { $address } ({ $bytes } bytes), accept token attached; new contact learned (trust on first use)
send-result-note-rotated = Sent to { $address } ({ $bytes } bytes); contact rotated to a new key (chain verified)
send-result-note-rotated-token = Sent to { $address } ({ $bytes } bytes), accept token attached; contact rotated to a new key (chain verified)
send-result-note-plain = Sent to { $address } ({ $bytes } bytes)
mail-sent-note = sent to { $address }
mail-sent-note-accepted = sent to { $address } (accepted)
## Background-operation status notes
##
## Built in `spawn_op` (src/view.rs) rather than ops.rs, since that is
## where each `PendingOp` result is assembled for the worker thread.
status-registered-note = Registered
status-restored-note = Restored at rotation { $index }
status-deleted-note = Deleted
status-accepted-note = Accepted { $address }
status-blocked-note = Blocked { $address }
status-not-blocked-note = { $address } was not blocked
contacts-no-key-error = no key for { $address } yet
# Split from one selector into flat siblings for the token count, matching
# this file's existing convention (see fetch-result-note-* above).
contacts-accepted-note-one = { $address } accepted; server now holds { $held } accept token
contacts-accepted-note-other = { $address } accepted; server now holds { $held } accept tokens
contacts-blocked-note-one = { $address } blocked; server now holds { $held } accept token
contacts-blocked-note-other = { $address } blocked; server now holds { $held } accept tokens
status-imported-note = Imported { $address } (verified)
status-rotated-note = Rotated to index { $index }; new key { $key_prefix }…
## Backup
backup-written-note = Backup written to { $path }
## Drafts
draft-saved-note = Draft saved
## Log out
logged-out-note = Signed out. Create a new identity or restore a seed.
## Onboarding
identity-created-note = Identity created. Write the seed down. It's the only secret.
seed-restored-note = Seed restored. Bind a username or recall an address.
## Signup
signup-enter-host-error = Enter the server host first.
signup-enter-user-host-error = Enter the user and host.
# A pin is keyed by bare host, so these two catch the mistakes that would
# otherwise silently pin a string nothing looks up again: a whole address,
# or a host with its port still attached.
signup-host-looks-like-address-error = "{ $host }" looks like an address, not a server — the part after the @ goes here
signup-host-has-port-error = "{ $host }": a pin is by host only, no port — just the part before the colon
## Compose
compose-enter-recipient-error = Enter a recipient.
compose-header-row-error = Header { $index }: { $reason }
reply-no-address-error = This sender left no address to reply to.
reply-subject-prefix = Re: { $subject }
address-invalid-error = That address isn't in the right format.
## Contacts
contacts-reply-address-invalid-error = The sender's reply address isn't in the right format.
contacts-sender-key-invalid-error = The sender's key isn't in the right format.
contacts-accept-no-address-error = This sender left no address to accept.
contacts-block-no-address-error = This sender left no address to block.
contacts-sender-key-mismatch-error = that address carries a different key than this message's sender
# A pinned, conflicting Reply-To claim is refused outright rather than asked
# about — see saveContactChecked's dialog for the softer self-certifying case.
contacts-reply-key-conflict-error = { $address } is already known with a different key — verify out of band before replying
# Shown when a typed address or a smol:// link would overwrite an address
# already saved under a different key, and the user declined the prompt
# that showed both fingerprints and asked.
contacts-key-kept-note = kept the existing key for { $address }
contacts-sender-saved-note-verified = { $address } saved for this sender (verified key)
contacts-sender-saved-note-unverified = { $address } saved for this sender
# Richer than status-imported-note: this client shows the imported key and
# its fingerprint alongside the confirmation.
contacts-import-detail-note = imported { $address } { $key } (verified){"\u000A"}fingerprint: { $fingerprint }
## Common — short words reused verbatim across several buttons/dialogs
action-cancel = Cancel
action-back = Back
action-block = Block
action-unblock = Unblock
action-accept = Accept
action-reply = Reply
action-delete = Delete
# Shown wherever a fetched server key is on screen before it's pinned:
# the compose's pin card, the signup server step, and the contact detail
# body when a key was fetched for that contact.
trust-fingerprint-hint = If the server operator published a key or fingerprint, make sure it matches before trusting it.
# Reused wherever an action needs an identity that doesn't exist yet
# (sending, fetching, pushing accept tokens).
identity-missing-error = no identity yet
account-not-registered-fetch-warning = not registered yet — claim an address in settings
account-not-registered-tokens-note = not registered; the set will be pushed with your first fetch
## Sidebar
mail-fetch-button = Fetch
mail-write-button = Write
folder-inbox = Inbox
folder-requests = Requests
folder-sent = Sent
folder-drafts = Drafts
settings-nav-label = Settings
settings-close-aria-label = close settings
settings-close-tooltip = close
identity-you-caption = you
contacts-caption = contacts
contacts-import-placeholder = Import a smol:// address
contacts-import-button = Import
# "Follow the system" is a real preference, not the absence of one, so it
# gets its own label rather than defaulting silently to one of the other two.
theme-auto-label = theme: following the system
theme-light-label = theme: light
theme-dark-label = theme: dark
account-not-registered-value = not registered
mail-search-placeholder = search { $folder }
## Mail — the open-message meta line
##
## Split from one selector into one message per variant, each a full
## sentence; the caller in view.rs picks `-yes`/`-no` to match `$kept`.
mail-meta-to = to
mail-meta-from = from
mail-meta-line-no = { $label } { $from } · { $time } UTC · id { $id }…
mail-meta-line-yes = { $label } { $from } · { $time } UTC · id { $id }… · a server copy still exists
mail-no-subject = (no subject)
mail-no-reply-address = no reply address: can't accept or block
contacts-empty-hint = no contacts
# The §4/§8 trust chip on an open message: a signature always verifies, or
# unseal() would have thrown already — what varies is the binding between
# the key that signed it and an address.
mail-back-to-list-button = messages
mail-meta-sent = to: { $recipient }{"\u000A"}id: { $id }{"\u000A"}sent: { $time }
mail-meta-received = from: { $from }{"\u000A"}id: { $id }{"\u000A"}date: { $time }
mail-trust-own-copy = your own sealed copy
mail-trust-verified-sender = verified sender key
mail-trust-tofu-sender = key pinned on first use
mail-trust-unbound-sender = key bound to no address
mail-sender-unbound-tooltip = sender key not bound to an address
mail-signed-reply-hint = this message carries the sender's signed address: { $address }
mail-save-sender-reply-button = save sender & reply
mail-name-sender-button = name sender & reply
mail-unknown-sender-hint = The wire carries no sender name, only this signed key. To reply, give the sender's address — it is checked against this key:
mail-delete-not-registered-error = not registered; cannot reach the server to delete this message
mail-request-unaccepted-hint = unsolicited mail from { $address }, not yet accepted into your main tier
mail-accept-button = accept — future mail lands in your main tier
## Mail list — empty-folder messages, and the own-identity detail
mail-inbox-empty-title = Inbox is empty
mail-inbox-empty-description = Fetch to check the mailbox.
mail-requests-empty-title = No requests
mail-requests-empty-description = Mail from senders you haven't accepted yet arrives here.
mail-sent-empty-title = Nothing sent yet
mail-sent-empty-description = Messages you send keep a sealed copy here.
mail-drafts-empty-title = No drafts
mail-drafts-empty-description = Closing a compose from the sidebar keeps it here.
own-identity-meta = you · rotation { $rotations }
contacts-pin-button-fetched = Pin this key
contacts-pin-button-unfetched = Pin server
mail-empty-title = No message selected
mail-empty-description = Pick a message from the list above to read it.
# The two sentences shown under Fetch when the inbox is empty.
mail-empty-hint = Fetching removes mail from the server once it's stored here. Turn on "Leave mail on server" in Settings to keep it there instead.
detail-qr-tooltip = Show the address as a QR code
detail-copy-tooltip = Copy the address
mail-row-unreadable-error = <unreadable: { $error }>
mail-contacts-reader-hint = contacts and their keys are listed alongside
mail-list-count-one = { $count } message
mail-list-count-other = { $count } messages
mail-list-shown-of-total = { $shown } of { $total }
## Compose
compose-to-label = To
compose-subject-label = Subject
compose-add-header-button = + header
compose-send-button = Send
compose-header-placeholder = Key: value
compose-header-remove-tooltip = Remove this header
compose-body-placeholder = message
compose-anonymous-label = anonymous — omit my address
## Contacts — trust state shown in the sidebar and the detail pane
contact-state-accepted = accepted
contact-state-blocked = blocked
contact-state-verified = verified
contact-state-tofu = trust on first use
# `$state` is one of the four words above, already resolved by the caller
# through `contact_state`. Split from one selector into one message per
# pin state; the caller in view.rs picks `-yes`/`-no` to match `$pinned`.
contact-meta-line-yes = { $state } · server pinned
contact-meta-line-no = { $state } · server not pinned
## Detail pane — the monospace key/value block shared by contacts and the
## own identity view. Column widths are padded to these labels in code
## (14 characters), so a much longer translation would throw the
## alignment off; flagged in the extraction report.
detail-key-label = key
detail-fingerprint-label = fingerprint
detail-address-label = address
detail-server-label = server
contact-server-key-offered = this server presents
contacts-server-pinned-badge = pinned
contacts-server-not-pinned-badge = not pinned
contacts-history-badge = { $count } previous
contacts-import-empty-hint = no contacts yet — import a smol:// address above, or write to someone
contacts-refresh-button = re-resolve
contacts-accept-token-title = accept token
contacts-accepted-hint = This contact's mail lands in your main tier.
contacts-unaccepted-hint = This contact's mail lands in requests until accepted.
contacts-history-title = previous keys ({ $count })
contacts-history-hint = Replaced by a signed rotation chain. Mail signed with these was sent before the change; rotation is not revocation, so a stolen key can still rotate onward.
contacts-history-replaced = replaced { $time }
## Settings — tab switcher labels
settings-tab-identity = Identity
settings-tab-server = Server
settings-tab-backup = Backup
settings-tab-advanced = Advanced
## Settings — Identity tab
settings-field-address = Address
settings-field-key = Key
settings-field-fingerprint = Fingerprint
settings-field-uri = URI
property-row-copy-tooltip = Copy the { $field }
settings-recovery-secret-title = Recovery secret
settings-secret-reveal-button = reveal
settings-secret-hide-button = hide
settings-secret-reveal-tooltip = Reveal the recovery secret
settings-secret-hide-tooltip = Hide the recovery secret
settings-secret-copy-tooltip = Copy the recovery secret
settings-secret-warning = Anyone who holds this can read your mail and write as you, and losing it loses the address with it — there is no reset. Keep it in a password manager.
# A copy button's own label, flashed on click instead of a toast.
copy-button-idle = copy
copy-button-success = copied
copy-button-failed = failed
settings-not-registered-value = not registered yet
settings-uri-claim-hint = claim an address to get one
## Settings — Server tab
settings-field-host = Host
settings-field-public-key = Public key
settings-public-key-not-pinned = not pinned yet
server-connection-title = Connection
server-timeout-title = Timeout
server-timeout-subtitle = Seconds before a network call gives up
server-fetching-title = Fetching
server-leave-mail-title = Leave mail on server
server-leave-mail-subtitle = Keep a copy on the server after fetching, so you can fetch it again from another app or device. When this is on, deleting a message removes it here and on the server.
## Settings — Backup tab
backup-page-description = One file with your mail, contacts, and server info, for moving to another app or keeping what the server no longer has. It's sealed to this identity and never includes the secret itself.
backup-export-title = Export
backup-export-subtitle = Write a backup file
backup-import-title = Import
backup-import-subtitle = Restore from a backup file
backup-export-dialog-title = Export backup
backup-import-dialog-title = Import backup
## Settings — Advanced tab
advanced-trust-section-title = trust
advanced-rotations-title = Rotations
advanced-rotations-description = Issues a fresh key from your secret with a signed certificate proving it replaces this one. Contacts accept the change from that chain, and the old key stays readable. Rotation is not revocation.
advanced-rotations-completed = Completed
advanced-rotate-button = Rotate identity
advanced-rotate-needs-account-error = rotate needs a registered account
advanced-first-contact-title = First contact
advanced-first-contact-description = A recipient who isn't a contact yet, and whose address carries no key, has to be looked up on their own server. That answer is only as good as the server: one with no pinned key can return a key of its own and read what you send.
advanced-strict-pinning-title = Require a pinned server
advanced-strict-pinning-subtitle = Stop that send and offer to pin the server's key first, so you can check it against what the operator published. With this off, the key's taken on trust, and the send is only reported as unverified afterwards.
advanced-logout-title = Sign out
advanced-logout-description = Removes this identity from this app entirely: the secret, pins, contacts, and every cached message. Without a backup of the secret, you can't get back in. Mail already fetched here may have no other copy anywhere, unless "Leave mail on server" was on. Whatever's still on the server comes back on the first fetch after you sign back in.
advanced-logout-button = Sign out and delete all data
## Onboarding
##
## The app name itself ("carrier") is a brand, not translated prose, and
## is left as a literal in code — see the extraction report.
onboard-welcome-title = welcome
onboard-welcome-description = Encrypted mail with no account and no password. Your identity is one secret, kept in this browser and nowhere else.
onboard-tagline = smolmail: one seed, sealed mail, five operations
onboard-create-button = Create a new identity
onboard-restore-button = Restore an existing identity from a seed
onboard-created-title = Write this seed down
onboard-created-description = It's the only secret, and it's shown once.
onboard-saved-button = I saved it
onboard-restore-title = Restore from a seed
onboard-restore-description = Paste the secret you saved. Your keys come back from it — it is all this client needs.
onboard-seed-entry-title = Seed: 32 bytes, base32 or hex
onboard-restore-go-button = Restore
## Signup
signup-server-title = Set up the server
signup-host-label = host
signup-fetch-key-button = Fetch the server's key
signup-continue-button = Continue
signup-start-over-button = Start over
signup-account-title = Choose your address
signup-mode-new-label = Create a new address
signup-mode-existing-label = I already have this address
signup-user-label = User
signup-invite-label = Invite token (if the server requires one)
signup-register-button = Register
signup-recall-button = Restore access
## Compose — the inline pin card shown after a blocked send
compose-pin-title = { $host } isn't pinned
compose-pin-body = { $address } isn't a contact yet, so carrier would have to ask this server for its key. A server with no pinned key can answer with one of its own, then read the message.
compose-pin-button-fetch = Fetch their server's key
compose-pin-button-send = Pin and send
## Dialogs
delete-dialog-title = Delete this message?
delete-dialog-body-kept = Deleting it here leaves the server's copy in place. Deleting it everywhere asks the server to drop that copy too.
delete-dialog-body-gone = This removes the only copy, which is sealed and stored on this device.
delete-dialog-everywhere-button = Delete everywhere
rotate-dialog-title = Rotate the identity?
rotate-dialog-confirm-button = Rotate
reset-dialog-title = Sign out and delete all data?
reset-dialog-confirm-button = Sign Out
# `$list` is the sender's own frontmatter rows, already typed by a human
# and reproduced verbatim — not translatable prose itself, just data
# interpolated into this one sentence.
reply-dialog-title = Carry the sender's fields into the reply?
reply-dialog-body = This message has its own headers:{"\u000A"}{"\u000A"}{ $list }{"\u000A"}{"\u000A"}Reply with copies of these fields, or start with none. The fields stay editable either way.
reply-dialog-cancel-button = Cancel reply
reply-dialog-without-button = Reply without
reply-dialog-copy-button = Copy fields
key-change-dialog-title = Replace this contact's key?
key-change-dialog-body = { $address } is already on file with a different key.{"\u000A"}{"\u000A"}known { $known_fingerprint }{"\u000A"}new { $offered_fingerprint }{"\u000A"}{"\u000A"}The address you were given carries the new key and would replace the one on file. If this contact didn't hand it to you themselves, stop: a key swapped in on the way reads everything you send them.
key-change-dialog-replace-button = Replace key
## Status bar
##
## `model.busy` also doubles as an internal state-machine key compared
## against literal English in app.rs (e.g. `self.busy.as_deref() ==
## Some("fetching")`), so that value itself is not translated — only its
## display here is, via this lookup from the internal label to a phrase.
## See the extraction report for the coupling this implies.
status-busy-fetching = fetching…
status-busy-refreshing = refreshing…
status-busy-registering = registering…
status-busy-restoring = restoring…
status-busy-rotating = rotating…
status-fetching-progress = fetching… { $count } in inbox
## First contact / server trust
first-contact-blocked-error = { $address } isn't a contact yet, and { $host } isn't pinned. Pin their server's key to send.
server-key-offered-note = The server presented this key. Pin it only if the fingerprint matches what the operator published.
server-key-already-pinned-note = This server's key is already pinned.
server-key-pinned-note = Server key pinned
connect-unpinned-warning = { $host } is not pinned; its key is { $key }.{"\u000A"}Lookups from this session are UNVERIFIED.
recall-rotation-not-found-error = the key bound to { $address } is not derived from this master within { $max } rotations
contacts-refresh-embedded-key-error = that address already carries a key; use import instead
# Shared by a first send to a never-before-seen recipient and a contact's
# own "re-resolve" button — both land here the same way, by RESOLVE finding
# no existing key for the address.
contacts-resolved-note = { $address } pinned (trust on first use)
contacts-resolved-note-unverified = { $address } pinned (trust on first use, UNVERIFIED server)
contacts-refresh-unchanged-note = { $address }: key unchanged
contacts-refresh-rotated-note = { $address } rotated its key; a signed chain confirms it.{"\u000A"}now { $key }
contacts-refresh-no-chain-warning = { $address } presents a different key with no valid rotation chain.{"\u000A"}Verify out of band, then import the new smol:// address.