chore: redesign article localization before implementation

This commit is contained in:
Florian Sylvain committed 2026-11-01 14:57:07 +01:00
1 parent 99a74dc3a2
commit 8c4a1825ab
31 files changed
+3365 -882

No files matched your search

+28 -14
View File
@@ -1,20 +1,34 @@
# New article
# Localization: new article and add translation
Board: RenewCMS Screens Localization. Frame: LocaleFrame. Data: locale-fixtures.js (single fixture source), tables in locale-spec.js. UI copy says "article", never "story". No revision numbers, IDs or HTTP status names in user-facing text.
Visual reference: `RenewCMS Screens Localization.dc.html`, group "L3 New article".
## L3 New article
Route: /articles (New article modal)
API: existing POST /v1/article/ + proposed lang, story_id
Read [localization.md](../localization.md) first. Its integration decisions supersede conflicting board annotations. These states describe target behavior, not shipped behavior.
Single-language sites show no language field. Multilingual sites show Language and a New article / Translation of an existing article choice. The translation path uses the same endpoint and rules as Add translation. The picker lists only articles the user can read; the chosen version is the source.
Route: `/articles (New article modal)`
| ID | State | Trigger | Selector | Sizes | Fixture |
|---|---|---|---|---|---|
| loc.l3.single | Single language | Title and site only | LocaleFrame{s:{v:"na",x:"single"}} | 1440, 390 | Archive |
| loc.l3.multi | Multilingual: new article | Language defaults to the site default | LocaleFrame{s:{v:"na",x:"multi"}} | 1440, 390 | Journal |
| loc.l3.translation | Translation of an article | Article picker + language | LocaleFrame{s:{v:"na",x:"translation"}} | 1440, 390 | Journal |
| loc.l3.sitechange | Site changed | Selected language not offered by the new site | LocaleFrame{s:{v:"na",x:"sitechange"}} | 1440, 390 | Journal, Notes |
### New article (group "L3 New article", 4 states)
## L4 Add a translation
Route: /article/{id}/edit?dialog=add-translation&lang=fr
API: proposed: POST /v1/article/{id}/translations
| # | 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` |
Always creates a draft. Source: the user picks which readable version to copy from (default: the default-language version if readable, else the first readable). The source version is captured in the same transaction as the copy. Copied text stays in the source language until edited; the version starts as Needs review. Start empty: no tracked source, so freshness shows No source. The primary action stays in the sticky footer on mobile; the body scrolls.
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.
| ID | State | Trigger | Selector | Sizes | Fixture |
|---|---|---|---|---|---|
| loc.l4.form | Copy from source | Editor → language menu → Add translation | LocaleFrame{s:{v:"at",x:"form"}} | 1440, 390 | Journal |
| loc.l4.empty | Start empty | Title only | LocaleFrame{s:{v:"at",x:"empty"}} | 1440, 390 | Journal |
| loc.l4.saving | Creating | Submit in flight | LocaleFrame{s:{v:"at",x:"saving"}} | 1440, 390 | Journal |
| loc.dup.readable | Exists, readable | Conflict; Open offered | LocaleFrame{s:{v:"at",x:"dup"}} | 1440, 390 | Journal |
| loc.dup.hidden | Exists, not readable | Neutral error, no Open | LocaleFrame{s:{v:"at",x:"dupHidden"}} | 1440, 390 | Journal |
| loc.l4.fail | Failed | Server error, entries kept | LocaleFrame{s:{v:"at",x:"fail"}} | 1440, 390 | Journal |
| loc.l4.gone | Source deleted | Deleted while the dialog was open | LocaleFrame{s:{v:"at",x:"gone"}} | 1440, 390 | Journal |
| loc.l4.unreadable | Source no longer readable | Access lost between opening and submitting | LocaleFrame{s:{v:"at",x:"unreadable"}} | 1440, 390 | Journal |
| loc.l4.langOff | Language disabled mid-flow | An owner disabled French while the dialog was open | LocaleFrame{s:{v:"at",x:"langOff"}} | 1440, 390 | Journal |
| loc.l4.long | Long dialog | Long title, many authors and images; body scrolls, footer stays | LocaleFrame{s:{v:"at",x:"long"}} | 1440, 390 | Journal |