Repository navigation
Fix the server not loading translations, which broke hydration - #207
Merged
Merged
Conversation
The server-side i18next backend resolved its locales from the working directory (`apps/locales`, which doesn't exist), so the server rendered raw message keys while the client rendered translations. The resulting hydration mismatch made React discard and re-render the whole server-rendered page on every load, detaching any element grabbed before hydration (e.g. the image block measured by `image-block-style-fields.test.ts`). Resolve the locales relative to the module instead: `public/locales` in development and `build/client/locales` in production. Add acceptance tests asserting the server renders translated messages and that the server-rendered image block stays connected after hydration.
Member
Author
|
@pnicolli merging, since I think it's important, at least to have this fixed. We can improve later, in case we find a better way. |
sneridagh
added a commit
that referenced
this pull request
Oct 2, 2026
* a3-content-css-pilot: Measure the image block width once again in the style fields test Fix the server not loading translations, which broke hydration (#207)
sneridagh
added a commit
that referenced
this pull request
Oct 2, 2026
… into b1b-anatomy-gaps * origin/b1a-content-contract-foundation: Measure the image block width once again in the style fields test Fix the server not loading translations, which broke hydration (#207)
This was referenced Oct 2, 2026
sneridagh
added a commit
that referenced
this pull request
Oct 6, 2026
…#199 A3) (#205) * Move the image block and inner container styles to styles/content.css Step A3 of #199, the pilot for the content CSS architecture. The image block drops its CSS Module and the block inner container its duplicated Public UI and CMSUI rules: both now live in styles/content.css, loaded in both user interfaces inside the plone-content cascade layer. The editor gets the .content-area content root, and Agave ships its first content token. Acceptance tests prove that a theme token reaches the image block in both user interfaces and that its layout doesn't depend on the public theme's reset. * Make the image block reset test independent of fonts A centered image right after a float is pushed below it by an amount that depends on how tall the text next to the float is, which varies with the fonts installed. The test page now puts the floated image last. * Measure the image block width once again in the style fields test The retry worked around React replacing the server-rendered DOM on hydration. #207 fixed the cause (the server didn't load the translations), so the nodes now stay connected.
sneridagh
added a commit
that referenced
this pull request
Oct 6, 2026
…tent.css (#216) * Move the Tailwind reset out of the top cascade layer in the CMS UI Step A1 of #199. The CMS UI loads Tailwind with a plain import, so its theme variables, preflight and utilities land in the declared theme, base and utilities layers instead of a top-level cmsui layer. The reset now sits below every other layer. Removes the cmsui layer and adds the plone-content layer for block content CSS. The quanta table row drag handle no longer relies on the global reset to drop the basic button styles. * Add the styles/content.css entry point to the add-on styles loader Step A2 of #199. Every add-on's styles/content.css is aggregated into a generated .plone/content.css, which both the Public UI and the CMSUI loaders import first, inside the plone-content cascade layer. Add-ons write block styles once and get them in both user interfaces. Documents the convention, its authoring rules and how to override block styles. * Move the image block and inner container styles to styles/content.css Step A3 of #199, the pilot for the content CSS architecture. The image block drops its CSS Module and the block inner container its duplicated Public UI and CMSUI rules: both now live in styles/content.css, loaded in both user interfaces inside the plone-content cascade layer. The editor gets the .content-area content root, and Agave ships its first content token. Acceptance tests prove that a theme token reaches the image block in both user interfaces and that its layout doesn't depend on the public theme's reset. * Add the block content classname contract foundations Phase 1a of #200. An acceptance test checks that the public block content only uses contract classnames, against a list of pending Tailwind classes that may only shrink as nodes are converted. Stylelint rules guard styles/content.css. Lists get the block-p__list and block-p__item parts and a data-list-style-type attribute, and the classname contract is documented for themers. * Make the image block reset test independent of fonts A centered image right after a float is pushed below it by an amount that depends on how tall the text next to the float is, which varies with the fonts installed. The test page now puts the floated image last. * Add h1 and hr to the Plate block anatomy Phase 1b of #200. h1 (category text) and hr (category separator) were the Plate-native blocks without anatomy classnames. In the public view, the separator now gets the existing separator category spacing. * Measure the image block width once again in the style fields test The retry worked around React replacing the server-rendered DOM on hydration. #207 fixed the cause (the server didn't load the translations), so the nodes now stay connected. * Move the text block styles to styles/content.css Phase 2 of #200. Paragraph, title, headings, blockquote and separator are styled by plain CSS in @plone/plate's styles/content.css instead of Tailwind utilities, in both the public renderer and the editor. Values read the theme's Tailwind variables with Tailwind's defaults as fallback. Editor affordances stay Tailwind. A new acceptance test checks the text blocks render the same under any public theme reset; the reset helpers move to the shared Playwright tooling. * Move the inline mark styles to styles/content.css Phase 3 of #200. Inline code, keyboard input, highlight, links and mentions are styled by plain CSS in @plone/plate's styles/content.css instead of Tailwind utilities. Mention marks become data attributes. Comment and suggestion marks render as plain text in the public view; the editor keeps showing them. New tests: a visual test for the inline marks, a contract check for inline and editorial marks, and a reset independence test for the inline styles. * Move the list styles to styles/content.css Phase 4 of #200. Lists, to-do items and the read-only to-do checkbox of the rendered content are styled by plain CSS in @plone/plate's styles/content.css instead of Tailwind utilities. Checked to-do items get a data-checked attribute. The editor's interactive checkbox stays a Tailwind editor control. A new acceptance test checks lists render the same under any public theme reset, and the reset tests share their measuring helpers. * Move the code block styles to styles/content.css Part of #200. * Move the table styles to styles/content.css Part of #200. * Remove the Plate media nodes from Aurora's presets Nothing in Aurora's editor could insert them, pasted iframes became embeds the public view didn't render, and file drops needed an upload backend Aurora doesn't have. Aurora uses Plone blocks for media. The stock full preset keeps them. Part of #200. * Move the structural block and content root styles to styles/content.css Callout, toggle, columns, table of contents and the rendered content root. The rendered content no longer has any Tailwind classes, so the contract test's PENDING list is gone. Part of #200. * Move the table drag handle fragment to @plone/quanta The quanta Table moved from @plone/components to @plone/quanta in #212. * Keep EditorView as the Tailwind-free content root PlateRenderer renders EditorView again instead of PlateView directly, and EditorView no longer applies editorVariants: the content root is styled by styles/content.css. EditorView was only used by PlateRenderer, so it isn't left as dead code that would bring the Tailwind root classes back.
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.
Problem
While working on #199 (step A3),
image-block-style-fields.test.ts› "combinations set in the editor render correctly after saving" was flaky: the.image-blockelement it measured was sometimes detached (isConnected === false, 0x0 rect) shortly after page load.The cause is not the image block. The server-side i18next backend in
apps/aurora/app/i18next.server.tsresolved its locales withresolve('../locales/...'), relative to the working directory (apps/aurora), i.e.apps/locales, which doesn't exist. So the server rendered raw message keys (e.g.layout.slots.headertools.anonymousTools.login) while the client rendered the translations ("Log In"). React reports a hydration text mismatch and discards the whole server-rendered tree, re-rendering it on the client — on every load. The apparent "1 in 6" flakiness was only whether the test grabbed the element before or after hydration.Fix
Resolve the locales relative to the module instead of the working directory:
public/localesin development (app/i18next.server.ts) andbuild/client/localesin production (build/server/index.js).Tests
New
apps/aurora/acceptance/tests/hydration.test.ts:.image-block(captured atDOMContentLoaded) is still connected, is the current.image-block, and has a non-zero width once React owns it.Both fail without the fix. With it, the full
pnpm acceptance-testsuite passes (166 tests), and the previously flaky style-fields test passed 6/6 with--repeat-each=6. Dev build shows no remaining hydration warnings.