Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - coryhubbell/Development-Translation-Bridge: Universal WordPress page builder translation system across 14 frameworks · GitHub
Skip to content

Latest commit

History

178 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

DevelopmentTranslation Bridge

Move a WordPress site from one page builder to another — without rebuilding it by hand. Translation Bridge converts content between 14 frameworks — Elementor, DIVI, Gutenberg, Bricks, Oxygen, Avada, WPBakery, Beaver Builder, Kadence, Thrive, Bootstrap, plus native support for the ground-up rewrites (DIVI 5, Elementor 4 Atomic Editor, Oxygen 6).

CIVersionStatusPHPPythonLicenseFrameworksTranslation pairs

Quick start · CLI reference · Python API · REST API · Architecture · Latest release notes

Visual Interface translating a Bootstrap hero section into Gutenberg blocks, with live preview

The bundled Visual Interface (WordPress Admin → Visual Interface): Monaco-powered side-by-side editing, framework selectors, live preview, and one-click translate/check/AI actions.


⚡ 30-second start

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge && pip install -e .
./devtb transform elementor gutenberg your-page.json

That's it — your-page-gutenberg.html appears next to your input, with a per-conversion fidelity report like ✓ Fidelity: 60/60 content strings preserved (100.0%). Convert to every framework at once with ./devtb transform-all elementor your-page.json. Full setup (WordPress theme, REST API, admin UI): see Quick start.


What it does

Translation Bridge takes content in any supported page builder's native format (Elementor JSON, DIVI shortcodes, Gutenberg blocks, etc.) and re-emits it in another framework's format. It runs as either a WordPress plugin (with a REST API), a standalone CLI, or a Python library.

Typical situations it solves:

  • Builder migration. A site built on Elementor needs to become Gutenberg-native (or Bricks, or anything else) — convert the pages instead of rebuilding them.
  • Version rewrites. DIVI 4 → DIVI 5, Elementor 3 → Elementor 4 Atomic, Oxygen 4 → Oxygen 6: the successor formats are supported natively, so legacy content can be modernized in place.
  • Clean HTML output. Emit framework-free Bootstrap 5 HTML from any builder — useful for handoffs, static exports, and AI/agentic content pipelines.
  • No silent data loss. Elements without a native equivalent in the target framework are preserved and visibly annotated rather than dropped.

One schema, two conforming runtimes. Every conversion rides the same lossless pipeline — parse → universal document → convert — whether it runs in the Python engine or the PHP (WordPress) runtime. The legacy mapping engine is gone as of 5.0:

flowchart TD
IN(["Your content<br/>(any of the 14 frameworks)"]) --> P["parse → <b>universal document</b> → convert"]
P --> OUT(["Any of the 14 target frameworks"])
P -.->|"per conversion"| F["fidelity metrics"]
Loading
CommandEngineStatusNotes
transformPythonRecommendedJSON-native, 100% metadata, ~0.5s/page
transform-allPythonSupportedOne source → every other framework, per-target fidelity table

Supported frameworks

14 frameworks → 182 translation pairs (N × (N-1)).

Framework keyCMS version targetedFormatNotes
bootstrapBootstrap 5.3.xHTMLUniversal output, AI-friendly
elementorElementor 3.30.0JSONSection → Column → Widget
elementor-4Elementor 4.0.0JSONAtomic Editor (e-div-block, e-flexbox, e-heading...)
diviDIVI 4.27.0Shortcodes[et_pb_*]
divi-5DIVI 5.0.0Block markup<!-- wp:divi/* -->
oxygenOxygen 4.8.3JSONLegacy ct_* schema
oxygen-6Oxygen 6.0.0JSON treeBreakdance-derived EssentialElements\* namespace
gutenbergWordPress 6.9.0Block markupCanonical core blocks
bricksBricks 2.3.5JSONFlat element registry with parent ids
kadenceKadence Blocks 3.7.2Block markupkadence/* blocks + core/* fallthrough
thriveThrive Architect 10.8.10TCB HTMLdata-css tokens + tve_custom_style
wpbakeryWPBakery 8.7.3Shortcodes[vc_*]
beaver-builderBeaver Builder 2.10.2JSON
avadaAvada 7.15.3Shortcodes[fusion_*]

Schema verification status

The oxygen-6, divi-5, and elementor-4 paths shipped in v4.3.0 as documentation-based proxies; they have since been verified and corrected against real evidence:

  • elementor-4 — verified against the open-source elementor/elementor repository (modules/atomic-widgets): settings now use the real typed-prop system ($$type envelopes, html-v3 content, link.destination, Style_Definition variants) and only real atomic element types are emitted.
  • divi-5 — verified against the Divi 5 block-format docs: content lives in the top-level content attribute group with unicode-escaped HTML and the responsive desktop.value wrapper.
  • oxygen-6 — node shape verified against a real Breakdance element export (committed at tests/fixtures/oxygen6/): integer ids, data-nested type/properties, _parentId back-references, and content.content field grouping. Oxygen 6 shares ~80% of Breakdance's codebase; if Oxygen 6 ships its own element namespace, the parser's namespace-agnostic lookup already handles it and the emitter's prefix is a single constant.

tests/Unit/ProxySchemaVerificationTest.php pins all of the above, including parsing the real export end-to-end.


Quick start

Requirements

  • PHP 8.1+ (for the WordPress runtime, theme install, and REST API)
  • Python 3.9+ (for the transform path and CLI); local verification is pinned to 3.11 via .python-version
  • Node 20.19.0, 22.13.0+, or 24+ + npm (only to rebuild the React admin UI from source)
  • Composer 2.0+ and pip (only if installing from source)

Install

git clone https://github.com/coryhubbell/Development-Translation-Bridge.git
cd Development-Translation-Bridge
# PHP dependencies
make composer-install
# Python package
pip install -e .# Build the React admin UI (required for the Visual Interface in production).# admin/dist/ is gitignored, so this step is needed after every clone or pull# that touches admin/. In WP_DEBUG mode the Vite dev server is used instead;# see admin/README.md for the dev workflow.cd admin
npm ci
npm run build
cd ..
# Make the CLI executable
chmod +x devtb

Release assets named development-translation-bridge-*.zip are packaged for WordPress theme installation. They are built reproducibly by scripts/build-release-package.sh, and pushing a v* tag publishes the release automatically (zip + generated changelog) via the release workflow. Clone the repository when you need the standalone CLI, Python package, tests, or development tooling.

To run the full local release gate before opening or updating a PR:

make verify

Choosing a command

You want to…Run
Convert one file to one framework./devtb transform <source> <target> <file>
Convert one file to all 13 other frameworks./devtb transform-all <source> <file>
Convert a whole directory or site export./devtb transform-site <source> <target> <dir>
Inspect content without converting./devtb analyze <framework> <file>
List the 14 framework keys./devtb list-frameworks
Check a file parses as a framework./devtb validate <framework> <file>

Every conversion prints a fidelity line (content strings preserved). If a target has no native slot for something, it is preserved and visibly annotated — never silently dropped.

Translate a file

# JSON-native transform (recommended for JSON-based frameworks)
./devtb transform elementor bootstrap input.json -o output.html
# fan out to every framework at once (per-target fidelity table)
./devtb transform-all divi input.html
# Transform an entire site export
./devtb transform-site elementor bootstrap ./export-kit/
# Analyze content without converting
./devtb analyze elementor input.json

From Python

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementor4importElementor4Converter# Parse Elementor JSON, emit Bootstrap HTMLelementor_data= [...] # parsed JSONhtml=BootstrapConverter().convert(elementor_data)
# Build Atomic Editor JSON from any parsed universal dataatomic_json=Elementor4Converter().convert(elementor_data)

As a WordPress plugin

# Activate by copying or symlinking into wp-content/themes/
ln -s "$PWD" /path/to/wp-content/themes/development-translation-bridge
# Then activate "DevelopmentTranslation Bridge" in WordPress Admin → Themes.

The REST API mounts at /wp-json/devtb/v2/* after activation (see REST API below).


CLI

The devtb CLI is a bash wrapper that routes commands to the Python engine (conversions) or the PHP engine (WordPress runtime utilities).

COMMANDS (Python engine — JSON-native, lossless):
transform <source> <target> <file> Transform a file (100% metadata preserved)
transform-all <source> <file> Transform to every other framework
transform-site <source> <target> <dir> Transform every file in a directory
analyze <framework> <file> Inspect parsed content without converting
COMMANDS (PHP engine utilities):
list-frameworks List supported frameworks
validate <framework> <file> Validate file format
OPTIONS:
-h, --help Show this help message
-v, --version Show version information
-n, --dry-run Preview without writing files
-d, --debug Show debug information
-o, --output <file> Specify output file path

Run ./devtb --help for the current up-to-date command list.

Common workflows

# Migrate Elementor → Bricks
./devtb transform elementor bricks page.json -o page-bricks.json
# Modernize legacy DIVI 4 → DIVI 5 block markup
./devtb transform divi divi-5 page.txt -o page-divi5.html
# Detect format, then route to the right path
./devtb analyze elementor mystery.json # tells you elType, version, etc.# Generate every framework's version from one input (fidelity table included)
./devtb transform-all bootstrap landing.html

Python API

Direct module imports for programmatic use:

fromtranslation_bridge.converters.bootstrapimportBootstrapConverterfromtranslation_bridge.converters.elementorimportElementorConverterfromtranslation_bridge.converters.elementor4importElementor4Converterfromtranslation_bridge.converters.diviimportDiviConverterfromtranslation_bridge.converters.divi5importDivi5Converterfromtranslation_bridge.converters.gutenbergimportGutenbergConverterfromtranslation_bridge.converters.bricksimportBricksConverterfromtranslation_bridge.converters.oxygenimportOxygenConverterfromtranslation_bridge.converters.oxygen6importOxygen6Converterfromtranslation_bridge.converters.wpbakeryimportWPBakeryConverterfromtranslation_bridge.converters.beaverimportBeaverConverterfromtranslation_bridge.converters.avadaimportAvadaConverterfromtranslation_bridge.converters.kadenceimportKadenceConverterfromtranslation_bridge.converters.thriveimportThriveConverter# Each converter has the same surface:converter=BricksConverter()
output_json=converter.convert(parsed_data) # serializedoutput_list=converter.convert_to_dict(parsed_data) # python objectsframework_name=converter.get_framework() # "bricks"

Site-level conversions:

fromtranslation_bridge.parsers.elementor_siteimportElementorSiteParserfromtranslation_bridge.converters.stylesimportStylesConverterfromtranslation_bridge.converters.templatesimportTemplateConvertersite=ElementorSiteParser().parse_kit("./export-kit/")
tokens=StylesConverter().extract_tokens(site.settings)
template_parts=TemplateConverter().build(site.templates)

REST API

After activating the WordPress theme/plugin, endpoints mount at /wp-json/devtb/v2/*.

Endpoints

MethodPathPurpose
GET/statusHealth check + version info
GET/frameworksList supported frameworks
POST/translateTranslate a single payload
POST/batch-translateQueue a batch translation job
GET/job/{job_id}Poll a batch job's status
POST/validateValidate a payload for a framework
POST/savePersist a translation result
GET, PUT, DELETE/translations/{id}CRUD on saved translations
GET/translations/historyList recent translations
GET/translations/{id}/versionsVersion history for a translation
GET, POST/api-keysList or create API keys
DELETE/api-keys/{key}Revoke an API key

Authentication

API keys are encrypted at rest (AES-256-CBC) and required for every endpoint except /status and /frameworks. Pass via header:

Authorization: Bearer <api-key>

Generate keys via the WordPress admin UI or POST /wp-json/devtb/v2/api-keys.

Quick examples

# Health check
curl https://example.com/wp-json/devtb/v2/status
# List frameworks
curl https://example.com/wp-json/devtb/v2/frameworks
# Translate
curl -X POST https://example.com/wp-json/devtb/v2/translate \
-H "Authorization: Bearer $DEVTB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"elementor","target":"bootstrap","content":"..."}'

Full endpoint reference: docs/api-v2.md.


Architecture

Every framework plugs into the same hub-and-spoke pipeline: parse into a universal component tree, map, then convert out. Adding one framework adds 13 × 2 new translation pairs — no per-pair code.

flowchart LR
A["Source content<br/>(Elementor JSON,<br/>DIVI shortcodes, ...)"] --> B["Parser<br/>(one per framework)"]
B --> C["Universal<br/>Component[]<br/>(typed tree)"]
C --> D["Mapping engine<br/>(styles, tokens,<br/>element maps)"]
D --> E["Converter<br/>(one per framework)"]
E --> F["Target content<br/>(any of 14<br/>frameworks)"]
Loading

Each framework provides a paired parser (input → universal components) and converter (universal components → output). Parsers and converters register independently with DEVTB_Parser_Factory and DEVTB_Converter_Factory, so a framework can be a source, a target, or both.

Project layout

translation-bridge/
├── core/
│ ├── interface-parser.php
│ ├── interface-converter.php
│ ├── class-parser-factory.php
│ ├── class-converter-factory.php
│ ├── class-mapping-engine.php
│ └── class-translator.php
├── parsers/ # one per framework (PHP)
├── converters/ # one per framework (PHP)
├── models/ # DEVTB_Component
└── utils/ # CSS, JSON, HTML, shortcode helpers
src/translation_bridge/
├── parsers/ # Python parsers
├── converters/ # Python converters
├── transforms/ # Zone Theory engine (v4)
└── cli.py # Python CLI entry point
includes/
├── class-devtb-api-v2.php # REST API
├── class-devtb-auth.php # API key + permission checks
├── class-devtb-encryption.php # AES-256-CBC for keys at rest
├── class-devtb-rate-limiter.php
├── class-devtb-job-queue.php # async batch translations
└── class-devtb-webhook.php

Detailed architecture notes live in docs/TRANSLATION_BRIDGE.md.


Testing

PHP (via PHPUnit):

make test-php # full suite
vendor/bin/phpunit --filter FrameworkConversionsTest # 182-pair matrix

Python (via pytest):

python3 -m pytest tests/python -q

Full local release gate:

make verify

As of v5.1.0:

  • PHP: 344 tests / 5,691 assertions / 0 errors / 0 failures / 0 deprecations, including 18 widget-coverage tests (tests/Unit/GutenbergWidgetCoverageTest.php), 9 real-format schema-verification tests (tests/Unit/ProxySchemaVerificationTest.php), 8 responsive round-trip tests (tests/Unit/ResponsiveRoundTripTest.php), and 9 classic-Oxygen hardening tests (tests/Unit/OxygenClassicHardeningTest.php).
  • Python: 307 tests across converters, parsers (all 14 frameworks parse natively), transforms, responsive helpers, the bidirectional interchange, the translate-path deprecation surfaces, the 39-cell cross-source fidelity matrix, dual-engine conformance (including the exact-mirror gate), and project alignment checks.
  • End-to-end fidelity smoke gates (make e2e-smoke), each running through both engines as CI gates on every push and PR: Elementor → Gutenberg (tests/smoke_gutenberg_e2e.py), Elementor → Bricks (tests/smoke_bricks_e2e.py, flat-format + content survival), and DIVI → Gutenberg (tests/smoke_divi_e2e.py, content survival + block integrity).

The 41 pre-existing errors and 3 failures that v4.1 / v4.2 / v4.3.0 inherited (class-autoload mismatches and missing WP-function mocks) were all resolved in v4.3.1 via the shared autoloader + WP function stubs. The full suite is now green, including composer audit.

Continuous integration

Every push and PR to main / develop runs four jobs (.github/workflows/ci.yml):

JobWhat it runs
PHP testsPHPUnit across PHP 8.1 – 8.5, plus composer validate, syntax check, composer audit, PHPCS (WordPress standards), and Codecov coverage upload
Python tests + Gutenberg e2e smokeFull pytest suite, then three e2e fidelity gates through both engines: Elementor → Gutenberg, Elementor → Bricks, and DIVI → Gutenberg kitchen-sink fixtures
Admin buildESLint, tsc --noEmit, and a production Vite build on Node 20.19.0 / 22.13.0 / 24
Release package smokeBuilds and inspects the WordPress theme zip via scripts/build-release-package.sh, so packaging breakage is caught before tagging

Dependency freshness is automated with Dependabot: weekly update PRs for Composer, npm (admin/), and pip, and monthly for GitHub Actions and Docker Compose images. composer audit gates every CI run, and make verify additionally runs npm audit --omit=dev on the admin UI.


Docker (development)

A local stack is available for plugin development:

docker-compose up -d
# WordPress: http://localhost:8080# phpMyAdmin: http://localhost:8081

The stack pins WordPress 7.0 (PHP 8.4 + Apache), MySQL 9.7, and phpMyAdmin 5.2 — image versions are kept fresh by Dependabot's monthly docker-compose updates. Ports and database credentials are overridable via environment variables (WORDPRESS_PORT, MYSQL_PORT, MYSQL_USER, ...); see docker-compose.yml for the full list and DOCKER_SETUP.md for a walkthrough.

The plugin is mounted from the working tree, so edits are reflected immediately.


Documentation

Topical guides under docs/:

FileTopic
getting-started.mdFirst-run setup walkthrough
api-v2.mdFull REST API reference
api-development.mdBuilding against the API
TRANSLATION_BRIDGE.mdArchitecture deep-dive
FRAMEWORK_MAPPINGS.mdPer-framework element maps
CONVERSION_EXAMPLES.mdReal translation examples
bootstrap-components.mdBootstrap output reference
claude-integration.mdAI-assisted editing workflows
PLUGIN_CONVERSION.mdPlugin migration cookbook

A consolidated version history lives in CHANGELOG.md; detailed notes for major releases live at RELEASE_NOTES_V*.md and in GitHub Releases.


Current release: v5.1.0 (production-ready)

v5.1.0 closes the deprecation window and ships transform-all. One command now fans a page out to every other framework with a per-target fidelity table; the legacy translate/translate-all commands are removed on schedule. Full notes: v5.1.0 release and RELEASE_NOTES_V5.1.0.md.

What 5.1.0 added

  • devtb transform-all <source> <file> — one source → all 13 other frameworks through the universal route, per-target fidelity table.
  • Removed: the translate/translate-all CLI commands (deprecated since 4.14.0). The WordPress runtime engine is unaffected.
  • Fixed:list-frameworks/validate are supported utilities, not deprecated; help corrected.

What 5.0.0 changed (RFC 5.0 complete)

  • Removed (breaking): the v3 mapping engine and its fallback branch; the DEVTB_Component shape as a public interchange format.
  • Unchanged: every CLI command, REST endpoint, and API signature.
  • Migration: direct DEVTB_Mapping_Engine users move to parse_to_universal() / translate_universal(); stats route is always universal.
Release history highlights (v4.3.0 → v4.15.0)

What 4.15.0 added (pre-5.0 converter hardening)

  • Cross-source fidelity matrix: 3 real fixtures × 14 targets, ≥90% content survival per pair, gating in CI.
  • All 14 converters hardened: structural recursion for nested container shapes, canonical widget vocabulary, content-preserving fallbacks — no empty elements for unmapped widgets.
  • Bidirectional interchange:element_to_component / document_to_components mirror DEVTB_Universal's reverse direction.
  • Honest metrics: style keys excluded from content; JSON outputs compared via decoded string scalars.

What 4.14.0 added (RFC 5.0 Phase 3 complete)

  • The universal route everywhere:DEVTB_Translator::translate() normalizes through the canonical universal document instead of the v3 fuzzy mapping engine — all 182 pairs green.
  • Fidelity metrics per conversion: route + content-string survival in translator stats and both CLIs.
  • translate deprecated: notices on every surface; Python CLI accepts it as an alias of transform; unregistered Python pairs convert through the universal route behind a runtime fidelity gate.
  • Fixed:devtb-php silent-exit bug (missing DEVTB_CLI constant) that killed CLI conversions touching the responsive helper.

What 4.13.0 added (RFC 5.0 Phase 2 complete)

  • Shared interchange module:src/translation_bridge/interchange.py — component-shaped dicts translate to canonical universal elements with PHP-identical semantics; the Gutenberg converter's ad-hoc adapter is replaced by delegation to it.
  • Exact-mirror conformance gate:component_to_element(to_array()) == to_universal() for every component of all three real fixtures, on every CI run.
  • Round-trip vocabulary completed in both engines:icon_list, wp_gallery, selected_icon, alert_*, and CTA links survive universal ⇄ component conversion.
  • Better legacy output:row/column components become real core/columns blocks; the schema-canonical nav widgetType is accepted.

What 4.12.0 added (RFC 5.0 Phases 1–2)

  • The spec:schema/universal-element.schema.json + docs/RFC-5.0-engine-consolidation.md.
  • Conformance in CI: three real fixtures parsed by both engines must produce schema-valid, content-equivalent documents.
  • Universal interchange in PHP:DEVTB_Universal, parse_to_universal() / translate_universal(), and universal as a REST source/target.
  • Cross-engine proof: Python-parsed → PHP-converted and PHP-parsed → Python-converted, both content-preserving. Purely additive.

What 4.11.0 added (Python parsers final tranche)

  • Seven new parsers: DIVI 4, WPBakery, and Avada (shared shortcode tokenizer with self-closing-leaf handling); Kadence (extends the Gutenberg parser); Beaver Builder (flat node registry); Thrive and Bootstrap (shared HTML walker).
  • 13 new transform pairs and CLI resolution; verified against the committed DIVI kitchen-sink fixture and the repo's real Bootstrap hero example. Purely additive.

What 4.10.0 added (Python parsers tranche 2)

  • Oxygen6Parser — the Breakdance-verified node shape, all envelope variants, design breakpoints canonicalizing; parses the committed real export fixture end to end.
  • Divi5Parserwp:divi/* markup per the verified format, with tablet/phone/hover wrappers canonicalizing.
  • GutenbergParser — core block markup as a lossless source; unknown blocks preserved verbatim.
  • Shared block tokenizer, parse-direction responsive helpers, seven new transform pairs, CLI aliases. Purely additive.

What 4.9.0 added (responsive canonicalization completion)

  • Elementor v3:_tablet/_mobile/_hover setting suffixes canonicalize on parse and re-emit on convert, in both engines.
  • Bricks::tablet_portrait/:mobile_portrait setting-key suffixes canonicalize and re-emit in both engines; mobile_landscape passes through verbatim.
  • Cross-framework transfer in every direction — e.g. Elementor tablet overrides become Bricks :tablet_portrait keys, and either can land in DIVI 5 wrappers, Elementor 4 variants, or Oxygen media bags. Purely additive: non-responsive content converts byte-identically.

What 4.8.0 added (e2e fidelity smoke gates)

  • Two new gates: Elementor → Bricks (flat-format integrity + content survival) and DIVI → Gutenberg (new 17-module DIVI kitchen-sink fixture; content survival + block integrity, both Gutenberg converters).
  • Seven content drops fixed: Bricks converters (Python widget branches, PHP gallery arrays) and Gutenberg converters (container recursion, universal attribute vocabulary, button labels, toggle panels, testimonial citations).
  • make e2e-smoke runs all three gates locally; make verify and CI include them.

What 4.7.0 added (JSON source parsers)

  • Three new source parsers on the lossless Python engine, built on schemas verified in earlier releases: BricksParser (real 2.x flat page format), OxygenParser (all four classic storage shapes, with unit normalization and responsive media canonicalization), and Elementor4Parser (typed-prop unwrapping + style-variant canonicalization).
  • CLI wiring:devtb transform bricks|oxygen|elementor4 <target> file.json works end to end; five new transform pairs registered (each source → gutenberg / bootstrap).
  • Shared UniversalDocument primitives so the next source parser is a much smaller diff.
  • Purely additive — no existing transform or converter behavior changed.

What 4.6.0 added (classic Oxygen hardening)

  • All four real storage shapes parse — the nested ct_builder_json root tree, the ct_builder_json wrapper, the flat ct_parent list, and ct_builder_shortcodes strings. (Previously only the flat list parsed — the committed fixture itself was unreadable.)
  • Real element vocabularyct_link, ct_new_columns/ct_column, oxy_rich_text, oxy_testimonial_box, oxy_map, oxy_nav_menu, and the rest of the genuine ct_*/oxy_* set; nine fabricated names earlier releases emitted still parse as aliases but are never emitted again.
  • One output shape across engines — PHP and Python now emit the identical real root-tree format with correct ct_id/ct_parent linkage (previously three mutually incompatible shapes).
  • Style + responsive fidelity — full options.original passthrough (the old allow-list silently dropped gap, border shorthand, and more), unit normalization both ways (Oxygen unitless ↔ CSS px), and options.media breakpoint overrides round-tripping via the canonical responsive model.
  • Deterministic outputtime()-based selectors removed; conversions are byte-reproducible.

What 4.5.0 added (responsive breakpoint round-tripping)

  • Canonical responsive model — breakpoints desktop/tablet/phone, states default/hover — carried in component metadata, implemented on both engines (DEVTB_Responsive_Helper in PHP, translation_bridge.responsive in Python).
  • DIVI 5: per-breakpoint content values and hover states parse into canonical form and re-emit as full multi-breakpoint wrappers.
  • Elementor 4: style-definition variants canonicalize per breakpoint/state (mobilephone) and re-emit as one variant each.
  • Oxygen 6: design-tree breakpoint_* leaves flatten to canonical props and re-nest on emit — design data now round-trips at all.
  • Cross-framework transfer: responsive styling moves between frameworks (e.g. Oxygen 6 design breakpoints → Elementor 4 variants), tested in both directions. Purely additive — elements without responsive data emit byte-identical output to v4.4.0.

What 4.4.0 added (real-format schema verification)

The three next-generation framework paths shipped in v4.3.0 as documentation-based proxies; v4.4.0 corrects each against real evidence:

  • Elementor 4 — verified against the open-source elementor repo (modules/atomic-widgets). Settings now use the real typed-prop system: every value wrapped in a {"$$type": ..., "value": ...} envelope, html-v3 content props, the paragraph settings key, link.destination/isTargetBlank, the nested image.src shape, and Style_Definition variants referenced via the classes prop. Emissions use only real atomic element types — e-svg, e-youtube, e-self-hosted-video, e-divider replace the invented e-icon/e-video/e-list.
  • DIVI 5 — verified against the Divi 5 block-format docs. Content moved to the top-level content attribute group (was module.content), and block attrs now unicode-escape HTML exactly like WP core's serialize_block_attributes(), so content can never break the block-comment delimiters. The responsive desktop.value wrapper was confirmed correct as shipped.
  • Oxygen 6 — verified against a real Breakdance export (committed, scrubbed, at tests/fixtures/oxygen6/). Nodes carry integer ids with the element payload nested under data, _parentId back-references, a tree.root envelope, content.content field grouping, the plural tags heading key, and real element names (CodeBlock, TextLink, PricingTable, ProgressBar).
  • Back-compat preserved: parsers accept both the real shapes and the old proxy shapes, so v4.3.x output still translates. Nine new schema-verification tests pin the real formats — including parsing the real export end-to-end.
  • Release engineering: Dependabot across five ecosystems, reproducible zip packaging (scripts/build-release-package.sh + tag-triggered releases), the four-job CI pipeline, and make verify.

What 4.3.4 added (Elementor → Gutenberg widget coverage)

  • Widget coverage on both engines. ~70 of the 90+ universal widget types the Elementor parser produces were previously silently collapsing onto core/paragraph with empty content. Compound widgets (tabs, accordion, card, cta, counter, testimonial, pricing-table, alert) now expand into native block groups with a devtb-<type>-converted className. Widgets with no native Gutenberg equivalent (form, slider, countdown, portfolio, toc, map, progress, rating, unknown widgets) are preserved as core/html with a visible data-devtb-source annotation — no silent data loss.
  • Type-map expansion for 1:1 mappings the parser produced but the converter was missing (social-icons, nav, blockquote, icon).
  • Settings denormalization (typography, color, spacing, border, className, anchor) restored on the Python side — these were silently dropped before.
  • Four new transforms registered:elementor_to_gutenberg, html_to_gutenberg, divi_to_gutenberg, bricks_to_gutenberg.
  • CI gate: kitchen-sink fixture (30 widget types, every dispatch class) now runs through both engines on every push and PR via the new Python tests + Gutenberg e2e smoke job. The smoke caught two real fidelity bugs (counter title, blockquote author) that the targeted unit tests didn't reach — both fixed before tagging.

Full notes: v4.3.4 release and RELEASE_NOTES_V4.3.4.md.

What 4.3.0 added (framework coverage milestone)

  • 3 new frameworks:divi-5, elementor-4, oxygen-6 — native parser + converter pairs for the block-based / atomic rewrites.
  • Bricks correctness fix: PHP converter now emits the flat 2.x page format (string parent ids, child id arrays) matching real Bricks output. Previous nested-children output was wrong against every Bricks version.
  • Automatic routing: legacy DIVI and Elementor parsers detect their successor format and route to the new parser instead of attempting an incompatible parse.
  • Framework matrix: 11 → 14 frameworks, 110 → 182 translation pairs.

What 4.3.1 → 4.3.3 added (production-readiness chain)

  • CLI translation fatal fixed (v4.3.1): the inline autoloader mangled namespaced class names — replaced with a shared autoloader used by CLI, PHPUnit, and (defense-in-depth) WordPress.
  • Matrix consistency across all surfaces (v4.3.1): REST API, CLI, file-handler, config class, admin TypeScript, Monaco language map — all now derive from DEVTB_Converter_Factory::get_framework_info(). Stale claude pseudo-framework purged from every consumer.
  • Test suite green (v4.3.1): 41 errors + 3 failures → 0 / 0 (284 tests, 4,133 assertions). PHP 8.5 deprecation count → 0.
  • PHP 8.1+ floor declared (v4.3.1): matches the tested runtime; PHP 7.4 EOL'd 2022-11.
  • Security (v4.3.1): CVE-2026-24765 (unsafe deserialization in PHPT coverage) cleared by phpunit bump to 9.6.34.
  • User-facing copy synced to 14 / 182 (v4.3.2): style.css framework list, ASCII banner, admin help text, CLI help text.
  • functions.php admin pages factory-driven (v4.3.3): five hardcoded 9-framework call sites (admin home, Frameworks matrix table, Settings select, System Status rows, Framework Details card) now consume the factory directly. Adding a 15th framework later only requires updating the factory.

v4.3.1 → v4.3.3 notes: v4.3.3 release — see also CODEX_REVIEW.md for file-by-file rationale.


Version history

VersionDateHighlights
v5.1.0(latest)2026-07-04transform-all fan-out with per-target fidelity; translate/translate-all removed on schedule
v5.0.02026-07-04RFC 5.0 complete — one schema, two conforming runtimes; v3 mapping engine removed (breaking); migration guide in release notes
v4.15.02026-07-04Pre-5.0 converter hardening: Python cross-source parity, 39-cell fidelity matrix in CI, bidirectional interchange
v4.14.02026-07-04RFC 5.0 Phase 3 complete: universal route everywhere, fidelity metrics per conversion, translate deprecated, silent-exit CLI fix
v4.13.02026-07-03RFC 5.0 Phase 2 complete: shared component interchange in Python, exact-mirror conformance gate, round-trip vocabulary completed in both engines
v4.12.02026-07-03RFC 5.0 Phases 1–2: canonical schema, dual-engine conformance in CI, universal interchange in the PHP engine + REST
v4.11.02026-07-03Python parsers final tranche: all 14 frameworks parse natively — the 4.7+ roadmap is complete
v4.10.02026-07-03Python parsers tranche 2: Oxygen 6, DIVI 5, and Gutenberg sources — all JSON/block-markup formats parse natively in Python
v4.9.02026-07-03Responsive canonicalization completed: Elementor v3 suffixes + Bricks breakpoint keys join the canonical model; cross-framework transfer in every direction
v4.8.02026-07-03E2e fidelity smoke gates for Elementor → Bricks and DIVI → Gutenberg; seven content drops caught and fixed
v4.7.02026-07-03JSON source parsers: Bricks, classic Oxygen, and Elementor 4 Atomic now ride the lossless transform path as sources
v4.6.02026-07-03Classic Oxygen hardening: all real storage shapes parse, real ct_*/oxy_* vocabulary, unified root-tree output, full style passthrough, responsive media round-tripping
v4.5.02026-07-03Responsive breakpoint round-tripping: canonical desktop/tablet/phone + hover model for divi-5 / elementor-4 / oxygen-6, with cross-framework transfer
v4.4.02026-07-02divi-5 / elementor-4 / oxygen-6 schemas verified against real formats (elementor repo, Divi 5 docs, real Breakdance export); Dependabot, reproducible packaging, four-job CI, make verify
v4.3.42026-05-20Elementor → Gutenberg widget coverage hotfix (compound widgets, marker fallback, settings denormalization); e2e smoke harness now a CI gate
v4.3.32026-05-19functions.php admin pages now factory-driven; eliminates drift surface for framework lists
v4.3.22026-05-19User-facing copy errata (style.css, admin help, CLI help); 9 → 14 / 72 → 182
v4.3.12026-05-19Production-readiness: CLI fatal fix, matrix consistency, test suite green, PHP 8.1 floor, CVE-2026-24765 cleared
v4.3.02026-05-19DIVI 5, Elementor 4 Atomic, Oxygen 6 native parsers; Bricks flat-output fix
v4.2.02026-05-18Kadence + Thrive converters; CMS version re-association; correctness audit
v4.1.02026-01-178 Python converters; site-level parser; styles & template extraction
v4.0.02025-Q4JSON-native transform engine; Zone Theory; 100% metadata preservation

Roadmap

The 4.x line is feature-complete on framework coverage and production-ready as of v5.1.0. Release verification is automated end to end — Dependabot keeps dependencies fresh, make verify mirrors the release gate locally, and the four-job CI pipeline (including release-package smoke) runs on every push and PR. The v4.3.0 proxy schemas were verified against real formats in v4.4.0 (see Schema verification status), and v4.5.0 added responsive breakpoint round-tripping: tablet/phone breakpoints and hover states survive round trips for all three paths and transfer across frameworks through a canonical responsive model.

On Oxygen: classic Oxygen (4.x) support is fully hardened — real ct_*/oxy_* vocabulary, every storage shape (JSON tree, wrapper, flat list, shortcodes), full style passthrough with unit normalization, and responsive media round-tripping. The oxygen-6 path intentionally tracks the verified Breakdance-derived schema (~80% shared codebase) rather than chasing Oxygen 6-specific deltas.

Next (4.7+)

Candidate work for upcoming 4.x releases, roughly in priority order:

  1. More JSON source parsers for the lossless transform path.Done in v4.7.0: Bricks, classic Oxygen, and Elementor 4 Atomic now parse into the universal shape and ride the 100%-metadata Python engine as sources (devtb transform bricks|oxygen|elementor4 <target> file.json).
  2. E2e fidelity smoke gates for more targets.Done in v4.8.0: Elementor → Bricks and DIVI → Gutenberg kitchen-sink gates now run through both engines on every push/PR alongside the original Elementor → Gutenberg gate — and caught seven real content drops on their first run.
  3. Responsive canonicalization for the remaining frameworks.Done in v4.9.0: Elementor v3's _tablet/_mobile/_hover setting suffixes and Bricks' :breakpoint setting keys now canonicalize on parse and re-emit on convert, so responsive data survives round trips and transfers across frameworks (e.g. Elementor tablet overrides become Bricks :tablet_portrait keys).
  4. Python parsers for the remaining frameworks.Done in v4.11.0: all 14 frameworks now parse natively in Python — JSON, block markup, shortcodes, and HTML — completing the parser half of the 5.x engine consolidation.

5.x — engine consolidation (Phase 1 underway)

The 5.x line consolidates both engines onto a single shared schema and retires the lossy HTML-intermediate path. The plan lives in docs/RFC-5.0-engine-consolidation.md; the canonical interchange shape is normatively specified in schema/universal-element.schema.json.

  • Phase 1 (shipped, unreleased): the schema spec, DEVTB_Component::to_universal() on the PHP side, and a dual-engine conformance suite — shared real fixtures parsed by BOTH engines must produce schema-valid, content-equivalent universal documents.
  • Phase 2 (core shipped, unreleased):DEVTB_Universal bridges both directions; the translator gains parse_to_universal() / translate_universal(); the REST /translate endpoint accepts universal as source or target; cross-engine interchange is conformance-tested both ways (a Python-parsed document converts in PHP and vice versa).
  • Phase 3: every translate pair re-routes through the lossless path.
  • Phase 4: 5.0 — one schema, two conforming runtimes.

Contributing

Contributions welcome. Useful starting points:

  • Add a new framework: create a parser/converter pair in translation-bridge/{parsers,converters}/, register in both factories, add the framework key to FrameworkConversionsTest::$frameworks with a sample input, and follow the existing structural-assertion pattern. The Bricks flat-format work in v4.3 is a good reference.
  • Share real exports: real page exports from any supported builder make great regression fixtures — open an issue with the JSON dump if you have one that behaves unexpectedly.
  • Fix a converter bug: see the audit-finding pattern in RELEASE_NOTES_V4.2.0.md — these were caught by running real CMS exports through the round-trip and diffing.

PRs should keep the framework matrix green (vendor/bin/phpunit --filter FrameworkConversionsTest and pytest tests/python).


License

GPL-2.0-or-later. See LICENSE.


Links

Releases

Packages

Contributors

Languages