Translate pages, areas, menus, forms and posts field by field instead of rebuilding them
A site can have further languages (Settings → Languages). A page is built once; each language adds only its texts, keyed by the stable block IDs, plus its own address under /en/… (ADR 111, document schema v27, migration 20261009000100 for page_translation). - Editor: DE | EN switch, a list of all texts with original, state (missing, translated, original changed) and filter; structure stays with the main language. Undo, drafts, publishing and revisions cover all languages at once. - Website: /en and translated slugs, lang, canonical, hreflang with x-default, og:locale, sitemap; links to translated pages follow the language; a language switch block. - Header, footer and linked sections translate the same way; menu entries carry labels per language; fixed template texts come from a small dictionary. - Forms: labels, help, options, button and success message per language; messages and the step script speak the language, the submission and the email stay in the main language. - Posts, archives, category names, consent text and the 404 page follow the language. - Single-language sites see none of it and never touch the new table. The forms administration becomes an overview with one row per form and its own edit page; fields are one line each with details collapsed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c7705b7083
commit
e15b2517b1
51 files changed
+3045
-219
No files matched your search
@@ -681,8 +681,12 @@ final class EditorSecurityTest extends WebTestCase
|
||||
preg_match('#<style>(.*?)</style>#s', $html, $style);
|
||||
self::assertStringContainsString("'sha256-".base64_encode(hash('sha256', $style[1], true))."'", (string) $client->getResponse()->headers->get('Content-Security-Policy'));
|
||||
|
||||
// Eine Farbe, die keine ist, wird mit Meldung abgelehnt und nichts geaendert.
|
||||
// Die Übersicht listet das Formular, bearbeitet wird es auf seiner eigenen Seite.
|
||||
$crawler = $client->request('GET', '/admin/forms');
|
||||
self::assertSame(0, $crawler->filter('.form-def')->count(), 'Die Übersicht zeigt keine Editoren.');
|
||||
self::assertSame('/admin/forms/kontakt', $crawler->filter('.form-list a')->first()->attr('href'));
|
||||
// Eine Farbe, die keine ist, wird mit Meldung abgelehnt und nichts geaendert.
|
||||
$crawler = $client->request('GET', '/admin/forms/kontakt');
|
||||
$token = $crawler->filter('.form-def input[name="_csrf_token"]')->first()->attr('value');
|
||||
self::assertCount(5, $crawler->filter('.form-def')->first()->filter('.field-card:not(.field-card-new)'), 'Jedes Feld ist eine Karte.');
|
||||
self::assertSame('Anfrage senden', $crawler->filter('.form-def')->first()->filter('[data-preview-button]')->text());
|
||||
@@ -696,7 +700,7 @@ final class EditorSecurityTest extends WebTestCase
|
||||
public function testFormAdministrationNeedsAPublisherRoleAndACsrfToken(): void
|
||||
{
|
||||
$client = $this->login('publisher');
|
||||
$crawler = $client->request('GET', '/admin/forms');
|
||||
$crawler = $client->request('GET', '/admin/forms/neu');
|
||||
self::assertResponseIsSuccessful();
|
||||
$token = $crawler->filter('.form-def input[name="_csrf_token"]')->first()->attr('value');
|
||||
$field = ['fields' => [['name' => 'email', 'type' => 'email', 'label' => 'E-Mail', 'required' => '1']]];
|
||||
|
||||
Reference in new issue
Block a user