chore: articles localization groundwork

This commit is contained in:
Florian Sylvain committed 2026-10-31 21:22:44 +01:00
1 parent 0bdcca8a90
commit 99a74dc3a2
23 files changed
+3524

No files matched your search

@@ -0,0 +1,24 @@
# Add a translation
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L4 Add a translation".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/article/{id}/edit?dialog=add-translation&lang=fr`
### Add a translation (group "L4 Add a translation", 8 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Copy from source | Editor → language menu → Add translation | `loc.l4.form` | `at:form` |
| 2 | Start empty | Title only | `loc.l4.empty` | `at:empty` |
| 3 | Creating | Submit in flight | `loc.l4.saving` | `at:saving` |
| 4 | Exists, readable | 409 language_exists, Open offered | `loc.l4.dup` | `at:dup` |
| 5 | Exists, not readable | Neutral 409, no Open | `loc.l4.dupHidden` | `at:dupHidden` |
| 6 | Failed | 5xx, entries kept | `loc.l4.fail` | `at:fail` |
| 7 | Source unavailable | Source deleted or access lost mid-flow | `loc.l4.gone` | `at:gone` |
| 8 | Long dialog | Long title, many authors and images; body scrolls | `loc.l4.long` | `at:long` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,27 @@
# Article list and coverage
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L7 Article list and coverage".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/articles?site&lang&tab=all|missing|review&q&status&author&seo&page&size`
### Article list and coverage (group "L7 Article list and coverage", 11 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | All languages | Stories | `loc.l7.all` | `li:all` |
| 2 | French selected | Versions | `loc.l7.fr` | `li:fr` |
| 3 | Not in French | Missing-translation discovery | `loc.l7.frMissing` | `li:frMissing` |
| 4 | Nothing missing | Separate fixture: Press (3 stories, all translated). Empty; no summary, no pager | `loc.l7.emptyMissing` | `li:emptyMissing` |
| 5 | No results | Search "zinc"; every count 0 | `loc.l7.noResults` | `li:noResults` |
| 6 | Loading | | `loc.l7.frLoading` | `li:frLoading` |
| 7 | Failed | Filters kept | `loc.l7.listFail` | `li:listFail` |
| 8 | Limited access | No dashed missing chips | `loc.l7.limited` | `li:limited` |
| 9 | Mobile filter sheet | Journal, French, Draft: 2 results | `loc.l7.filters` | `li:filters` |
| 10 | Tabs scrolled | Not in French reachable; fade and chevrons | `loc.l7.tabsScroll` | `li:tabsScroll` |
| 11 | Long labels, many languages, filters | Separate fixture: Atelier (8 languages), active filter chips | `loc.l7.long` | `li:long` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,21 @@
# Permissions, conflicts, site moves
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L11 Permissions, conflicts, site moves".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `various`
### Permissions, conflicts, site moves (group "L11 Permissions, conflicts, site moves", 5 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Session expired | Draft kept locally | `loc.l11.session` | `pm:session` |
| 2 | Concurrent update | Four choices, local work kept | `loc.l11.conflict` | `pm:conflict` |
| 3 | Move: language missing | | `loc.l11.move` | `pm:move` |
| 4 | Move: address conflict | | `loc.l11.moveSlug` | `pm:moveSlug` |
| 5 | Move: no permission | Neutral | `loc.l11.movePerm` | `pm:movePerm` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,34 @@
# Editor: language navigation
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L5 Editor: language navigation".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/article/{id}/edit (one id per version)`
### Editor: language navigation (group "L5 Editor: language navigation", 18 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Default (French draft) | Editable title, language menu, badges | `loc.l5.default` | `ed:default` |
| 2 | Menu: four languages | Open menu | `loc.l5.menu` | `ed:menu` |
| 3 | Menu: two languages | Two-language site | `loc.l5.two` | `ed:two` |
| 4 | Menu: many languages | Scrolls inside the viewport, with filter | `loc.l5.many` | `ed:many` |
| 5 | Unsaved changes | Dirty badge; Save enabled | `loc.l5.dirty` | `ed:dirty` |
| 6 | Unsaved draft: Save and publish | Button reads Save and publish French; Save stays separate | `loc.l5.dirtyPublish` | `ed:dirtyPublish` |
| 7 | Unsaved online version | Save updates the live page; Unpublish stays available | `loc.l5.onlineDirty` | `ed:onlineDirty` |
| 8 | Save failed | Stays unsaved; Try saving again; nothing published | `loc.l5.saveFail` | `ed:saveFail` |
| 9 | Switch with unsaved changes | Choose English while dirty | `loc.l5.unsaved` | `ed:unsaved` |
| 10 | Saving | Save in flight | `loc.l5.saving` | `ed:saving` |
| 11 | Saved | Toast | `loc.l5.saved` | `ed:saved` |
| 12 | Loading version | Slow switch | `loc.l5.loading` | `ed:loading` |
| 13 | Switch failed | Stays on current version | `loc.l5.navFail` | `ed:navFail` |
| 14 | Version unavailable | Deleted or no access (neutral) | `loc.l5.gone` | `ed:gone` |
| 15 | Title: editing | Focus | `loc.l5.focus` | `ed:focus` |
| 16 | Title: invalid | Empty | `loc.l5.invalid` | `ed:invalid` |
| 17 | Title: saving | | `loc.l5.titleSaving` | `ed:titleSaving` |
| 18 | Title: save failed | Text kept, still unsaved, Try again | `loc.l5.failed` | `ed:failed` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,32 @@
# Site languages
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L1 Site languages".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/settings/languages`
### Site languages (group "L1 Site languages", 16 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Single language | Owner opens Languages on Archive (one language, pt-BR kept) | `loc.l1.single` | `sl:single` |
| 2 | Multilingual | Six languages, two disabled (Spanish, Italian) | `loc.l1.multi` | `sl:multi` |
| 3 | Loading | Request in flight | `loc.l1.loading` | `sl:loading` |
| 4 | Load failed | Network or server error | `loc.l1.error` | `sl:error` |
| 5 | Add a language | Add language | `loc.l1.add` | `sl:add` |
| 6 | Add failed | Server error, selection kept | `loc.l1.saveFail` | `sl:saveFail` |
| 7 | Duplicate language | Already enabled | `loc.l1.adddup` | `sl:adddup` |
| 8 | Make default | Row menu | `loc.l1.default` | `sl:default` |
| 9 | Disable with content | Row menu → Disable German | `loc.l1.disable` | `sl:disable` |
| 10 | Disable default blocked | Disable English | `loc.l1.disableDefault` | `sl:disableDefault` |
| 11 | Disable last blocked | Only one enabled | `loc.l1.disableLast` | `sl:disableLast` |
| 12 | Re-enable | Spanish row → Re-enable | `loc.l1.reenable` | `sl:reenable` |
| 13 | Remove (no content) | Italian (0 versions) | `loc.l1.remove` | `sl:remove` |
| 14 | Remove blocked | Spanish has versions | `loc.l1.removeBlocked` | `sl:removeBlocked` |
| 15 | Read-only (403) | Non-owner: list stays readable; no Add language, Re-enable or row menus | `loc.l1.readonly` | `sl:readonly` |
| 16 | Saved | After Add language | `loc.l1.saved` | `sl:saved` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,20 @@
# Metadata and public API
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L10 Metadata and public API".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `Search and sharing panel · /integration`
### Metadata and public API (group "L10 Metadata and public API", 4 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Search and sharing: French | Localized slug, canonical, alternates | `loc.l10.seo` | `seo:` |
| 2 | Public URL not configured | No pattern, no fabricated URL | `loc.l10.unset` | `seo:unset` |
| 3 | Social locale not set | fr has no region and none is configured: og:locale omitted | `loc.l10.noSocial` | `seo:noSocial` |
| 4 | Integration: languages | Proposed requests | `loc.l10.api` | `api:` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,20 @@
# New article
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L3 New article".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/articles (New article modal)`
### New article (group "L3 New article", 4 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Single language | Title and site only | `loc.l3.single` | `na:single` |
| 2 | Multilingual: new story | Language defaults to the site default | `loc.l3.multi` | `na:multi` |
| 3 | Translation of a story | Story picker + language | `loc.l3.translation` | `na:translation` |
| 4 | Site changed | Selected language not offered by new site | `loc.l3.sitechange` | `na:sitechange` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,23 @@
# Permission states (per version)
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L5b Permission states (per version)".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/article/{id}/edit`
### Permission states (per version) (group "L5b Permission states (per version)", 7 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Read-only version | No Save, Publish, Delete, toolbar | `loc.l5b.ro` | `ed:ro` |
| 2 | Read-only: menu | No Add translation row | `loc.l5b.roMenu` | `ed:roMenu` |
| 3 | Edit, no publish | Save only | `loc.l5b.p2` | `ed:p2` |
| 4 | Publish, no edit | Publish only; fields read-only | `loc.l5b.p3` | `ed:p3` |
| 5 | Sibling readable, not editable | German tagged Read only | `loc.l5b.p4` | `ed:p4` |
| 6 | Sibling not readable | German absent, no count | `loc.l5b.p5` | `ed:p5` |
| 7 | Can create, not modify all | Story delete and move disabled | `loc.l5b.p6` | `ed:p6` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,26 @@
# Publishing and deletion
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L8 Publishing and deletion".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `same as editor`
### Publishing and deletion (group "L8 Publishing and deletion", 10 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Publish French | Confirm, English untouched | `loc.l8.publish` | `pd:publish` |
| 2 | Save and publish French | Unsaved edits: one action saves first, then publishes | `loc.l8.saveAndPublish` | `pd:saveAndPublish` |
| 3 | Save failed, nothing published | Toast; edits kept and retryable | `loc.l8.saveFailPublish` | `pd:saveFailPublish` |
| 4 | Unpublish French | Confirm | `loc.l8.unpublish` | `pd:unpublish` |
| 5 | Delete French version | Confirm | `loc.l8.delete` | `pd:delete` |
| 6 | Delete a source version | Warns about review reference | `loc.l8.deleteSource` | `pd:deleteSource` |
| 7 | Delete last version | Deletes the story | `loc.l8.deleteLast` | `pd:deleteLast` |
| 8 | Delete story blocked | Neutral, no version named | `loc.l8.deleteStory` | `pd:deleteStory` |
| 9 | Published | Toast | `loc.l8.done` | `pd:done` |
| 10 | Publish failed | Toast | `loc.l8.fail` | `pd:fail` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,27 @@
# Source reference
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L6 Source reference".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/article/{id}/edit?ref=:sourceId`
### Source reference (group "L6 Source reference", 11 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Side by side | Show source reference | `loc.l6.split` | `src:split` |
| 2 | Reference hidden | Hide source reference; button returns | `loc.l6.closed` | `src:closed` |
| 3 | Reopened | Show source reference again; scroll positions kept | `loc.l6.reopen` | `src:reopen` |
| 4 | Change reference | Menu; tracked source stays English | `loc.l6.changeRef` | `src:changeRef` |
| 5 | Narrow desktop (1024 px) | True 1024 px frame | `loc.l6.narrow` | `src:narrow` |
| 6 | Long content | Both panes scroll independently | `loc.l6.long` | `src:long` |
| 7 | Arabic beside English | dir=rtl on the Arabic title and body only | `loc.l6.rtl` | `src:rtl` |
| 8 | Mobile: editing | Segment | `loc.l6.mobileEdit` | `src:mobileEdit` |
| 9 | Mobile: source | Segment | `loc.l6.mobileSrc` | `src:mobileSrc` |
| 10 | Mobile: closed | Show source reference button | `loc.l6.mobileClosed` | `src:mobileClosed` |
| 11 | Reference unavailable | Deleted or unreadable | `loc.l6.unavail` | `src:unavail` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
@@ -0,0 +1,26 @@
# Freshness and review
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L9 Freshness and review".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `editor banner · list badge`
### Freshness and review (group "L9 Freshness and review", 10 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Source updated | English changed after review | `loc.l9.warn` | `fr:warn` |
| 2 | Published, needs review | | `loc.l9.pub` | `fr:pub` |
| 3 | Mark reviewed | Confirm with revisions | `loc.l9.review` | `fr:review` |
| 4 | Source changed again | Revision 9 while reviewing 8 | `loc.l9.changed` | `fr:changed` |
| 5 | Translation changed | Saved by someone else while confirming | `loc.l9.changedTr` | `fr:changedTr` |
| 6 | Choose tracked source | Cycle prevented | `loc.l9.replace` | `fr:replace` |
| 7 | Source unavailable (access) | History kept | `loc.l9.inaccessible` | `fr:inaccessible` |
| 8 | Source deleted | Replace | `loc.l9.gone` | `fr:gone` |
| 9 | Reviewed | Toast | `loc.l9.done` | `fr:done` |
| 10 | Review failed | Toast | `loc.l9.fail` | `fr:fail` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.
+21
View File
@@ -0,0 +1,21 @@
# First-time setup for existing articles
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L2 First-time setup for existing articles".
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Route: `/settings/sites/:key/languages (banner) · /settings/languages/setup`
### First-time setup for existing articles (group "L2 First-time setup for existing articles", 5 states)
| # | State | Trigger | Stable ID | Frame selector |
|---|---|---|---|---|
| 1 | Ready to assign | Journal (en), Notes (no locale, must choose), Archive (pt-BR kept) | `loc.l2.ready` | `su:ready` |
| 2 | Site with no articles | Gallery has no articles; en-GB kept, confirm and Save | `loc.l2.empty` | `su:empty` |
| 3 | Applying | POST in flight | `loc.l2.applying` | `su:applying` |
| 4 | Done | 16 articles labelled | `loc.l2.done` | `su:done` |
| 5 | Failed | Nothing changed; choices kept | `loc.l2.fail` | `su:fail` |
Exact rendered copy and geometry are in `source/LocaleFrame.dc.html` for the selector above. Use Nuxt UI mappings in `components.md`; the frame markup is a visual reference, not production component code.
The standard captures are 1440×900 and 390×844 in light and dark. The narrow reference state also uses 1024×768. The visual harness must support these sources and sizes before this screen can pass its gate. No visual exceptions or new clock-sensitive skips are approved.