contact messages: document the settings, localization and toggle

docs/messages.md gains the site-settings/localization section (enabled
toggle, mailto link, chunk-keyed string translations and their manual
override UI); docs/localization.md notes the site strings riding the
title/nav pipeline; AGENTS.md's i18n/translate bullets match.
This commit is contained in:
LeoVasanko committed 2026-09-28 06:35:55 +00:00
1 parent dd82005f6c
commit 106712a359
3 files changed
+53 -12

No files matched your search

+2 -2
View File
@@ -20,8 +20,8 @@ Pagerite is a CMS. See `docs` for the full design and implementation details. Ke
- `feeds.py` — machine-readable exports: `/llms.txt` (compact index linking each article's `.md` Markdown URL), `/feed.json` (JSON Feed 1.1), `/feed.xml` (RSS 2.0 + atom:link); the feeds carry all published articles with full content, linked from every page `<head>` and the sitemap, recorded in analytics.
- `data.py` — msgspec Structs for the kanta database.
- `chunks.py` — block-level Markdown chunking and content-hash keys for the chunk stores (docs/migrate.md).
- `i18n.py` — language selection, translation assembly (chunks + overrides) and translated-edit recording (per-chunk user overrides in `Data.overrides`, per-language title overrides, refresh).
- `translate.py` — translator service protocol (msgspec structs), the connected-client `Dispatcher` (job pipeline, result validation) and pending/store core for the `/_translate/{key}` WebSocket (docs/localization.md); api.py only registers the route.
- `i18n.py` — language selection, translation assembly (chunks + overrides) and translated-edit recording (per-chunk user overrides in `Data.overrides`, per-language title overrides, refresh), plus the site-string translations (`site_string`/`set_string_translation`) for the contact label/subject (docs/messages.md).
- `translate.py` — translator service protocol (msgspec structs), the connected-client `Dispatcher` (job pipeline, result validation) and pending/store core for the `/_translate/{key}` WebSocket (docs/localization.md); api.py only registers the route. Pending title/nav work includes the site contact strings, so the contact chrome localizes automatically.
- `segments.py` — the translation round trip: fragments split into pure-prose wire segments (via markdown.make_md's verbatim parser; link- and formatting-carrying blocks stay whole, link/formatted texts inline, Markdown stripped) and translations spliced back by source offset, link/formatting markdown re-inserted at weight-mapped positions (docs/localization.md).
- `migrations.py` — kanta migrations (`migrate_vN`); ALL schema/storage upgrades live here (raw state dict before struct decoding), never in the app lifespan: v1 moves legacy in-db file blobs to the on-disk store and rebuilds the legacy flat `pages` as the menu tree, v2 rewrites `/_f/{hash}.ext` image links to the extension-less form, backfills AVIF/WebP/JPEG derivatives on disk and drops the obsolete `version` field.
- `markdown.py` — markdown-it-py renderer.
+7
View File
@@ -503,6 +503,13 @@ offerable to clients of another approach.
placeholders lost is skipped individually and likewise stays pending
for a scoped title job.
Site-level settings strings (the contact-messaging label/subject,
docs/messages.md) localize through the same machinery: they are emitted
as title-kind fragments by `pending_items` and ride nav jobs as extra
top-level list items; `i18n.site_string` looks them up at render time,
and manual overrides are edited in the site editor's messaging block
(`i18n.set_string_translation`).
`scripts/llm_translator.py` is the reference markdown+article+nav client
(instruct LLMs via an OpenAI Chat Completions endpoint or ollama's native
API); `scripts/translator.py` (Seed-X) is untouched and announces
+44 -10
View File
@@ -11,12 +11,16 @@ existing WebSockets; there is no REST polling anywhere.
- `pagerite/messages.py` — the feature's core: the strict message renderer,
thread store ops, wire payloads, both socket protocols, the admin unread
count and the `/_contact/files` upload route.
- `pagerite/data.py` — `Data.contact` (`ContactThread`/`ContactMessage`).
- `pagerite/data.py` — `Data.contact` (`ContactThread`/`ContactMessage`)
and the site settings (`contact_enabled`, `contact_label`,
`contact_email`, `contact_subject`).
- `pagerite/tracking.py` — the sockets the protocol rides (see below).
- `pagerite/api.py` — `/_api/settings` carries `contact_unread` (the admin
icon badge seed — the probe runs on every page load, no polling).
- `pagerite/views.py` — the `{contact:}` directive (`_contact_tag`) and the
on-demand bundle's asset config.
icon badge seed — the probe runs on every page load, no polling) and the
contact configuration (with `?lang=` overrides for the label/subject).
- `pagerite/views.py` — the `{contact:}` directive (`_contact_tag`), the
localized contact strings (`_contact_config`) and the on-demand bundle's
asset config.
- `frontend/src/contact-main.js` + `ContactOverlay.vue` — the overlay entry
and shell (paskia's shared blur backdrop, centered dialog, full-screen on
mobile), imported on demand by `pagerite.js` on icon/trigger clicks.
@@ -30,12 +34,40 @@ existing WebSockets; there is no REST polling anywhere.
A lone `{contact: Label}` line in article Markdown (the block-directive
machinery of `markdown.py`) renders
`<button class="contact-trigger">Label</button>` ("Contact us" when the
label is empty). `pagerite.js` click-delegates these buttons and lazy-loads
`<button class="contact-trigger">Label</button>`. An empty label falls
back to the configured site label (`Data.contact_label`, localized —
below), ultimately the built-in "Contact us". `pagerite.js`
click-delegates these buttons and lazy-loads
the contact bundle; the editor preview renders the same button inert, and
description/card mining resolves the tag to nothing. The label lives in the
chunk, so translated pages localize it like any other text. Feeds render the
tag as its literal source (no directive context).
description/card mining resolves the tag to nothing. A per-button label
lives in the chunk, so translated pages localize it like any other text.
Feeds render the tag as its literal source (no directive context). When
messaging is disabled the tag renders nothing at all.
## Site settings and localization
The site editor's messaging block holds the feature's configuration
(`/_api/settings`): `contact_enabled` (off = no trigger buttons, no
visitor corner icon, sends rejected; admins keep the inbox for existing
threads), `contact_email` (a mailto link in the visitor dialog, its
subject prefilled) and the `contact_label`/`contact_subject` strings
(the label doubles as the dialog's title and the buttons' default; the
subject defaults to the label).
The two strings localize like titles: translations live in the
chunk-keyed `Data.trans` store (`i18n.site_string` looks them up at
render time — the *effective* label, so the built-in default localizes
too) and the translator service picks them up automatically
(`pending_items` emits them as title-kind fragments; nav-mode jobs carry
them as extra top-level list items). Manual overrides are edited in the
same messaging block: its language selector switches the label/subject
fields to a translation, saved via `PUT /_api/settings?lang=` into the
same store (`i18n.set_string_translation`; empty or the original's text
drops the override). The localized strings reach the client through the
page's asset config (`pagerite:contact-label` / `-subject` / `-email`,
absent entirely when disabled — pagerite.js reads that as "visitors get
no icon"); `contact-main.js` re-reads them on every open, so a language
switch is reflected immediately.
## Visitor side
@@ -179,4 +211,6 @@ Appends are single transactions (`contact` / `contact:reply` /
- Message source ≤ 8000 chars; uploads ≤ 20 MB and ≤ 10 pending per
session; payloads cap at 100 threads × last 200 messages.
- No thread moderation (delete/block), no orphan-upload GC for files
orphaned by a server restart, and panel strings are English-only.
orphaned by a server restart, and the panels' own UI strings (composer
hints, "you", inbox labels) are English-only — the *configurable* site
strings (label, subject) do localize (above).