Skip to content

fix(content-translator): translate hasMany text fields per entry#167

Merged
jhb-dev merged 1 commit into
mainfrom
claude/content-translator-hasmany-text-fields
Jun 25, 2026
Merged

fix(content-translator): translate hasMany text fields per entry#167
jhb-dev merged 1 commit into
mainfrom
claude/content-translator-hasmany-text-fields

Conversation

@jhb-dev

@jhb-dev jhb-dev commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

What

hasMany text fields (e.g. keyword/tag lists) store an array of strings. The traversal previously pushed the whole array as a single value to translate, so the resolver received a non-string entry — at best the array got clobbered into one string, at worst it crashed in he.decode(...) with "e.replace is not a function".

Now each element is translated individually. The target is pre-seeded with the originals and each entry is replaced in place as its translation resolves, so a skipped or non-string element keeps its original text.

Tests

test/traverseFields.test.ts:

  • translates each element of a hasMany text field individually;
  • keeps non-string entries in place while translating the rest;
  • does not send the whole array as a single value.

Dev app

Added a localized hasMany keywords field to the dev pages collection (seeded with sample values) so the behavior is clickable in the admin panel.

Notes

Split out from a combined branch; the rich-text marker / index-reconstruction fixes ship separately in #166. Builds on the unnamed-group fix already on main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L4xMrsaXkGmviWmb8MK1hb


Generated by Claude Code

Translate each element of a hasMany text field individually instead of
sending the whole array as one value (which made the resolver return a
non-string and crash in he.decode). Pre-seed the target with the
originals and replace each entry in place as its translation resolves, so
a skipped or non-string element keeps its original text.

Demonstrated via a localized hasMany keywords field on dev pages and
covered by traverseFields tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4xMrsaXkGmviWmb8MK1hb
Comment thread content-translator/src/translate/traverseFields.ts Dismissed

jhb-dev commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

The CodeQL "prototype-polluting assignment" alert on traverseFields.ts:351 (siblingDataTranslated[field.name] = translatedArray) is a false positive. field.name is validated before the switch runs — the loop continues on any field named __proto__/constructor/prototype via the isUnsafeKey guard:

if ('name' in field && isUnsafeKey(field.name)) {
  continue
}

So line 351 is unreachable for a polluting key. This is the same guarded pattern every other siblingDataTranslated[field.name] = … write in the file relies on (including the unchanged string-value write just below it); CodeQL only flagged this line because it's newly added and assigns an array. The guard is covered by the existing traverseFields - prototype pollution tests ("ignores a field named __proto__/constructor/prototype").

Suggest dismissing alert #19 as a false positive — no code change needed.


Generated by Claude Code

@jhb-dev jhb-dev merged commit 0cf1f06 into main Jun 25, 2026
15 checks passed
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.

3 participants