• Mahmoud Aglan's avatar
    feat(website): make the builder able to reproduce a real bilingual site · 21792905
    Mahmoud Aglan authored
    Building an existing client site inside the builder surfaced the gaps between
    "the blocks exist" and "the blocks can express a finished design". Each of these
    was found by rendering the target and comparing it, not by reading the code.
    
    Blueprint export/import (v2) now carries the whole design, not a third of it.
    It exported pages only — so importing a design gave you the content with a
    default theme and no navigation, which looks nothing like its source. It now
    carries theme settings and menus too. Menu items record their page by SLUG,
    because a page id means nothing in another tenant's database and would import a
    navigation pointing at whatever happened to hold that id. Tracking identifiers
    are deliberately excluded from the whitelist: importing a design must never
    start reporting one client's traffic into another's account. v1 files still
    import.
    
    Isolation that did not isolate. BlockRenderer catches a failing block so the
    rest of the site survives, but Laravel's View::render() calls flushState() when
    any view throws, which clears the section stack of the page *around* it.
    Rendered inside the layout's @section, one bad block therefore killed the whole
    page at @endsection with an unrelated "Cannot end a section" error — the exact
    opposite of the intent. Blocks are now rendered before the layout runs, where
    there is no open section to corrupt.
    
    Bilingual content reached templates raw. Translatable repeater sub-fields
    (a button label, a card title, a partner name) are stored as ['ar'=>…,'en'=>…]
    and read straight out of the data array, so they arrived at {{ }} as arrays and
    took the block down with "htmlspecialchars(): array given". website_text()
    resolves them, and 49 such reads across 15 block views now use it.
    
    The English site rendered right-to-left. website.css hardcoded
    `direction: rtl` on .website-body, silently overriding the dir attribute the
    layout computes from the locale. Direction now follows the document.
    
    There was no English at all. No lang/ directory existed, so every __() returned
    its Arabic key and English visitors read Arabic form labels, buttons and
    helper text. lang/en.json covers all 125 public-site strings.
    
    Smaller gaps, each of which made a real design impossible to express:
    - 'glass' was a valid navbar template and a forbidden column value; the CHECK
      constraint predated it, so choosing it failed at write time.
    - navbar_cta_text had no English twin, so a bilingual site showed one language's
      button to both audiences.
    - An empty navbar CTA fell back to the default label, so the button could not
      be turned off.
    - An anchor menu item resolved to a bare "#id", which points at nothing from a
      sub-page; it now addresses the homepage in the reader's language.
    - A footer column title was a plain string, so it could not be bilingual; the
      'about' column dropped the social row whenever columns were configured.
    - product_showcase stacked its showcase under a centred headline instead of
      laying out as the split it is.
    - A map field stores coords as ['lat'=>…,'lng'=>…] and the view passed the array
      to urlencode(), killing the block.
    - New: 'stacked' info cards, a footer spacer, heading rules and eyebrows on the
      contact block, and a nowrap on highlighted heading fragments so
      "Welcome to {OC-Sport}" cannot break mid-phrase.
    
    Verified against a local Postgres replica carrying a real 11-page bilingual
    site: 22 page/locale combinations answer 200 with zero logged block failures,
    all 137 block/variant combinations render, reserved and unknown paths still 404,
    the four migrations apply and roll back on both an existing tenant and a
    from-scratch install + seed, and the suite passes (140 tests, 483 assertions).
    Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    21792905
Name
Last commit
Last update
..
blocks Loading commit data...
builder Loading commit data...
events Loading commit data...
footers Loading commit data...
icons Loading commit data...
navbars Loading commit data...
partials Loading commit data...
sections Loading commit data...
footer.blade.php Loading commit data...
index.blade.php Loading commit data...
layout.blade.php Loading commit data...
navbar.blade.php Loading commit data...
news-index.blade.php Loading commit data...
news-show.blade.php Loading commit data...
page.blade.php Loading commit data...