Message Translator
The most pervasive pattern in any EDI integration: convert a message from a source schema to a target schema. Hohpe canonised it in 2003; the code has not changed much since — but the discipline has.
Problem
EDI is defined by the plurality of its formats: EDIFACT in Europe, X12 in North America, cXML at Coupa and Ariba, UBL at PEPPOL, IDoc on the SAP side. No partner speaks a single format. To integrate ORDERS received from 200 suppliers across 4 different formats into one ERP, you must translate — often into an internal canonical model — then re-translate towards the target.
Forces
- Asymmetric semantics. Two formats may carry "the
same information" in radically different structures. EDIFACT
bundles quantity and unit in QTY+21:24:PCE; JSON splits them. UBL
uses
cbc:BaseQuantitywith attributeunitCode. - Missing information. The target may require a field the source does not carry. Either enrich (see Content Enricher) or apply a documented default.
- Information loss. Conversely, the source may carry fields the target ignores. Decision: keep them in a trace field, or drop them explicitly. Never silently.
- Maintainability. A translation "map" is a software asset that survives versions. It must be versioned, tested, audit-closed.
Solution
Hohpe (EIP §85) prescribes a pure component, with no business
state, that takes a message in format A and returns the same
message in format B — nothing more. The translation is structural (the schema changes) and sometimes semantic (values are transformed: an
EDIFACT date "20260514" becomes "2026-05-14" ISO, a quantity with
unit PCE becomes EA per a UN/CEFACT REC
20 mapping table).
EDIFACT ORDERS Canonical JSON
────────────── ──────────────
UNH+1+ORDERS:... ┌──────┐ {
BGM+220+PO-001 │ M.T. │ "header": {
DTM+137:20260514 ──▶│ │──▶ "type": "ORDER",
NAD+BY+8712345600014 │ │ "number": "PO-001",
LIN+1++4006381... └──────┘ ...
QTY+21:24:PCE } Topology
Two main topologies:
- Point-to-point. A direct translation between each source/target pair. Simple to start with 2-3 partners, becomes unmanageable above — the famous n × m mapping problem.
- Hub-and-spoke (canonical). Each format is translated to a common canonical, then each target format is generated from that canonical. The cost of adding a partner becomes O(1) instead of O(n). See the Canonical Model pattern.
EDI implementation
The most emblematic example: translating an EDIFACT D.96A ORDERS to an internal canonical JSON.
UNH+1+ORDERS:D:96A:UN:EAN008'
BGM+220+PO-12345+9'
DTM+137:20260514:102'
NAD+BY+8712345600014::9'
NAD+SU+5412345600015::9'
LIN+1++4006381333931:EN'
QTY+21:24:PCE'
PRI+AAA:12.50'
UNT+8+1' The canonical equivalent:
{
"schemaVersion": "1.0",
"header": {
"type": "ORDER",
"number": "PO-12345",
"date": "2026-05-14",
"buyer": { "gln": "8712345600014" },
"supplier": { "gln": "5412345600015" }
},
"lines": [
{
"position": 1,
"item": { "gtin": "4006381333931" },
"quantity": { "value": 24, "uom": "PCE" },
"price": { "value": 12.50, "currency": "EUR" }
}
],
"sourceTrace": {
"format": "EDIFACT/D96A/ORDERS",
"interchange": "ORD202605140001"
}
} Three interesting translations:
- Date.
DTM+137:20260514:102→2026-05-14. Qualifier102indicates theCCYYMMDDformat; reformat to ISO 8601. - Partner identifier.
NAD+BY+8712345600014::9→buyer.gln. Composite C082 contains identifier + agency qualifier (9= EAN/GS1). Either keep the qualifier in the target, or elide it if the target has only one identifier type. - Quantity with unit.
QTY+21:24:PCE→{ "value": 24, "uom": "PCE" }. Qualifier21(Ordered quantity) is here implicit through context (QTY segment inside an ORDERS LIN).
Reversibility
A translation is reversible if you can reconstruct the source from the target without loss. In EDI, pure reversibility is rare: source formats often have optional or redundant fields that translation normalises. The pragmatic rule: byte-level reversibility is not needed, but we must be able to reconstruct a message semantically equivalent. That allows re-generating an EDIFACT INVOIC from canonical to answer a partner that only speaks EDIFACT.
Anti-patterns
- Partner-to-partner direct translation. 200 partners × 4 formats = 200 × 199 possible translations. Canonical reduces to 200 ins + 200 outs.
- Magic strings in code. The mappings (EDIFACT qualifier → canonical field) must be declarative — tables or DSL — not procedural code buried in implementation.
- Silence on dropped fields. If translation abandons information, the log must record it explicitly. Otherwise audit will never know why such-and-such EDIFACT field disappears.
- Test by specific cases only. Tests must cover combinatorics — qualifiers, optional segments, cardinalities. Translation bugs hide in rare combinations.
- Implicit versioning. EDIFACT D.96A and D.01B do not have the same NAD structure. A single "EDIFACT" translation that ignores the version always breaks eventually.
Related patterns
- Canonical Model — the pivot format we translate to.
- Normalizer — the pattern that orchestrates several Message Translators based on detected format.
- Content Enricher — when translation needs external data.
Sources
- Hohpe G., Woolf B. — Enterprise Integration Patterns, Message Translator (§85). enterpriseintegrationpatterns.com — Message Translator
- UN/CEFACT — Recommendation 20. Unit-of-measure codes (PCE, EA, KGM...) and international cross-reference tables. unece.org — Recommendation 20
- OASIS UBL 2.1 — Annex C. Semantic mapping tables between UBL and EDIFACT concepts (Cross Industry Invoice).
- SAP — IDoc ORDERS05. Documentation of IDoc target structures and their mapping to EDIFACT ORDERS (OSS note 23).