Skip to content

Migrate last CaptionML/OptionCaptionML occurrences off deprecated syntax - #10517

Draft
Alexander Holstrup (aholstrup1) wants to merge 1 commit into
mainfrom
aholstrup1-al0424-captionml-migration
Draft

Migrate last CaptionML/OptionCaptionML occurrences off deprecated syntax#10517
Alexander Holstrup (aholstrup1) wants to merge 1 commit into
mainfrom
aholstrup1-al0424-captionml-migration

Conversation

@aholstrup1

@aholstrup1 Alexander Holstrup (aholstrup1) commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

What & why

AL0424 flags the deprecated multilanguage syntax (CaptionML / OptionCaptionML). It is currently pinned to Warning in src/rulesets/base.ruleset.json as a temporary mitigation (from #10470), and cannot be promoted back to Error while any occurrence remains.

A full scan of all .al files found exactly 4 remaining occurrences, in 2 Rapid Start test fixtures:

File Property
src/Layers/W1/Tests/Rapid Start/EnumRs.Enum.al CaptionML = ENU = 'Eight'/'Nine'/'Ten', DAN = 'Otte'/'Ni'/'Ti';
src/Layers/W1/Tests/Rapid Start/OptionAndEnumRS.Table.al OptionCaptionML = ENU = 'Zero,One,Two', DAN = 'Null,En,To';

This PR migrates all four.

Why not a .xlf translation file

The obvious migration is Caption = 'Eight'; + a checked-in Translations/Tests-Rapid Start.da-DK.xlf, because the Danish captions look load-bearing: ImportPackageWithTranslatedOptionsAndEnums() runs under GlobalLanguage(1030) and the Danish captions are the only thing distinguishing it from its ENU sibling ImportPackageWithOptionsAndEnums(). Dropping them without replacement would silently hollow out the test.

That route does not work for this project:

  1. build/projects.json registers Tests-Rapid Start as isGDLProject: true + isTest: true with no hasTranslations, so ALAppBuild.psm1 computes HasTranslations = false.
  2. With HasTranslations = false, Build-Application always takes the LCG branch (-features:lcgtranslationfile). The XLIFF branch — the only one that consumes .xlf from Translations/ — is never taken for this project.
  3. BCApps' own AL-Go CI compiles with no translation feature at all.
  4. .gitignore blanket-ignores *.xlf behind a hand-maintained allowlist. The repo contains exactly one hand-authored .xlf (en-US, for a shipping product app). There is no precedent for a test app carrying a translation to drive runtime behaviour.

A checked-in da-DK.xlf would very likely be dropped from the test .app that actually runs, leaving the Danish captions non-functional — the exact silent failure the migration is meant to avoid.

What I did instead

Made the test independent of compile-time multilanguage captions and assert the underlying contract directly, which is strictly stronger than the previous implicit probe.

Reading the RapidStart code, the real invariant is that the export is caption-independent:

  • Export: ConfigXMLExchange.FormatFieldValue uses Format(FieldRef.Value, 0, 2) for FieldType::Option (enums included) — invariant format.
  • Import: ConfigValidateManagement.EvaluateValueToOption (XMLValue = true) resolves via Evaluate(OptionNo, Value) into an Integer, so the XML must carry the ordinal.
  • VerifyEnumsAndOptionsAfterApplyingPackage() only ever asserted ordinals — it never asserted a caption string.

So the Danish captions only implicitly probed "the round-trip is caption-independent". The test now asserts that explicitly: still under GlobalLanguage(1030), it verifies the exported XML serializes the option/enum values as language-independent ordinals (0,1,2 / 8,9,10) rather than localized caption text — using the XMLDOMManagement.LoadXMLDocumentFromFile + FindNodes pattern already used elsewhere in the same codeunit.

GlobalLanguage(LanguageId) is also now restored immediately after the apply and before the assertions, so a failing assert cannot leak Danish global language into subsequent tests in the suite.

No pragma warning disable AL0424 — pragma would suppress the diagnostic without fixing the condition, leaving the captions non-functional and the test hollow, just silently.

Linked work

Fixes #

⚠️ This still needs an issue linked. I did not create one; please attach the appropriate approved issue (or ADO work item via AB#<number>) before this is merged.

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome

Verified:

  • Full-repo scan confirms \b\w*ML\s*=\s*[A-Z]{3}\s*= now returns zero matches across all .al files (was 4).
  • Traced the export/import contract in source to establish the expected ordinals (0,1,2 and 8,9,10) — see the reasoning above; the import path's Evaluate(OptionNo, Value) into an Integer proves the XML must hold ordinals, not caption text.
  • Confirmed AddPrefixMode is false for this codeunit (SetPrefixMode is only ever called in ERMRSPackageBaseOperations, a different codeunit with its own Config. XML Exchange instance), so the exported field nodes are named plainly and the XPath resolves.
  • Known false positives deliberately left untouched: DataDictionary.Report.al (dataitem/columns literally named CaptionML, for parsing legacy C/AL text exports), RolecenterSelectorMgt.Codeunit.al and its GB copy (Label 'CaptionML', Locked = true — an XML attribute name), and DataDictionary.rdlc.

Not verified — please treat as the main review risk:

  • I did not compile this and did not run the tests. Docker Desktop is installed on my machine but the daemon will not start (npipe:////./pipe/dockerDesktopWindowsEngine not found), so I could not follow LOCAL_DEV_ENV.md to build a container; the repo also pins a bcinsider artifact. I have deliberately left the build/run checkboxes unticked rather than claim verification I don't have.
  • Accordingly, ImportPackageWithTranslatedOptionsAndEnums needs a real run to confirm the new assertions pass. That is the main thing I'd like a reviewer (or CI) to confirm.

Risk & compatibility

  • Test-only change. EnumRs (enum 136605) and OptionAndEnumRS (table 136605) are fixtures used solely by ERMRSPackageOperations.Codeunit.al within the same test project; no product code references them.
  • The English captions are unchanged, so any caption-dependent behaviour in ENU is unaffected. The Danish captions are removed — intentionally, since as established above they could not be made to work via a translation file for this project, and nothing asserts on them.
  • Follow-up (not this PR): promote AL0424 back to Error in src/rulesets/base.ruleset.json. That should only happen once this change has propagated to the NAV repo, so the internal multi-country build doesn't break again.

The deprecated multilanguage syntax (CaptionML/OptionCaptionML) is flagged by
AL0424, which is currently pinned to Warning in src/rulesets/base.ruleset.json
as a temporary mitigation. The last four occurrences in the repository were in
two Rapid Start test fixtures.

The Danish captions on these fixtures were only implicitly load-bearing:
ImportPackageWithTranslatedOptionsAndEnums runs under GlobalLanguage(1030) and
relied on them to differ from its ENU sibling test. A checked-in .xlf is not a
viable replacement here, because Tests-Rapid Start is registered in
build/projects.json as a GDL test project without translations, so it is always
compiled with -features:lcgtranslationfile and never takes the XLIFF branch that
consumes Translations/*.xlf.

Instead, make the test independent of compile-time multilanguage captions and
assert the underlying contract directly: the RapidStart export serializes option
and enum values as language-independent ordinals rather than localized captions.
The global language is now also restored before the assertions so a failure
cannot leak Danish into subsequent tests.

Promoting AL0424 back to Error is left as a follow-up.
@github-actions github-actions Bot added the Integration GitHub request for Integration area label Aug 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Could not find a linked ADO work item. Please link one by using the pattern 'AB#' followed by the relevant work item number. You may use the 'Fixes' keyword to automatically resolve the work item when the pull request is merged. E.g. 'Fixes AB#1234'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Integration GitHub request for Integration area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant