If you've ever built an onboarding flow, KYC system, or any product that deals with government documents across multiple countries, you know the real problem isn't storing the document. It's validating that it meets the destination country's formal requirements before a human ever looks at it.
The M21Global article on certified translation for EU driving licence exchange lays out a good example of this: EU driving licences follow a standardized format under Directive 2006/126/EC, yet each member state has different rules about whether a translation is required, what language it must be in, and how it must be certified. The document itself is fine. The failure mode is purely a rules-engine problem.
This is a pattern that shows up constantly in software: a well-structured source document, inconsistent downstream validation rules, and a process that fails silently until a human rejects it weeks later. Let's talk about how to model and automate this instead of discovering requirements manually every time.
Why this is a data modeling problem, not a translation problem
The source article's breakdown is basically a requirements matrix:
- Is translation required at all?
- What target language applies (and does the country have multiple official languages)?
- What certification form is accepted (letterhead declaration vs. notarized vs. registered translator)?
- What supporting documents are needed?
That's four independent variables per country, each with its own edge cases. If you're building any kind of relocation, immigration, or compliance tooling, this maps cleanly onto a rules table rather than hardcoded logic.
# requirements_schema.py
from dataclasses import dataclass
from enum import Enum
class CertificationType(Enum):
NONE = "none"
CERTIFIED = "certified" # translator/agency declaration
SWORN = "sworn" # notarized or court-registered translator
@dataclass
class CountryRequirement:
country_code: str
requires_translation: bool
target_languages: list[str] # some countries have >1 official language
certification_type: CertificationType
requires_driving_record: bool
requires_certified_true_copy: bool
authority_name: str
REQUIREMENTS = {
"DE": CountryRequirement("DE", True, ["de"], CertificationType.CERTIFIED, True, False, "Kraftfahrt-Bundesamt"),
"FR": CountryRequirement("FR", True, ["fr"], CertificationType.CERTIFIED, False, False, "Préfecture"),
"ES": CountryRequirement("ES", False, ["es"], CertificationType.CERTIFIED, False, False, "DGT"),
}
This is deliberately simplified, but the point stands: once you encode this as data instead of institutional knowledge sitting in someone's head (or in a vendor's blog post), you can validate submissions programmatically before they're sent anywhere.
Building a pre-submission validator
The mistakes listed in the source article are almost all things a script can catch before a document reaches a case officer:
- Missing certification declaration
- Declaration in the wrong language
- Omitted fields (restriction codes, expiry dates)
- Photocopy submitted where a certified true copy is required
Here's a minimal validator shape:
def validate_submission(doc, country_code):
req = REQUIREMENTS[country_code]
errors = []
if req.requires_translation and not doc.has_translation:
errors.append("Translation required but missing")
if doc.has_translation and doc.translation_language not in req.target_languages:
errors.append(
f"Translation language '{doc.translation_language}' not accepted; "
f"expected one of {req.target_languages}"
)
if doc.has_translation and doc.certification_type != req.certification_type:
errors.append(
f"Certification type mismatch: got {doc.certification_type}, "
f"expected {req.certification_type}"
)
missing_fields = req_fields_missing(doc, country_code)
if missing_fields:
errors.append(f"Missing required fields in translation: {missing_fields}")
if req.requires_certified_true_copy and not doc.is_certified_true_copy:
errors.append("Certified true copy required, plain photocopy submitted")
return errors
This isn't glamorous code. That's the point. Most compliance tooling failures aren't algorithmic, they're from nobody bothering to write down the rules in a structured, testable way.
Keeping the rules table current
The hard part isn't the schema, it's maintenance. Regulatory requirements change, and unlike a software API there's no changelog or versioned spec you can poll. Some practical approaches:
- Treat it like a dependency. Store the requirements table in version control, review changes via PR, and require a source citation (official gov page, embassy notice, etc.) in the commit message.
-
Add a
last_verifiedtimestamp per country entry. Flag anything older than 6-12 months for manual re-check rather than silently trusting stale data. - Separate "hard requirements" from "commonly requested extras." The article mentions Germany's transport authority may request a driving history. Model that as optional-but-flagged rather than mandatory, so your validator doesn't produce false positives.
@dataclass
class CountryRequirement:
# ...
last_verified: str # ISO date
source_url: str
If you're doing this at any scale (more than a handful of countries), it's worth treating the requirements table the same way you'd treat a tax-rate table or shipping-rules table: externalized, auditable, and owned by someone whose job is literally to keep it correct.
Where automation stops being appropriate
It's worth being honest about the limits here. A validator can catch structural problems (missing language, missing field, wrong certification type) but it cannot assess translation quality or legal sufficiency. The distinction the source article draws between certified and sworn translation is a legal one, not a formatting one, and getting that wrong has real consequences for someone's relocation timeline.
So the realistic scope for this kind of tooling is: catch the mechanical failures before submission, surface the right requirements early, and route anything ambiguous (mixed jurisdictions, court-related documents, multiple official languages) to a human who actually knows the law. Automating 80% of the checklist still saves real time, it just shouldn't be mistaken for full compliance automation.
Takeaway
If your product touches document exchange across jurisdictions, don't wait for users to hit rejection emails to learn the rules. Model the requirements as structured, versioned data from day one, build a pre-submission validator against it, and keep a clear line between what the code checks and what still needs a human sign-off.
Top comments (0)