Skip to content

Translation fixes#501

Merged
cleech merged 9 commits intopreview-srcfrom
translation-fixes
Mar 30, 2026
Merged

Translation fixes#501
cleech merged 9 commits intopreview-srcfrom
translation-fixes

Conversation

@cleech
Copy link
Copy Markdown
Owner

@cleech cleech commented Mar 30, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Corrected aura formatting in card descriptions across multiple playbook versions for consistency.
    • Fixed text spacing and formatting in Spanish character ability descriptions.
  • Style

    • Updated application theme colors for improved visual appearance.
    • Enhanced typography and spacing for Chinese and Spanish language content.
  • Chores

    • Updated dependency tooling and manifest metadata.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 96d24a6a-1c30-4565-ab61-e164051366eb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch translation-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cleech cleech force-pushed the translation-fixes branch from e1a7e22 to 318d5c7 Compare March 30, 2026 23:21
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
src/pages/App.tsx (1)

60-61: Consider removing long commented-out style variants.

Keeping deprecated color options and the disabled &::before block inline adds noise and makes future theme edits harder to scan.

♻️ Optional cleanup
     primary: {
       main: "#4e91ba",
-      // main: "#ba9d4e",
-      // main: "#5578a6",
     },
@@
         body: {
-          // need this hackery to allow nested backdrop-filters ...
-          // '&::before': {
-          //   content: "''",
-          //   position: "absolute",
-          //   width: "100%",
-          //   height: "100%",
-          //   backdropFilter: "blur(20px)",
-          //   zIndex: -99,
-          // },
           // overflow: "hidden",

Also applies to: 76-83

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/App.tsx` around lines 60 - 61, Remove the long commented-out style
variants to reduce visual noise in App.tsx: delete the commented color lines
like the alternate "main" values (e.g., // main: "#ba9d4e", // main: "#5578a6")
and the disabled &::before block, or if you want to preserve them, move them
into a single clearly named fallback/legacy-theme constant (e.g.,
LEGACY_THEME_VARIANTS) or a short note in a changelog instead of inline
comments; update any references in the theme-building code (the theme/variant
creation logic in App.tsx) to use the live values only.
vite.config.ts (1)

6-7: Consider removing commented-out code or adding clarifying comments.

Leaving the Cloudflare plugin import and invocation commented out rather than removed suggests this may be for easy toggling between configurations. If intentional, consider adding a brief comment explaining when to use each plugin (e.g., // Use cloudflare() for production preview, basicSsl() for local dev).

Also verify that commenting out cloudflare() doesn't affect production deployment, since wrangler deploy is still in package.json scripts and @cloudflare/vite-plugin remains in devDependencies.

Also applies to: 23-24

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vite.config.ts` around lines 6 - 7, The commented-out import and usage of
cloudflare (the symbol "cloudflare") next to the active import of basicSsl (the
symbol "basicSsl") should either be removed or annotated: either delete the
commented import/invocation to avoid stale code, or add a short clarifying
comment above them (e.g., when to use cloudflare() vs basicSsl() for prod
preview vs local dev) so future readers know it's intentional; also scan the
"wrangler deploy" usage in package.json and devDependencies to ensure keeping
the commented cloudflare() won't cause confusion for production deployment and
update package.json or comments accordingly.
src/utils/handlebars.ts (2)

34-54: Consider extracting shared logic between trait and play helpers.

Both helpers have nearly identical structure: db validation, document lookup, qualifier extraction, depth-based resolution, and SafeString formatting. A shared utility function could reduce duplication.

♻️ Example extraction
async function lookupAndFormat(
  context: HelperContext | undefined,
  collection: 'character_traits' | 'character_plays',
  name: string,
  rest: unknown[]
): Promise<string | Handlebars.SafeString> {
  const db = context?.db;
  if (!db) {
    console.error(`Database not provided for ${collection} lookup: ${name}`);
    return "";
  }
  const doc = await db[collection].findOne(name).exec();
  const item = doc?.toJSON();
  if (!item) {
    console.error(`can not find ${collection.replace('character_', '')} ${name}`);
    return "";
  }
  const qualifier = (rest.length > 1) ? rest[0] as string : undefined;
  const depth = context?.depth || 1;
  const text = depth === 1 ? await resolveText(item.text, db, 2) : item.text;
  return new hb.SafeString(`(_${item.name}${qualifier ? ` [${qualifier}]` : ''}: ${text}_)`);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/handlebars.ts` around lines 34 - 54, Extract the duplicated logic
in the "play" and "trait" helpers into a shared async utility (e.g.,
lookupAndFormat) that accepts (context: HelperContext | undefined,
collectionName: 'character_traits' | 'character_plays', name: string, rest:
unknown[]) and performs db presence check (this?.db), document lookup via
db[collectionName].findOne(name).exec(), doc->toJSON(), qualifier extraction
((rest.length > 1) ? rest[0] as string : undefined), depth resolution
(context?.depth || 1) and conditional text resolution via resolveText when depth
=== 1; have the helper functions (play and trait) call this utility and return
the resulting Handlebars.SafeString so you can remove the duplicated blocks that
reference db.character_plays, play.text, play.name, hb.SafeString and similar
code in the trait helper.

18-18: Simplify by removing redundant .then() after await.

Mixing await and .then() is unnecessarily verbose here.

♻️ Suggested simplification
-  const trait = await db.character_traits.findOne(name).exec().then(doc => doc?.toJSON());
+  const doc = await db.character_traits.findOne(name).exec();
+  const trait = doc?.toJSON();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/handlebars.ts` at line 18, The line that assigns trait mixes await
with .then unnecessarily; change the expression so you await the promise
returned by db.character_traits.findOne(name).exec() and then call .toJSON() on
the result (e.g. const doc = await db.character_traits.findOne(name).exec();
const trait = doc?.toJSON();), updating the variable located where trait is
assigned and keeping references to db.character_traits.findOne, exec, and
toJSON.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/data/GB-Playbook-4-8.es.json`:
- Line 12959: Update the Spanish text entry in GB-Playbook-4-8.es.json that
currently reads "terminen su activación" to use the plural form "terminen sus
activaciones" for consistency with adjacent entries; locate the JSON object
whose "text" value contains "Coloca un AOE duradero dentro del alcance. Los
modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que
entren o terminen su activación dentro de este AOE duradero reciben la condición
de Burning." and replace that substring accordingly, preserving the rest of the
sentence and punctuation.

In `@src/components/CardQuirks.css`:
- Around line 178-181: The CSS rule blocks for the selector ".ColdSnap .text"
(and the similar blocks at the other occurrences) are triggering stylelint's
declaration-empty-line-before; fix by inserting a blank line before the
declaration lines inside those blocks so each property (e.g., "letter-spacing:
normal;" for "::first-line" and "letter-spacing: -0.5px;") is preceded by an
empty line, ensuring consistent formatting and satisfying the linter (adjust the
same change for the occurrences around the other selectors referenced).

In `@src/components/Gameplan.tsx`:
- Around line 125-135: The CardText markdown pipeline currently uses rehypeRaw
without sanitization; update src/components/CardUtils.tsx by importing
rehypeSanitize from 'rehype-sanitize' and adding it to the rehypePlugins array
used by the CardText renderer (alongside rehypeRaw) so raw HTML in gameplan.text
and gameplan.detail is sanitized before rendering, ensuring the CardText
component's pipeline (rehypePlugins, rehypeRaw) includes rehypeSanitize.

In `@src/utils/handlebars.ts`:
- Around line 61-65: Update the resolveText function signature to use the
concrete GBDatabase type instead of unknown: change the parameter declaration in
resolveText(db: unknown) to db: GBDatabase to match the existing HelperContext
and helper usage, and ensure the call sites provide a GBDatabase instance; the
body can remain the same (using hb.compile and template({ db, depth })), and
consider adding a note/comment to cache compiled templates if repeated
compilation becomes a performance concern.

---

Nitpick comments:
In `@src/pages/App.tsx`:
- Around line 60-61: Remove the long commented-out style variants to reduce
visual noise in App.tsx: delete the commented color lines like the alternate
"main" values (e.g., // main: "#ba9d4e", // main: "#5578a6") and the disabled
&::before block, or if you want to preserve them, move them into a single
clearly named fallback/legacy-theme constant (e.g., LEGACY_THEME_VARIANTS) or a
short note in a changelog instead of inline comments; update any references in
the theme-building code (the theme/variant creation logic in App.tsx) to use the
live values only.

In `@src/utils/handlebars.ts`:
- Around line 34-54: Extract the duplicated logic in the "play" and "trait"
helpers into a shared async utility (e.g., lookupAndFormat) that accepts
(context: HelperContext | undefined, collectionName: 'character_traits' |
'character_plays', name: string, rest: unknown[]) and performs db presence check
(this?.db), document lookup via db[collectionName].findOne(name).exec(),
doc->toJSON(), qualifier extraction ((rest.length > 1) ? rest[0] as string :
undefined), depth resolution (context?.depth || 1) and conditional text
resolution via resolveText when depth === 1; have the helper functions (play and
trait) call this utility and return the resulting Handlebars.SafeString so you
can remove the duplicated blocks that reference db.character_plays, play.text,
play.name, hb.SafeString and similar code in the trait helper.
- Line 18: The line that assigns trait mixes await with .then unnecessarily;
change the expression so you await the promise returned by
db.character_traits.findOne(name).exec() and then call .toJSON() on the result
(e.g. const doc = await db.character_traits.findOne(name).exec(); const trait =
doc?.toJSON();), updating the variable located where trait is assigned and
keeping references to db.character_traits.findOne, exec, and toJSON.

In `@vite.config.ts`:
- Around line 6-7: The commented-out import and usage of cloudflare (the symbol
"cloudflare") next to the active import of basicSsl (the symbol "basicSsl")
should either be removed or annotated: either delete the commented
import/invocation to avoid stale code, or add a short clarifying comment above
them (e.g., when to use cloudflare() vs basicSsl() for prod preview vs local
dev) so future readers know it's intentional; also scan the "wrangler deploy"
usage in package.json and devDependencies to ensure keeping the commented
cloudflare() won't cause confusion for production deployment and update
package.json or comments accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dfdc3f48-7aac-47fd-807e-32163f469150

📥 Commits

Reviewing files that changed from the base of the PR and between d2f6c9d and 318d5c7.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • package.json
  • public/data/GB-Playbook-4-3.json
  • public/data/GB-Playbook-4-4.json
  • public/data/GB-Playbook-4-5.json
  • public/data/GB-Playbook-4-6.fr.json
  • public/data/GB-Playbook-4-6.json
  • public/data/GB-Playbook-4-7.fr.json
  • public/data/GB-Playbook-4-7.json
  • public/data/GB-Playbook-4-7.zh.json
  • public/data/GB-Playbook-4-8.es.json
  • public/data/GB-Playbook-4-8.fr.json
  • public/data/GB-Playbook-4-8.json
  • public/data/GB-Playbook-4-8.zh.json
  • public/data/manifest.json
  • public/data/manifest.yaml
  • scripts/check.ts
  • src/components/CardFront.css
  • src/components/CardQuirks.css
  • src/components/CardUtils.tsx
  • src/components/Gameplan.tsx
  • src/models/gbdbTypes.ts
  • src/pages/App.tsx
  • src/pages/GamePlay/components/RosterList.tsx
  • src/utils/handlebars.ts
  • vite.config.ts

{
"name": "Chilli Cook Out",
"text": "Coloca un AOE duradero dentro del alcance.\nLos modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que entren o terminen su activación dentro de este AOE duradero reciben la condición de Burning.",
"text": "Coloca un AOE duradero dentro del alcance. Los modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que entren o terminen su activación dentro de este AOE duradero reciben la condición de Burning.",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use plural form for consistency in activation wording.

Line 12959 uses “terminen su activación”, while adjacent entries consistently use “terminen sus activaciones”. Consider aligning to the plural form for translation consistency.

✏️ Suggested wording tweak
-      "text": "Coloca un AOE duradero dentro del alcance. Los modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que entren o terminen su activación dentro de este AOE duradero reciben la condición de Burning.",
+      "text": "Coloca un AOE duradero dentro del alcance. Los modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que entren o terminen sus activaciones dentro de este AOE duradero reciben la condición de Burning.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"text": "Coloca un AOE duradero dentro del alcance. Los modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que entren o terminen su activación dentro de este AOE duradero reciben la condición de Burning.",
"text": "Coloca un AOE duradero dentro del alcance. Los modelos impactados reciben 4 DAÑO y la condición de Burning. Los modelos que entren o terminen sus activaciones dentro de este AOE duradero reciben la condición de Burning.",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/data/GB-Playbook-4-8.es.json` at line 12959, Update the Spanish text
entry in GB-Playbook-4-8.es.json that currently reads "terminen su activación"
to use the plural form "terminen sus activaciones" for consistency with adjacent
entries; locate the JSON object whose "text" value contains "Coloca un AOE
duradero dentro del alcance. Los modelos impactados reciben 4 DAÑO y la
condición de Burning. Los modelos que entren o terminen su activación dentro de
este AOE duradero reciben la condición de Burning." and replace that substring
accordingly, preserving the rest of the sentence and punctuation.

Comment on lines +178 to +181
& .ColdSnap .text {
& ::first-line { letter-spacing: normal; }
letter-spacing: -0.5px;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Minor: Stylelint expects empty lines before these declarations.

The linter flags declaration-empty-line-before violations. While purely cosmetic, fixing them maintains consistent formatting.

🔧 Proposed fix
   & .ColdSnap .text {
     & ::first-line { letter-spacing: normal; }
+
     letter-spacing: -0.5px;
   }
   & .FlareOut .text {
     & ::first-line { letter-spacing: normal; }
+
     letter-spacing: -0.7px;
   }
   & .Reconnaissance .text {
     & ::first-line { letter-spacing: normal; }
+
     letter-spacing: -0.8px;
   }

Also applies to: 201-204, 225-228

🧰 Tools
🪛 Stylelint (17.5.0)

[error] 180-180: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/CardQuirks.css` around lines 178 - 181, The CSS rule blocks
for the selector ".ColdSnap .text" (and the similar blocks at the other
occurrences) are triggering stylelint's declaration-empty-line-before; fix by
inserting a blank line before the declaration lines inside those blocks so each
property (e.g., "letter-spacing: normal;" for "::first-line" and
"letter-spacing: -0.5px;") is preceded by an empty line, ensuring consistent
formatting and satisfying the linter (adjust the same change for the occurrences
around the other selectors referenced).

Comment on lines +125 to +135
<CardText>
{gameplan.text}
</Markdown>
</CardText>
</div>
<div
className='detail'
id={gameplan.title.replace(/[^a-zA-Z0-9]+/g, '')}
>
<Markdown>
<CardText>
{gameplan.detail ? `(_${gameplan.detail}_)` : undefined}
</Markdown>
</CardText>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Checking CardText markdown pipeline configuration..."
fd -i "CardUtils.tsx" src --exec rg -n -C3 "CardText|rehypeRaw|rehype-sanitize|remarkGBIcons|react-markdown|Markdown"

echo
echo "Checking where gameplan/translations content is sourced..."
rg -n -C2 "manifest|translation|translations|gameplan|fetch\\(" src public

Repository: cleech/GBPlaybook

Length of output: 27176


Add rehype-sanitize to the CardText markdown pipeline in src/components/CardUtils.tsx.

The CardText component uses rehypeRaw without rehype-sanitize, which permits raw HTML rendering from gameplan data without sanitization. Since gameplan content (text and detail) is loaded from JSON files and rendered through this pipeline, malicious or compromised data could execute scripts. Import and add rehype-sanitize to the rehypePlugins array.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Gameplan.tsx` around lines 125 - 135, The CardText markdown
pipeline currently uses rehypeRaw without sanitization; update
src/components/CardUtils.tsx by importing rehypeSanitize from 'rehype-sanitize'
and adding it to the rehypePlugins array used by the CardText renderer
(alongside rehypeRaw) so raw HTML in gameplan.text and gameplan.detail is
sanitized before rendering, ensuring the CardText component's pipeline
(rehypePlugins, rehypeRaw) includes rehypeSanitize.

Comment on lines +61 to +65
export async function resolveText(text: string | undefined, db: unknown, depth: number = 1): Promise<string> {
if (!text) return "";
const template = hb.compile(text);
return await template({ db, depth });
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there would be circular import issues with GBDatabase type
rg -l "from.*handlebars" --type=ts
rg "import.*resolveText" --type=ts -C2

Repository: cleech/GBPlaybook

Length of output: 350


🏁 Script executed:

# Check all imports in handlebars.ts
cat -n src/utils/handlebars.ts | head -20

Repository: cleech/GBPlaybook

Length of output: 845


🏁 Script executed:

# Check if GBDatabase is defined in gbdbTypes.ts
rg "export.*interface.*GBDatabase|export.*type.*GBDatabase|export.*class.*GBDatabase" src/models/gbdbTypes.ts

Repository: cleech/GBPlaybook

Length of output: 116


🏁 Script executed:

# Check all imports from gbdbTypes in the codebase
rg "import.*GBDatabase" --type=ts

Repository: cleech/GBPlaybook

Length of output: 1213


🏁 Script executed:

# Check how db parameter is actually used in the file
rg -A20 "export async function resolveText" src/utils/handlebars.ts

Repository: cleech/GBPlaybook

Length of output: 294


Change db: unknown to db: GBDatabase — it's already imported.

The GBDatabase type is already available in this file (line 3). The HelperContext interface within the same file explicitly expects db: GBDatabase (line 8), and the template helpers receive the db parameter through the context object. Using the proper type here removes unnecessary type widening and improves safety.

If repeated template compilation becomes a performance concern, consider caching compiled templates.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/handlebars.ts` around lines 61 - 65, Update the resolveText
function signature to use the concrete GBDatabase type instead of unknown:
change the parameter declaration in resolveText(db: unknown) to db: GBDatabase
to match the existing HelperContext and helper usage, and ensure the call sites
provide a GBDatabase instance; the body can remain the same (using hb.compile
and template({ db, depth })), and consider adding a note/comment to cache
compiled templates if repeated compilation becomes a performance concern.

@cleech cleech merged commit bfd65b5 into preview-src Mar 30, 2026
2 checks passed
@cleech cleech deleted the translation-fixes branch March 30, 2026 23:54
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.

1 participant