wordpress-mobile / wordpress-mobile/WordPress-iOS

Enforce localization key immutability in CI

Open
#25,790 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Swift
Stars
3.9k
Forks
1.2k
Avg merge
23h 51m
Merged PRs (30d)
58

Description

Summary

The regular-string String Catalog fold treats each (key, locale) cell's stored English as the record of what its translation was made for. If an explicit-key string's English is reworded in place (the key stays, only value: changes), xcstringstool sync silently keeps the old translations — now stale for the new text — and the fold can't tell a translation of the old English from a current one.

We've decided localization keys are immutable: rewording requires a new key. generate_strings_catalog now hard-fails on a reworded key (CatalogHelper.reworded_keysenforce_immutable_source_keys in fastlane/lanes/localization_catalog.rb).

The gap this issue tracks

That check compares freshly-extracted English against the persisted catalog, which works for the local manual lane but not in CI: Localizable.xcstrings is gitignored and generated transiently, so CI has no prior English to diff against. A reword can therefore merge without CI catching it.

Proposal

Add a CI lint on the committed English .strings — the one cross-run baseline we do keep (it's the GlotPress source of truth): fail when an existing key's value changes (same key, different English).

  • A key-as-source reword shows up in the .strings diff as a remove + add → passes (that key genuinely changed).
  • An explicit-key reword shows up as same-key / changed-value → fails, with a message to mint a new key.

This is what makes immutable keys enforced on every PR, not only where the catalog persists.

Escape hatch

Hard-fail everywhere for now, no exceptions. If the friction on cosmetic edits (typo fixes) proves burdensome, add an opt-in ack later — a Reword: commit trailer, or a PR-comment + review gate — that flips reconcile from fail to its keep-and-flag (needs_review) path. The placeholder-format gate runs regardless, so an ack could only ever let through prose drift, never a runtime crash.

References

  • Enforcement today: CatalogHelper.reworded_keys (fastlane/lanes/catalog_helper.rb), enforce_immutable_source_keys (fastlane/lanes/localization_catalog.rb).
  • Rationale + the human ?? AI ?? English contract and immutable-key note: docs/localization-pipeline.md.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with CatalogHelper.reworded_keys in fastlane/lanes/catalog_helper.rb, enforce_immutable_source_keys in fastlane/lanes/localization_catalog.rb, and the workflow that validates committed English .strings files. Trace how the existing source baseline is read, then ensure CI fails for same-key value changes while allowing remove-and-add key changes; verify the failure message requires minting a new key.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
ci-cd, localization
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.