Skip to content

ci: regenerate en_EN.json to remove orphaned keys - #23

Open
liviaUeno wants to merge 1 commit into
developfrom
fix-orphaned-i18n-keys
Open

liviaUeno wants to merge 1 commit into
developfrom
fix-orphaned-i18n-keys

Conversation

@liviaUeno

@liviaUeno liviaUeno commented Sep 24, 2026 •

Copy link
Copy Markdown

i18n: regenerate en_EN.json to remove orphaned keys

Context

The Static Analysis / i18n Check (Element Web) workflow was failing on develop — en_EN.json had orphaned keys (translation keys no longer referenced anywhere in the code).

What changed

Regenerated src/i18n/strings/en_EN.json via pnpm i18n (which runs matrix-gen-i18n to scan the codebase for _t()/_td() usages, sorts the keys, and lints the result). This removes keys that are no longer used and keeps the file consistent with what's actually referenced in the code.

No manual edits — this is a generated file.

Note: hardcoded strings introduced in recent features

While working on recent features (Live streaming, the space/bundle merge, admin promotion), several new UI strings were written directly in the components (e.g. "Iniciar transmissão", "Configurar transmissão") instead
of going through _t() with a translation key. This means:

  • Those strings don't appear in en_EN.json and aren't translatable — they render as-is regardless of the user's selected language.
  • This i18n check doesn't catch that, since it only validates consistency among existing translation keys, not whether new UI text bypassed the system entirely.

Not fixed in this PR — it would be a decent amount of work to go through and convert (identify every hardcoded string, add proper keys to en_EN.json,
update each component). Flagging it here so it's tracked; happy to pick it up as a separate task if it's a priority.

@liviaUeno
liviaUeno requested a review from zZMathSP September 24, 2026 13:04
@liviaUeno liviaUeno changed the title fix: regenerate en_EN.json to remove orphaned keys ci: regenerate en_EN.json to remove orphaned keys Sep 24, 2026

@zZMathSP zZMathSP left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hi! Thanks for picking this up. First, the good news: I regenerated en_EN.json locally with the pinned matrix-web-i18n@3.6.0 (matrix-gen-i18n, matrix-sort-i18n, matrix-i18n-lint) and got a zero diff against your branch, so the generated file is exactly right and all three i18n Check jobs are green. Nice.

Now the teaching moment. gen-i18n removes a key when it can no longer find a _t("that|key") call in the source. So every key that disappeared in this diff is a clue: somewhere, a _t() call was removed. Before accepting a deletion, it is worth asking "why did this key become orphaned, and was that intentional?" In this case, when I followed the six keys back to the code, I found two different stories, and neither one is really "the key was unused":

  1. Two keys (create_space|*_description) were orphaned because a _t() call was replaced by hardcoded Portuguese text. That is a bug, and deleting the key locks it in.
  2. Four keys (spotlight_dialog|*) were orphaned because JSX was commented out instead of removed. The commented code and its imports are what is still failing ESLint and tsc in the same Static Analysis workflow.

I left one inline comment per finding with concrete pointers. None of this is a big change, and once it is done this PR will actually close the loop on the CI failure instead of fixing one symptom. Happy to pair on any of it if you want.

One more general tip: when a PR removes user-facing strings, grep apps/web/playwright for them too. Two e2e specs still assert on strings and element IDs that no longer render (details inline).

"name_required": "Please enter a name for the space",
"personal_space": "Just me",
"personal_space_description": "A private space to organise your rooms",
"private_description": "Invite only, personal or for your team",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Let's not delete these two keys; let's fix the code that stopped using them.

private_description and public_description became orphans because commit befb957 replaced the _t() calls in apps/web/src/components/views/spaces/SpaceCreateMenu.tsx (lines 331 and 337) with hardcoded Portuguese text:

description="Aparece no Explorar — qualquer pessoa pode encontrar e entrar."
...
description="Não aparece no Explorar — só com link ou convite."

Think about what a user with the UI in English (or any of the other ~40 locales we ship) sees when they open the space-creation menu: Portuguese, no matter what language they picked. And all the existing translations of these two keys in the other locale files become unreachable.

The rule of thumb in this codebase: user-facing text always goes through _t(), even when it is only used once, and even if the wording is Portuguese-first. To change the copy, change the English source string in en_EN.json and translate it in pt_BR.json.

Suggested fix:

description={_t("create_space|public_description")}
...
description={_t("create_space|private_description")}

then update the two English values in en_EN.json to the new wording (something like "Shows up in Explore — anyone can find and join." / "Hidden from Explore — invite or link only.") and rerun pnpm i18n. The keys will come back on their own, because gen-i18n will see the _t() calls again.

"one": "%(count)s Member",
"other": "%(count)s Members"
},
"create_new_room_button": "Create new room",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This key was orphaned by commented-out code, not deleted code. The comments are what is still breaking CI.

If you open apps/web/src/components/views/dialogs/spotlight/SpotlightDialog.tsx around lines 1241-1259 and 1264-1281, you will see the JSX that used create_new_room_button, cant_find_room_helpful_hint, group_chat_section_title and start_group_chat_button wrapped in {/* ... */} and // ... (from commit f873077).

Here is the chain of consequences:

  • Commenting out the JSX removes the _t() calls, so gen-i18n drops the keys (that is what you are fixing here).
  • But it also leaves three imports with no remaining usage: capitalize (line 10), GroupIcon (line 40) and showStartChatInviteDialog (line 67).
  • ESLint (@typescript-eslint/no-unused-vars) and tsc (TS6133) flag exactly those symbols. You can see them in the Static Analysis job of this PR (run 36003166289). So the umbrella check stays red even with i18n green.

A good habit: commented-out code is a smell in a PR. Git already remembers the old version for us. If a feature is being removed, delete the code and its imports. If it is being temporarily disabled, add a TODO with a ticket and keep the imports used, or better, put it behind a setting/feature flag.

Suggested fix for this PR: delete the two commented blocks, remove the three unused imports, and rerun pnpm i18n and pnpm lint. That turns this from "fix the i18n check" into "fix the Static Analysis workflow", which is the real goal.

@@ -3288,8 +3283,7 @@
"result_may_be_hidden_privacy_warning": "Some results may be hidden for privacy",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Heads-up: these four keys survived the regen, but the code that uses them is also dead.

result_may_be_hidden_privacy_warning, result_may_be_hidden_warning, cant_find_person_helpful_hint and copy_link_text are all rendered inside hiddenResultsSection in SpotlightDialog.tsx (declared at line 1210). That variable is still computed, but it was dropped from the content fragment further down (around line 1284), so React never renders it.

This is a nice illustration of the limits of the tool: gen-i18n only checks "is there a _t() call in the source?", not "is that code reachable?". The _t() calls are still there, so the keys stay, even though no user can see them. tsc, on the other hand, does notice: TS6133 'hiddenResultsSection' is declared but its value is never read is another of the Static Analysis errors.

Two valid ways to resolve it, pick one deliberately:

  1. Restore the feature: add {hiddenResultsSection} back into the content fragment. Users filtering by People get the "Some results may be hidden for privacy / Copy invite link" hint again.
  2. Remove the feature: delete the whole hiddenResultsSection block and rerun pnpm i18n, which will prune these four keys as well.

What we should avoid is the current middle state where the code is neither used nor gone.

"result_may_be_hidden_warning": "Some results may be hidden",
"search_dialog": "Search Dialog",
"spaces_title": "Spaces you're in",
"start_group_chat_button": "Start a group chat"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The Playwright e2e specs still depend on this string and its button.

When a PR removes user-facing strings, it is worth grepping apps/web/playwright for the same text, because our e2e tests assert on literal English copy. Two specs will fail as things stand:

  • apps/web/playwright/e2e/spotlight/spotlight.spec.ts:346-349 waits for #mx_SpotlightDialog_button_startGroupChat and expects it to contain "Start a group chat". That button lives in the commented-out groupChatSection, so the locator will time out.
  • apps/web/playwright/e2e/room-directory/room-directory.spec.ts:77-81 expects the text "If you can't find the room you're looking for, ask for an invite or create a new room." (cant_find_room_helpful_hint, also removed here) and compares against the filtered-no-results.png screenshot baseline, which still shows that hint.

The right fix depends on the product decision from the other comments: if those features are really gone, delete or rewrite these test cases and regenerate the screenshot baseline. If they are coming back, the tests can stay as they are. Either way, the tests should change in the same PR as the strings, so the suite stays green at every commit.

},
"spotlight_dialog": {
"cant_find_person_helpful_hint": "If you can't see who you're looking for, send them your invite link.",
"cant_find_room_helpful_hint": "If you can't find the room you're looking for, ask for an invite or create a new room.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Something to be aware of about the other locale files (not a blocker for you, but worth knowing).

After this change, en_EN.json no longer has these six keys, but the other 35+ locale files (pt_BR.json, de_DE.json, ...) still do. Try grep -l start_group_chat_button apps/web/src/i18n/strings/*.json to see it.

Why not just remove them by hand? Because .github/workflows/i18n_check.yml has a step that asserts only en_EN.json was modified and fails the job otherwise. Upstream, the other locales are pruned by the Localazy sync workflow (localazy_download.yaml), which has never run in this fork.

So the mental model is: en_EN.json is the source of truth we edit; every other locale is generated. Nothing for you to change in this PR, but I am flagging it so that we (the team) decide on a pruning path for the other locales before the orphan set grows with each regen. If you want a follow-up task, opening an issue for that would be a great one.

This branch has not been deployed

No deployments
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.

2 participants