Block Themes & Patterns

Patterns, block-theme menus, and the two pieces of text every site has — translated where the block editor actually keeps them.

Two patterns that look identical, stored two different ways

Drop a pattern into a page and WordPress offers two things that are indistinguishable on the canvas and behave nothing alike underneath. What separates them is where the words end up — and that decides where the translation has to live. Switch between them and watch the right-hand panel:

Choose a pattern kind
About the bakery — Editor

Fresh sourdough

Baked every morning on a fifty‑year‑old starter, and usually gone by noon.

Opening hours

Monday to Friday, 7am–4pm. Saturday, 8am–1pm.

What the page stores

wp_posts.post_content
<!-- wp:heading -->
<h2>Fresh sourdough</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Baked every morning…</p>
<!-- /wp:paragraph -->

<!-- wp:group -->
<h3>Opening hours</h3>
<p>Monday to Friday…</p>
<!-- /wp:group -->
wp_posts.post_content
<!-- wp:heading -->
<h2>Fresh sourdough</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Baked every morning…</p>
<!-- /wp:paragraph -->

<!-- wp:block {"ref":412} /-->

The words live in the page. The inserter copied the pattern’s blocks in and kept no link back to it. Translating the page carries that text along, exactly like a paragraph you typed yourself.

The words live in the pattern. The page holds a reference and nothing else. Translate the pattern once and every page pointing at it follows.

Patterns are translated as content in their own right rather than as part of whatever page happens to embed them. Switch them on under Advanced content types in Settings → Translation and each one gains the same Translations row as a post or a product — one entry to maintain, however many pages reuse it.

One reference, the right language

Your pages keep the reference they were saved with. At render time PerfLocale points it at the translation for the language being viewed, so the same page serves the English pattern to English visitors and the German one to German visitors.

Patterns nested inside a Group or Columns work the same way, and per-instance overrides are stored in the page rather than the pattern, so they survive translation untouched.

Fallbacks that never leave a hole

WordPress renders nothing at all for a pattern or menu reference it will not accept. A blank space where your content used to be is worse than untranslated text, so every one of those conditions is checked before anything is substituted:

  • Translated

    The translation is published and valid — it is served.

  • No translation

    The original renders.

  • Draft

    The original renders. An unpublished draft never replaces live content.

  • Trashed or wrong type

    The original renders.

That is a deliberate guarantee, not a side effect of how it happens to be written.

Block themes do not use classic menus. A menu there is its own record, referenced by the Navigation block in the same way a page references a synced pattern.

Link addresses are already translated with no setting at all — a menu item pointing at a post resolves to that post’s translation. What is not translated by default is the visible label, because the label lives in the menu rather than in the target. Enable Navigation Menus to translate labels too.

Site title and tagline

Your site title and tagline are options rather than posts or theme strings, so neither the content pipeline nor a string scanner used to reach them. They now appear on the Strings screen as Site Title and Tagline, and translate like any other string. Nothing to enable and no scan to run — they are registered when the plugin is activated or updated.

Your stored title and tagline are never modified. The translation is served on the front end only, and PerfLocale refuses any write that would put a translated value back over the original — including from wp-admin, WP-CLI, XML-RPC and the REST API, all of which read and re-save options in ways that would otherwise overwrite your source text.

From your own code

Rendering part of a page in another language — a custom template, a page-builder code block, a notification built outside its recipient’s request:

echo perflocale()->with_language( 'de', fn() => do_blocks( $markup ) );

Inside that window, string translations, the site title, and pattern and menu references all follow the imposed language, and it is restored afterwards even if your callback throws. See the Helper API for the full surface.

What this does not cover

Translating the content of block templates and template parts — text you type into a template in the Site Editor — is not implemented. Customised templates keep working normally, and anything translatable embedded in them still translates, but the template’s own text does not. There is deliberately no setting for it: a checkbox with nothing behind it would be worse than none at all.

Theme templates that draw their text from the theme’s own translatable strings are already covered by String Translation.