Skip to content

OpenConceptLab/ocl_issues#2917 | Remove 223 unused i18n keys, and add the 4 the code uses to every catalog - #107

Merged
paynejd merged 4 commits into
mainfrom
OpenConceptLab/ocl_issues#2917-i18n-key-cleanup
Oct 18, 2026
Merged

paynejd merged 4 commits into
mainfrom
OpenConceptLab/ocl_issues#2917-i18n-key-cleanup

Conversation

@paynejd

@paynejd paynejd commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

What changed and why

The Mapper's catalogs had drifted from its code (OpenConceptLab/ocl_issues#2917, a follow-up to OpenConceptLab/ocl_issues#2880). On main, 209 of the 791 English keys were unreferenced, and the code used four keys no catalog had.

  • Four keys added to en, es, pt-BR and zh. common.none (MatchDetailsPanel.jsx), common.saved (MultiAlgoSelector.jsx) and search.save_default_filters (SearchFilters.jsx) showed the raw key in every language. map_project.candidates_legacy_shape (MapProject.jsx) showed its English default. common.none and search.save_default_filters take oclweb3's wording in all four locales, and common.saved follows the catalogs' existing "saved" strings. The English for candidates_legacy_shape is the default the call already passes, so English reads the same.
  • The 209 unreferenced keys removed from all four catalogs. This is the ticket's list, still the same on current main. The bookmarks namespace, left empty, goes too.
  • The optional item: the 14 keys only the non-concept column sets named. ResultConstants.js keeps only ALL_COLUMNS.concepts. TableResults.jsx reads ALL_COLUMNS[resource], and its only parent, SearchResults, is rendered by map-projects/Candidates.jsx and Search.jsx, both with resource='concepts'. So the mappings, repos, orgs, users and url_registry sets never rendered. They go, with their 14 keys and the three pieces only they used: mappings/ConceptCell.jsx, mappings/FromAndTargetSource.jsx and formatWebsiteLink() in common/utils.js.
  • es's two keys that English lacks, common.or_go_to_your and concept.history, go too. Nothing references them, and no other catalog has them.

Each catalog now has the same 572 keys (791 − 209 − 14 + 4).

How each removed key was checked

  • The list. The static audit from OCL Mapper: Audit unused i18n keys and Portuguese translation coverage ocl_issues#2880, run locally from its unmerged branch, reports the same 209 unreferenced keys and the same four missing ones on current main.

  • Last segment. Every string literal under src/ that contains a key's last segment as a word was listed, and none of them builds a key. Only three key patterns built at run time span a whole namespace, at seven call sites, and each was read by hand:

    • `concept.${prop}` (ConceptProperties.jsx) yields only concept_class and datatype;
    • `search.${resource}` (SearchResults.jsx) yields only concepts;
    • 'map_project.' + bucket (MapProject.jsx, ScoreBucketButton.jsx) yields only the three score buckets.

    Five t() calls take their key from a variable. Four get it from literals that aren't on the list: announcement links, the usage chip's lines, target-version badges and column labels. The fifth translates an algorithm whose name is a <Trans> element, and there is none: API algorithms are JSON, and the two built-in ones name themselves with t().

  • History. Each full key's history, the commits git log -S lists but with the key matched as a whole word, ends with the commit that removed its last use. 52 keys were never used in this repo's source. Of the other 157, 113 went with the oclweb3 leftovers removed in 4ae1a18 and 4c310cc. The three most recent removals (64511e9, 2806eef, 346cab7) drop the call outright rather than build the key another way.

  • After the change, the audit reports no unreferenced keys and nothing needing attention, and no locale has a missing, blank or extra key.

Tests

src/i18n/__tests__/catalogKeys.test.js checks that:

  • no locale has a key English lacks;
  • every literal key in the source (t('a.b'), this.props.t('a.b'), t(`a.b`), i18nKey='a.b') is in the English catalog. It reads 598 uses of 479 keys. Keys built at run time aren't read.

Against main's catalogs, 2 of its 5 tests fail: es has two keys English lacks, and the literal-key check names exactly the four call sites above. With this branch's pt-BR and zh but main's English, those two locales fail as well, since they'd hold the four new keys and English wouldn't. aiAssistantNaming.test.js no longer lists the removed map_project.ai_assistant_limit_reached.

The gate, run as pr.yml runs it, on Node 22.23.2:

  • the start-prod.sh secret check: passed;
  • npm ci: ok;
  • eslint: clean. I ran it with --no-eslintrc -c .eslintrc.json, the config CI uses: this checkout is nested in another, and ESLint would load that one's config too;
  • npm run test:all: 511/511 unit tests and 6/6 integration tests pass;
  • a development webpack build compiles.

PR checks: "Lint and test" passed on 4f2332d (run 39062561106).

Visual check

A throwaway harness, not committed, rendered two components side by side with main's catalogs and with this branch's. It ran in headless Chromium through Playwright, with each component in a 360px column, once per locale: en, es, pt-BR and zh. The ticket names no widths.

  • MatchDetailsPanel, for a match with a highlight but no raw score. On main the Raw Scores row shows common.none in all four languages. On this branch it shows None, Ninguno, Nenhum and 无.
  • SearchFilters, as a nested panel whose user may save default filters. On main the button shows search.save_default_filters. On this branch it shows Save as Default Filters, Guardar como Filtros Predeterminados, Salvar como filtros padrão and 另存为默认筛选条件. The longest, es, fits on one line.

The page logged no errors. common.saved and map_project.candidates_legacy_shape weren't rendered: one shows only after a custom algorithm's details are saved, the other only when a project loads in the old candidates format. The literal-key test covers their English entries.

Acceptance criteria

  • Add common.none, common.saved, search.save_default_filters and map_project.candidates_legacy_shape to en, es, pt-BR and zh. Done in 37ef20e. catalogKeys.test.js ("every literal key in the source is in the English catalog") fails without the English entries, and the visual check above shows two of the keys in all four languages.
  • Remove the unreferenced keys from all four locales at once, each checked by hand first (its last segment, and git log -S). Done in 09d5f6b; the check is described above. catalogKeys.test.js ("has no key English lacks") fails if a key leaves English but stays in another locale.
  • Optional: remove the 14 keys in the non-concept column sets of ResultConstants.js, along with those sets. Done in 5e4f2e7.

Docs

Nothing to update. No README, doc or comment describes the catalogs' keys or the removed column sets, and the one comment that names ALL_COLUMNS['concepts'] (Candidates.jsx) still holds.

Not done

  • No existing key is reworded; only the four new keys are translated.
  • map_project.candidates_legacy_shape's call keeps its English default, as the Mapper's other calls with defaults do (map_project.target_repo_version_required, for one).

Noticed, not fixed

  • addAlgo in MultiAlgoSelector.jsx still handles an algorithm whose name is a <Trans> element. No algorithm defines its name that way, so that branch never runs.
  • HIGHLIGHT_ICON_WHITELISTED_FILEDS in ResultConstants.js is imported nowhere. FACET_ORDER and SORT_ATTRS there still have entries for other resources, and SearchResults.jsx branches on those resources too. None of them holds i18n keys, so they're outside this ticket.
  • formatWebsiteLinkTruncated() in common/utils.js has no caller, here or on main.
  • OpenConceptLab/ocl_issues#2907 | suggesting field mapping for column headers #106 also edits the four catalogs. It uses none of the removed keys, but whichever of the two merges second will need its catalogs rebased.

Review

  • Codex, pass 1 (5e4f2e7): clean.
  • Simplification review (5e4f2e7): 4 items. S1 and S2, both in catalogKeys.test.js, were applied in 4f2332d: a stdlib directory listing, and no per-locale test of the four keys. S3 and S4 were kept, since that code was dead before this PR and holds no i18n keys; both are listed under "Noticed, not fixed".
  • Codex check of the cuts (4f2332d): clean, so no cut was reverted.

No P0 or P1 is open.

closes OpenConceptLab/ocl_issues#2917

🤖 Generated with Claude Code

https://claude.ai/code/session_01M8452pAtpyMrv7QRKXbUsj

Written by an Octoad session worker (worker-v0.11, recipe lean-loop, flow public>public, run openconceptlab-ocl-issues-2917-20261017-145015).

paynejd and others added 3 commits October 17, 2026 15:11
…very catalog, and test the catalogs against the source

common.none (MatchDetailsPanel.jsx), common.saved (MultiAlgoSelector.jsx)
and search.save_default_filters (SearchFilters.jsx) showed as the raw key
in every language, and map_project.candidates_legacy_shape (MapProject.jsx)
showed its English default. Each is now in en, es, pt-BR and zh. The
English text of candidates_legacy_shape is the default the call passes, so
English reads the same; common.none and search.save_default_filters take
oclweb3's wording in all four locales.

es also drops common.or_go_to_your and concept.history: no other catalog
has them, and nothing references them.

catalogKeys.test.js checks that every locale has the four keys and no key
English lacks, and that every literal key in the source (t('a.b'),
i18nKey='a.b') is in the English catalog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8452pAtpyMrv7QRKXbUsj
…m all four catalogs

No call site, dynamic key family or string literal in src/ can produce
these keys. Each was checked by hand: its last segment, searched in every
string literal under src/, builds no key, since no t() call builds keys in
its namespace from such a value (the three that span a whole namespace,
`concept.${prop}`, `search.${resource}` and 'map_project.' + bucket, produce
only concept_class and datatype, concepts, and the three score buckets).
git log -S on the full key shows each one's last use going, mostly with the
components removed in 4ae1a18 and 4c310cc; 52 were never used in this
repo's source. bookmarks, left empty, goes too.

aiAssistantNaming.test.js no longer lists ai_assistant_limit_reached.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8452pAtpyMrv7QRKXbUsj
… in ResultConstants.js, and remove the 14 keys only the others named

TableResults.jsx reads ALL_COLUMNS[resource], and its only parent,
SearchResults, is rendered by map-projects/Candidates.jsx and Search.jsx,
both with resource='concepts'. The mappings, repos, orgs, users and
url_registry column sets never rendered, so they go, with the 14 label keys
nothing else names: common.created_on, mapping.fromAndTargetSource,
mapping.fromConcept, mapping.map_type, repo.repo_id, repo.repo_type,
url_registry.canonical_url, url_registry.target_owner, and user.company,
email, joined_on, location, username and website.

ConceptCell.jsx, FromAndTargetSource.jsx and formatWebsiteLink() rendered
only those columns, so they go too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8452pAtpyMrv7QRKXbUsj
@paynejd paynejd added origin/ai-generated Issue or PR created by an AI agent origin/session-worker Opened by the Octoad session worker; a run record backs it labels Oct 17, 2026

@paynejd paynejd left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Codex review, pass 1 (codex-cli 0.163.0, commit 5e4f2e7)

Clean.

findings.json
{
  "reviewer": "codex-cli 0.163.0",
  "perspective": "defects",
  "mode": "full",
  "commit": "5e4f2e7",
  "verdict": "clean",
  "prior": [],
  "findings": []
}

@paynejd

paynejd commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

Response to Codex pass 1

No findings, so nothing to fix. No P0 or P1 is open, so the defect loop stops after this pass.

@paynejd paynejd left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Simplification review (commit 5e4f2e7)

4 items.

  • S1 · stdlib · src/i18n/tests/catalogKeys.test.js:42 · the recursive sources walker → readdirSync(SRC_DIR, { recursive: true }), filtered to .js/.jsx files outside the test folders (-4)
  • S2 · dup-test · src/i18n/tests/catalogKeys.test.js:24 · the ADDED list and its per-locale test, which repeat the literal-key test for en and pin four one-off translations in the other locales → nothing replaces it (-8)
  • S3 · delete · src/common/utils.js:31 · formatWebsiteLinkTruncated, which had no caller before this PR either, with the React, Tooltip and merge imports only it uses → nothing replaces it (-26)
  • S4 · delete · src/components/search/ResultConstants.js:27 · HIGHLIGHT_ICON_WHITELISTED_FILEDS, which nothing imports → nothing replaces it (-9)
findings.json
{
  "reviewer": "claude subagent",
  "perspective": "simplify",
  "mode": "full",
  "commit": "5e4f2e7",
  "verdict": "findings",
  "prior": [],
  "findings": [
    {
      "id": "S1",
      "severity": null,
      "tag": "stdlib",
      "file": "src/i18n/__tests__/catalogKeys.test.js",
      "line": 42,
      "claim": "The recursive `sources` walker (6 lines) does what fs.readdirSync(dir, { recursive: true }) already does. Node has shipped that option since 20.1, and CI and the Dockerfile run Node 22. On this tree both list the same 171 files.",
      "scenario": null,
      "action": "const SOURCES = readdirSync(SRC_DIR, { recursive: true })\n  .filter(file => /\\.jsx?$/.test(file) && !/(^|\\/)__(tests|integration)__\\//.test(file))\nThe test then reads readFileSync(path.join(SRC_DIR, file), 'utf8') and reports `${file}: ${key}`. The paths come back already relative, so the path.relative call goes too.",
      "lines_delta": -4,
      "confidence": "high"
    },
    {
      "id": "S2",
      "severity": null,
      "tag": "dup-test",
      "file": "src/i18n/__tests__/catalogKeys.test.js",
      "line": 24,
      "claim": "For en, the ADDED list and its per-locale test repeat the literal-key test. All four keys are literal t() calls that LITERAL_KEY matches (checked), so if one goes missing from en, 'every literal key in the source is in the English catalog' already fails. For es, pt-BR and zh, the test pins four translations chosen only by this ticket's history. No other translation is pinned, and i18next falls back to English when one is missing.",
      "scenario": null,
      "action": "Nothing replaces it. The loop keeps only the 'has no key English lacks' test.",
      "lines_delta": -8,
      "confidence": "medium"
    },
    {
      "id": "S3",
      "severity": null,
      "tag": "delete",
      "file": "src/common/utils.js",
      "line": 31,
      "claim": "formatWebsiteLinkTruncated, the twin of the formatWebsiteLink this PR deletes, has no caller on HEAD or on origin/main. It holds the only JSX and the only merge call in utils.js, so import React (line 3), import { Tooltip } (line 5) and merge in the lodash import (line 8) can go with it. It was dead before this PR, so whether to include it here is the author's call.",
      "scenario": null,
      "action": "Nothing replaces it.",
      "lines_delta": -26,
      "confidence": "medium"
    },
    {
      "id": "S4",
      "severity": null,
      "tag": "delete",
      "file": "src/components/search/ResultConstants.js",
      "line": 27,
      "claim": "Nothing imports HIGHLIGHT_ICON_WHITELISTED_FILEDS, on HEAD or on origin/main. It is dead code in the file this PR trims down to the concept columns. It holds no i18n keys, though, so it is outside the ticket's scope.",
      "scenario": null,
      "action": "Nothing replaces it.",
      "lines_delta": -9,
      "confidence": "low"
    }
  ]
}

…ist the sources with readdirSync, and drop the per-locale test of the four keys

S1: readdirSync(SRC_DIR, { recursive: true }) replaces the hand-written
walker in catalogKeys.test.js. It lists the same 171 files.

S2: the per-locale test of the four added keys goes. For English, the
literal-key test already fails if one of them is missing. In the other
locales it pinned four translations when no other translation is pinned,
and a missing translation falls back to English.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8452pAtpyMrv7QRKXbUsj
@paynejd

paynejd commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

Response to the simplification review

@paynejd paynejd left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Codex check of the cuts (commit 4f2332d)

Clean.

findings.json
{
  "reviewer": "codex-cli 0.163.0",
  "perspective": "defects",
  "mode": "cuts",
  "commit": "4f2332d",
  "verdict": "clean",
  "prior": [],
  "findings": []
}

@paynejd
paynejd marked this pull request as ready for review October 17, 2026 19:30
@paynejd
paynejd merged commit 5e304f1 into main Oct 18, 2026
2 checks passed
@paynejd
paynejd deleted the OpenConceptLab/ocl_issues#2917-i18n-key-cleanup branch October 18, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

origin/ai-generated Issue or PR created by an AI agent origin/session-worker Opened by the Octoad session worker; a run record backs it

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OCL Mapper: remove unused i18n keys, and add the 4 English keys the code uses

1 participant