Full Site Editing & Block Themes
In a block theme a great deal of what a visitor reads sits outside the post — a header, a footer, a page layout, a pattern reused across the site. PerfLocale translates each of those where the block editor actually keeps it.
1 What you edit
The canvas always shows — and saves — the original.
Translations
- English Current
- Deutsch Published
- Français Draft
One record per language, each edited on its own.
Full Site Editing
A header, a footer, a 404 page, an archive layout — in a block theme these are templates and template parts, stored separately from your content, so translating a page does not reach them: a German visitor reads a translated page underneath an English header.
PerfLocale gives each of them a translation of its own, created and edited like any other content. The canvas keeps showing — and saving — the original, while the Translations panel beside it holds one record per language.
2 What a visitor gets
- 🇺🇸 English
Original The default language — there is nothing to substitute.
- 🇩🇪 German
German translation Published, so it is served in the original’s place.
- 🇫🇷 French
Original The French translation is still a draft, so it is not used.
Published, or the original renders
On the front end the visitor’s language decides what is served, and a translation is used only once it is published. That is deliberate: WordPress renders an empty area for a template part it cannot resolve, so a half-finished header would leave a blank strip across the top of your site. Publishing is the signal that the translation is ready to be shown.
The template is chosen by WordPress exactly as it would be without the plugin. Only the content inside it is swapped, and only for a language whose translation is published.
Turning it on
Go to PerfLocale → Settings → Translation and tick Full Site Editing — one checkbox, Translate block theme templates and template parts. It is off by default.
The two types switch on together, deliberately. A page layout is a template and the header inside it is a template part, so enabling one without the other produces a half-translated page — a German body under an English header — which reads as a bug rather than as a choice you made.
Creating a translation
Once it is on, the templates and template parts you have customised appear on the Translations screen alongside your posts and pages, and are translated the same way: create the translation, edit its content, publish it.
You rarely need to create them by hand. Saving a template in your default language fills in any missing language, each one seeded with the original’s blocks and created unpublished — a draft, or Pending Review if that is your Default Translation Status — so nothing changes for visitors until you publish it. Add a language later and the next save picks it up. If you would rather create every translation yourself, return false from perflocale/fse/auto_create_translations.
The Site Editor carries a Translations panel in its settings sidebar. It lists every active language for the template or template part you are editing, marks the one you are looking at as Current, and links straight to each translation. One still in draft is marked Draft, with the line Not used until published - the original renders instead. beneath it. A template you have not customised yet has no record to translate, so the panel says so instead of showing an empty list.
When nothing is substituted
In each of these cases the page renders exactly as it would with the plugin switched off:
- no translation exists for the visitor’s language;
- a translation exists but is still a draft, pending or trashed;
- a translation is published but empty, or contains only whitespace;
- the source template was deleted, leaving the translation orphaned.
For the first three that means the template you customised. The last one is worth knowing about: the Site Editor’s Reset to theme default removes that customised record, while its translation is a separate record that survives. PerfLocale identifies a translation by its link to the source rather than by its name, so an orphaned translation stops being used rather than serving stale text indefinitely — and WordPress renders the theme’s own version of the template, exactly as it would for one you had never customised.
What does not change
Which template WordPress chooses never changes — only what it says. The template hierarchy resolves exactly as it would without the plugin, and the template’s id is never rewritten.
The Site Editor always shows and saves the original. Translated content is substituted on the front end, for visitors, and is never loaded into the canvas — because if it were, saving would write the German text over your English source with no undo. Translations also stay out of the Site Editor’s template list: four entries called “Header”, one per language, would make it harder to use, not easier.
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:
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 should 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.
- Published but empty
The original renders. WordPress would accept an empty translation and show a blank space, so a translation with nothing in it yet counts as no translation.
- Trashed or wrong type
The original renders.
That is a deliberate guarantee, not a side effect of how it happens to be written.
Block-theme navigation menus
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 reaches them on its own. PerfLocale lists them on the Strings screen as Site Title and Tagline, and you translate them there 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
Theme templates that draw their text from the theme’s own translatable strings are already covered by String Translation — there is no post to translate, and their text is already resolved in the visitor’s language. The Full Site Editing setting is for templates you have customised in the Site Editor, which WordPress stores in your database. If you have never opened the Site Editor, there is probably nothing here for you to translate.
It also does not translate the content inside a template that already has a translation route of its own. A synced pattern referenced from a template, a navigation menu, a post — those are handled by the mechanisms above, and they work whether or not the Full Site Editing setting is on.