Conversation
Proposes syntax-layer i18n support for MDL: inline translation map
literals `{ en_US: 'Hello', zh_CN: '你好' }`, DESCRIBE WITH TRANSLATIONS
output mode, and SHOW TRANSLATIONS query command.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AI Code ReviewWe need to review this PR. The PR is titled "docs: MDL i18n design proposal" and only adds a design document (docs/plans/2026-04-03-mdl-i18n-design.md). No code changes are present in the diff—only a new Markdown file. According to the review checklist, I need to check for overlap/duplication, MDL syntax design (if syntax is added), full-stack consistency, test coverage, security/robustness, scope/atomicity, code quality, and bugs/correctness. Since this PR only adds a design document and no actual code or syntax changes, many checklist items are not applicable:
Looking at the project structure, there's a However, I should verify if there's an existing proposal for i18n. The context says: "Proposals in repo: No proposals directory." But that might be outdated or referring to a different location. Since the PR adds to Since the PR only adds a design document and no implementation, there are no critical issues from a code perspective. However, I should check if the design document itself has any issues that might violate the checklist indirectly. For example, under "Design docs match the actual implementation" in code quality, but since there's no implementation yet, it's not applicable. The design document should be feasible and follow guidelines. Let me skim the design document for any red flags:
Potential issues:
But since this is just a design proposal, and no code is changed, the main thing is to ensure the design document is in the right place and doesn't duplicate existing work. The overlap checklist: "Check Given that the PR body says it's a design proposal and links to the design doc, and no code is changed, this PR is likely just for review of the design before implementation. In such cases, the review should focus on whether the design is sound and ready for implementation, but the checklist is geared towards code changes. However, the instructions say: "Review against ALL of the following checklist items". For items that don't apply (like grammar rules when none are added), I should skip them or note that they are not applicable. But the review structure requires: "Only list sections that have findings — skip empty sections." So for sections where there are no issues (because no code changed), I should not list them. Let me go through each checklist section: Overlap & duplication
MDL syntax design
Full-stack consistency
Test coverage
Security & robustness
Scope & atomicity
Code quality
Bugs & correctness
Given that, there might be no findings. But I should check if the design document has any flaws that would violate the checklist if implemented. For example, under MDL syntax design, if the proposed syntax violates guidelines, that would be a moderation issue even if not implemented yet. Let me evaluate the proposed syntax against the guidelines:
Check the design guideline from the context: "Property format — uses ( Key: value, ... ) with colon separators, one per line" This is for property lists in statements. However, for values that are themselves maps (like translation maps), what should the syntax be? In the PR body, it says: "New MDL syntax must follow design guidelines: reads as English (target audience is citizen developers), uses standard CRUD verbs (CREATE/ALTER/DROP/SHOW/DESCRIBE), consistent property format (Key: value) for property definitions, AS for name-to-name mappings (old AS new), qualified names (Module.Element), no keyword overloading, no symbolic syntax. IMPORTANT: colon is for property definitions (Key: value), AS is for name-to-name mappings — do not flag AS in mapping contexts as a syntax violation." So, for property definitions (i.e., after a colon in a statement), the format should be In the example given in the design: Here, The guideline says "consistent property format (Key: value) for property definitions", which is satisfied because it's Now, does the map syntax follow the guidelines?
Ah, here's a potential issue: the colon is used in two contexts:
The guideline says: "colon is for property definitions (Key: value), AS is for name-to-name mappings". It implies that colon should only be used for property definitions, not for other purposes. But in many languages, colon is used for key-value pairs in maps/objects (like JSON). However, the design guideline might be trying to avoid overloading. Let me check existing MDL syntax for similar constructs. From the context, I know that MDL uses For example, in pages, you might have properties like Is there any existing MDL syntax that uses colon inside a value? Looking at the doctype test files mentioned:
I don't have the content, but from general knowledge of MDL (as per the project), MDL is SQL-like, and I don't recall map literals existing. However, the design guideline explicitly says: "no symbolic syntax" and "colon is for property definitions". This suggests that using colon inside a value for map keys might be considered symbolic syntax or overloading. But the design also says: "AS is for name-to-name mappings (old AS new)" — implying that AS has a specific use, and colon another. In the translation map, if we used AS, it might look like The design guideline says: "do not flag AS in mapping contexts as a syntax violation" — meaning when AS is used for renaming (like For the translation map, using But to comply with "colon is for property definitions", perhaps the map should use a different syntax. Alternative syntaxes:
The design guideline emphasizes "reads as English". The proposed Perhaps it's acceptable. Let me see if there's any existing use of colon in values in MDL. From the CLAUDE.md, under "Mendix Expression String Escaping", it talks about escaping in expressions, but that's different. In the microflow examples, you might have expressions like Another thought: in the ALTER PAGE SET widget properties, you set properties like The design proposal seems reasonable. However, to strictly adhere to "colon is for property definitions", one could argue that inside a value, colon should not be used for other purposes. But the guideline might mean that colon should not be used as a symbolic operator in expressions, but for data literals, it's ok. The design guideline says: "no symbolic syntax" — and gives examples like no overloading, no symbols for domain operations. Using colon in a map literal might be considered symbolic syntax. But let's look at the "IMPORTANT" note: "colon is for property definitions (Key: value), AS is for name-to-name mappings — do not flag AS in mapping contexts as a syntax violation." This implies that colon has a specific reserved use: for property definitions in statements. Therefore, using colon elsewhere (like in data literals) would be incorrect. If that's the case, then the proposed translation map syntax violates the guideline. How else could we specify a translation map? Perhaps using a function-like syntax: Or using AS in a different way: but AS is for name mappings. Another idea: treat the translation map as a set of properties, but that doesn't fit. Perhaps the value should be a string that gets parsed, but that seems messy. Given the context, I recall that in some MDL contexts, there are complex values. For example, in expressions, you have operators, but those are symbolic. But for data literals, MDL might only support simple literals so far. The design proposal introduces a new kind of literal. To comply with the guideline, perhaps the map should use a syntax like: Or maybe use a list: The design guideline emphasizes "LLM-friendly — one example is sufficient for an LLM to generate correct variants" and "Diff-friendly — adding one property is a one-line diff". The proposed map syntax is diff-friendly: adding a language is one line. If we had to use a different syntax, it might not be. But let's see what the checklist says for MDL syntax design: it includes "Colon for property definitions (Key: value), AS for name-to-name mappings ('oldName' AS 'newName') — do not flag AS in mapping/renaming contexts as wrong" This suggests that in the context of property definitions, colon is used, and AS is used mapping Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
ako
left a comment
There was a problem hiding this comment.
Review
This is a design-doc-only PR (210 lines, single file). The proposal is well-structured with clear phasing and compatibility analysis. Here's my assessment, focusing on the overlap you mentioned.
Overlap with existing functionality
The proposal has significant overlap with features already merged to main:
| Proposed feature | Already exists on main |
|---|---|
| SHOW TRANSLATIONS MISSING | ✅ SHOW LANGUAGES — lists all languages with string counts (commit a060152) |
| Translation coverage auditing | ✅ QUAL005 MissingTranslations linter rule — detects elements missing translations in languages used by the project |
| Catalog strings with language data | ✅ strings FTS5 table already stores per-language translations with ElementId for uniqueness (commit 50b1e79) |
The proposal's SHOW TRANSLATIONS command (Section 3) is essentially a pivot view of data already available via SELECT * FROM CATALOG.strings WHERE Language = 'nl_NL'. The MISSING filter is what the QUAL005 linter rule does. The proposal should reference these existing features and explain what value the new command adds beyond what's already possible.
What's genuinely new
The unique contributions are:
- Inline translation map literals
{ en_US: 'Hello', zh_CN: '你好' }— this is the core value. No existing syntax supports writing multi-language strings. - DESCRIBE WITH TRANSLATIONS — showing all languages in DESCRIBE output.
- Merge semantics for bare strings — preserving existing translations when writing a single-language string.
These are valuable and well-designed.
Design feedback
Grammar ambiguity risk is real
The proposal acknowledges { ambiguity with widget body blocks but dismisses it:
Grammar context:
translatedTextonly appears in property value position, not statement position. Widget bodies follow)not:.
This isn't quite right. Consider pluggable widget properties (from PR #68):
PLUGGABLEWIDGET 'com.example.Widget' myWidget (
Caption: { en_US: 'Hello' } -- translation map
) { -- widget body
CONTAINER content { ... }
}
The parser sees Caption: { and must decide: is { starting a translation map or a widget body? Since Caption: uses : and widget bodies follow ), this particular case is disambiguated. But what about:
keyword: { en_US: 'text' }
vs a hypothetical future syntax where { follows : for other purposes? The proposal should add a concrete ANTLR rule showing how translatedText is integrated into the existing propertyValueV3 rule, not just the standalone rule.
Merge semantics need more detail
Bare string
'text'writes to the project'sDefaultLanguageCode. Languages not mentioned are preserved.
This implies every bare-string write requires a read-modify-write cycle:
- Read existing
Texts$Textfrom MPR - Find/update the default language entry
- Preserve other entries
- Write back
Currently, the writer constructs Texts$Text from scratch. This would be a significant change to all writer functions listed in the proposal. The implementation phases should call this out — it's not a trivial change and affects the core writer architecture.
Sort translations by language code
The proposal mentions this as a risk mitigation but doesn't include it in the design. Make it explicit: DESCRIBE output and BSON serialization should sort translations by language code for deterministic output.
Phase plan assessment
The 6-phase plan is reasonable, but:
- P5 (SHOW TRANSLATIONS) should be dropped or scoped down to "show gaps not covered by QUAL005" — the linter already does gap detection, and
SHOW LANGUAGESalready shows the language inventory. - P3 (DESCRIBE WITH TRANSLATIONS) is the highest user-value feature and could be done without P1/P2 (read-only, no grammar change needed).
- P4 (Writer merge semantics) is the riskiest phase — I'd flag it as requiring careful testing against Studio Pro.
Minor
- The "Author: @anthropics/claude-code" attribution is unusual for a design doc. Should this be the human author?
- The translatable fields inventory is useful but should note that
SHOW LANGUAGESalready covers most of these through the catalog strings table. - The proposal doesn't mention how
ALTER PAGE SETwould work with translation maps — this is an important use case for in-place translation updates.
Recommendation
The core idea (translation map literals + DESCRIBE WITH TRANSLATIONS) is sound and fills a real gap. The proposal should be updated to:
- Reference the existing
SHOW LANGUAGES,QUAL005, andstringscatalog table - Drop or re-scope SHOW TRANSLATIONS to avoid duplicating existing functionality
- Add a concrete ANTLR integration example showing how
translatedTextfits intopropertyValueV3 - Detail the read-modify-write implications for bare-string merge semantics
- Drop SHOW TRANSLATIONS (overlaps with SHOW LANGUAGES + QUAL005) - Add concrete ANTLR integration into propertyValueV3 - Detail read-modify-write impact on writer architecture - Reorder phases: P1 = DESCRIBE WITH TRANSLATIONS (highest value, zero risk) - Add ALTER PAGE SET + translation map interaction - Sort translations by language code for deterministic output - Fix author attribution Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
engalar
left a comment
There was a problem hiding this comment.
Updated the design doc addressing all points. Summary of changes:
SHOW TRANSLATIONS dropped. SHOW LANGUAGES + QUAL005 + SELECT ... FROM CATALOG.strings already cover translation auditing. Removed from scope entirely.
Concrete ANTLR integration added. New translationMap rule integrates into existing propertyValueV3 as a new alternative. Disambiguation analysis: translationMap only appears after : or = in property definitions; widgetBodyV3 follows ) at statement level. No ambiguity in the grammar — the parser context resolves it unambiguously. See updated Section 1.
Read-modify-write impact detailed. Current writers construct Texts$Text from scratch. Bare-string merge semantics require a shared mergeTranslation(existingBSON, translations) helper that reads existing items, updates/inserts the target language, and preserves others. This touches 11+ call sites across 7 writer files. Flagged as high-risk P4 phase requiring Studio Pro validation.
Phase order revised. P1 is now DESCRIBE WITH TRANSLATIONS (read-only, no grammar change, highest user value). Grammar/AST/Visitor are P2-P3. Writer merge semantics are P4 (highest risk).
ALTER PAGE SET interaction added. Translation maps work in ALTER PAGE SET via propertyValueV3 — no additional grammar changes needed (Section 3).
Translation ordering made explicit. Items array sorted by language code for deterministic BSON output.
Author attribution fixed.
AI Code ReviewCritical Issues
Moderate Issues
Minor Issues
What Looks Good
Automated review via OpenRouter (Nemotron Super 120B) — workflow source |
Summary
{ en_US: 'Hello', zh_CN: '你好' }DESCRIBE ... WITH TRANSLATIONSoutput mode for roundtrip-safe multi-language outputSHOW TRANSLATIONS [MISSING]query command for translation coverage auditingMotivation
MDL currently drops all non-default translations when describing or creating model elements. Multi-language Mendix projects cannot use MDL for full model management without losing translations.
Design
See
docs/plans/2026-04-03-mdl-i18n-design.mdfor the full proposal including:Test plan
{ }syntax🤖 Generated with Claude Code