Issue #3620839: Labels that only shipped configuration carries are never checked, and 24 of them are untranslated

Implements #3620839.

Reading shipped configuration

The missing direction was fed by potx and potx was never given config/install or config/optional, so a string that only a shipped configuration entity carries was never required to have a translation. Twenty-two of them did not have one, from the three status labels a requester of the webform example reads, to the flow labels of the payment example, to the name of the date format orchestra_ui installs.

Reading them needs potx, because which of a config entity's values are translatable is a question only the config schema answers and potx is the only thing here that reads schemas. Two changes: the shipped config files go to it alongside the code, and potx_finish_processing() is called so it parses them once every schema has been seen. It also has to find the Drupal root to resolve a dependency's schema, and it does that by splitting a path on /modules/, so it is handed its OWN path rather than the module's — a checkout somewhere else would otherwise leave it with nothing to read the schemas from. A run that discovers no modules now says so and stops instead of reporting a clean tree it never looked at.

Two kinds of string, two scopes

Getting this wrong would have been worse than not asking. localize.drupal.org offers a code string only in the catalog of the project that ships it, so those stay scoped to the project, strictly. locale keeps one string table, so a shipped config label is translated from whichever installed catalog holds the source string, and demanding a per-project copy of a word the base module already translates would manufacture duplicates — which is #3620840's whole subject. Those are scoped to the project's own catalog plus its dependencies', which is measured behaviour rather than a guess: on a French site the examples read "Start" from the base module.

What is not asked for, and why

Fifteen entries go on the allow-list rather than being translated, because they are not this project's words: the exposed-form and pager wording views serializes into a shipped view is core's, and core translates it. The one these views actually chose, the exposed form's Filter, is translated. So is an outcome machine value that ECA's own schema types as a translatable label.

Nine values are counted in the summary and not asked for at all, because no catalog can carry them. orchestra_is_importable() mirrors locale_string_is_safe(), tag list and token-stripping included, so what the check accepts is what locale's importer accepts: an HTML email body is refused there and would be refused here. A value that is a whole configuration document, which a webform's element tree is, is not a translation unit either.

The catalog reader

The second half of the issue. The reader never looked at msgstr, so an entry with an empty translation or a fuzzy flag counted as present while locale ignores both at runtime. It now answers both questions the two directions ask — whether the catalog has an ENTRY, and whether the string has a TRANSLATION — and it scans into records before folding them, so the running state is not a closure holding six variables by reference.

Two things found on the way

A shipped view's column read Processed in English while its French read "Traitée le": the English had lost the "on". Fixing the English rather than the French also stops it colliding with the webform example's Processed status, which is exactly what #3620840 is about.

And the two per-module unit tests #3620615 added are retired, as that issue anticipated: the check now asks their question for every module rather than two. The half of the Easy Email one the check cannot ask — that nobody ships a French HTML body, since the check skips such a value rather than demanding one — stays, with the reason in its docblock.

Result

34 projects, 34 catalogs, 1634 strings extracted, 100 allowed untranslated, 9 config values no catalog can carry. Clean, against 1465 strings extracted before. Every linter green, msgfmt --check on every touched catalog, and the unit and affected kernel classes pass.

This merge request was prepared with the assistance of an AI agent (Claude). The analysis and the wording were reviewed by me before posting, and accountability for the content is mine.

Merge request reports

Loading