fix(content): write a media or relation value to every locale at once - #227
Merged
Conversation
added 2 commits
September 2, 2026 10:24
On an i18n model, saving an image field wrote only the locale selected in the editor. The other locales kept the previous asset and nothing said so. A non-technical editor swapped a hero image with `en` selected, the site rendered `tr`, and nothing changed; someone with repo access had to diff the locale files to find out why. A delivery URL and an entry ref carry no language, but the editor scoped them per locale like prose. The schema has no `localized` flag yet, so the field type decides: image, video, file, relation and relations are locale-agnostic (shared/utils/locale-agnostic-fields.ts). The content engine carries their values into the model's other locales in the same commit (content-engine/locale-fanout.ts) — only into entries that already exist there, and only where the value differs, so a no-op save stays a no-op. Studio's meta semantics apply to each locale written. Documents get the same treatment, each locale keeping its own body. The save result names the fields and locales; the editor toast repeats it, the edit form marks these fields as applying to every locale, the agent's tool result carries it so it never offers to "do the same for tr", and media usage is recorded per locale written. Closes #207
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #207.
On an
i18n: truemodel, animage(orrelation) save wrote only the editor's active locale; the other locales kept the old value and nothing said so. A hero image swapped inenleft thetrsite unchanged.This is the issue's option (3) as an inferred default: the schema has no
localizedflag yet, so the field type decides.image/video/file/relation/relationsare locale-agnostic (shared/utils/locale-agnostic-fields.ts), and their values are written to every locale of the model in the same commit.content-engine/locale-fanout.ts, wired intosaveContentandsaveDocument). Extra entries for the other locales go into the sameplanContentSavecall, so one branch, one commit, one merge. Only entries that already exist in the other locale are written (a one-image partial entry would fail that locale's required fields, and the gap is a coverage problem this save was not asked to fix); a locale that already holds the value is skipped, so the byte-identical no-op short-circuit still fires. Studio's meta override (status kept,updated_by/updated_atstamped) runs for each locale written. Documents keep each locale's own body. The commit message notesShared across locales (tr): cover.WriteResult.sharedAcrossLocales = { fields, locales }, passed through to the agent's tool result (so it reports it rather than offering to repeat the save fortr) and to the content route.When
@contentrain/typesgrows a per-fieldlocalizedflag, it should replace the type list rather than sit beside it (noted in CLAUDE.md). Until then there is no per-project opt-out; per-locale images were not a case anyone had, and the silent divergence was.Test plan
tests/unit/content-engine.test.ts— the reported case (image swapped inenlands intr, Turkish prose intact,trmeta status kept + author stamped); prose-only save leavestralone; already-equal value leavestralone; relation on a collection carried only into entries that exist intr; non-i18n model unchanged; document cover carried with the Turkish body kepttests/unit/locale-agnostic-fields.test.ts,use-content-editor.nuxt.test.ts(toast)nuxt typecheck; unit + integration green; the nuxt project passes file-by-file (three unrelated files time out locally when the whole project runs right afternuxt typecheck— CI is the arbiter)site-settingswithenselected, swapguides_band_background, save; confirm the toast namestr, the branch touches both locale files, and thetrsite shows the new asset🤖 Generated with Claude Code
https://claude.ai/code/session_01Chid3TnLdPHjsKip4n63Ky