Skip to content

Harden language catalog repair and syntax validation - #1114

Merged
DavidGoodwin merged 6 commits into
postfixadmin:masterfrom
TrapoSAMA:agent/fix-language-update-syntax-repair
Aug 12, 2026
Merged

Harden language catalog repair and syntax validation#1114
DavidGoodwin merged 6 commits into
postfixadmin:masterfrom
TrapoSAMA:agent/fix-language-update-syntax-repair

Conversation

@TrapoSAMA

@TrapoSAMA TrapoSAMA commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • validate each language catalog before comparing translation keys
  • abort the catalog scan immediately when PHP syntax is invalid
  • repair the existing missing semicolons in 24 catalogs as a one-off correction
  • return a non-zero status for missing or obsolete translations
  • run both the catalog comparison and explicit php -l checks in CI
  • add focused regression coverage

Root cause

The tokenizer-based parser accepted token streams from syntactically invalid catalogs. Missing semicolons caused adjacent $PALANG assignments to be treated as one statement, so --patch could insert duplicate keys.

Behavior

languages/language-update.sh does not attempt automatic repair. It validates the complete PHP source before comparing translation keys and aborts the scan on the first syntax error.

Read-only catalog checks return status 1 when any catalog has missing or obsolete keys. --patch can return 0 after adding every missing key, but still returns 1 when obsolete keys remain. The GitHub Actions lint job runs the complete catalog check and explicitly executes php -l for every language file.

Validation

  • PHP 8.4 lint passed for all 36 language catalogs and the affected PHP test file
  • Bash syntax check passed
  • the complete 36-catalog check returned 0
  • invalid syntax returned 1 and prevented later catalogs from being processed
  • git diff --check passed
  • PostfixAdmin 4.x was inspected separately and does not contain this syntax defect
  • GitHub CI run 31548069597 passed lint, PHP 8.2-8.5, MySQL, and PostgreSQL

The full PHPUnit suite was not run locally because dependencies are unavailable in this checkout. Regression tests are included for CI.

Fixes #1112.
Fixes #1113.

@TrapoSAMA
TrapoSAMA marked this pull request as ready for review August 11, 2026 02:08
@TrapoSAMA
TrapoSAMA marked this pull request as draft August 11, 2026 02:12
@TrapoSAMA
TrapoSAMA marked this pull request as ready for review August 11, 2026 02:13
@DavidGoodwin

DavidGoodwin commented Aug 11, 2026

Copy link
Copy Markdown
Member

I think we'd be better off doing a one off fix on those files with invalid syntax, and just aborting/breaking within update-languages.sh if there is invalid syntax in the future (as in, stop trying to be clever fixing up invalid syntax).

@TrapoSAMA

Copy link
Copy Markdown
Contributor Author

Thanks, agreed. I simplified languages/language-update.sh so it only validates catalog PHP syntax and aborts the scan on the first invalid file; the 24 affected catalogs remain a one-off correction. The optional repair logic is now isolated in ADDITIONS/fix-language-syntax.php and is never called by the main script or CI. The updated GitHub CI run passed lint, PHP 8.2 through 8.5, MySQL, and PostgreSQL.

Comment thread ADDITIONS/fix-language-syntax.php Outdated
function next_backup_filename(string $file): string
{
$backup = "$file.bak";
for ($suffix = 2; file_exists($backup); $suffix++) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

file_exists comes with some funny details:

  • it returns false on dead symlinks (so you can have symlinks attack even without any race involved)
  • it caches the result

This is probably not very problematic for this script, but maybe you should at least add a comment (in the file header) like "don't run this script with files in directories that are writeable by others (like /tmp/)"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the cache only lasts as long as the php process, so probably not a problem here.

I just don't see any need to have the 'fix-language-syntax.php' script in git, that's all.

What we do probably need is to just run 'php -l' on each language file (or include languages/ in what psalm or parallel-lint checks).

Comment thread ADDITIONS/fix-language-syntax.php Outdated
Comment thread ADDITIONS/fix-language-syntax.php Outdated
@cboltz

cboltz commented Aug 11, 2026

Copy link
Copy Markdown
Member

PostfixAdmin 4.x was inspected separately and does not contain the syntax defect

I introduced these syntax errors when I updated the *.lang files two days ago. The most obvious (and most boring) issue was that some strings were missing in most language files.

There were also some texts that were changed, and not yet translated in most languages. Instead of just adding a comment, I replaced the not-yet-translated texts with the new text using some script magic, and accidentally killed the semicolon. Sorry for that!

(I'm not sure if my translation updates + fixes from this PR are also needed in the 4.0 branch - feel free to review and backport them.)

@TrapoSAMA

TrapoSAMA commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. I removed the automatic repair helper from the repository and added an explicit php -l check for every language catalog in CI. Could you confirm whether you prefer the one-off semicolon corrections in the affected .lang files to remain in this PR, or whether those files will be corrected internally? Separately, I will review Christian's observation about the 4.0 branch and submit a dedicated 4.x PR if a branch-specific correction is confirmed.

@DavidGoodwin
DavidGoodwin merged commit 2008d06 into postfixadmin:master Aug 12, 2026
7 checks passed
DavidGoodwin pushed a commit that referenced this pull request Aug 12, 2026
- add the missing Spanish translation for `pException_ip_error`, which is used by the 4.x TOTP exception flow
- remove the master-only `pDkim_field_domain_and_selector` key from the 4.x Spanish catalog
- restore exact key parity between `languages/en.lang` and `languages/es.lang`

related to  #1114 

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make language-update.sh run part of CI language-update.sh adds duplicated strings

3 participants