Skip to content

feat: chrome translation Tier 1 — Home + Breathe + badges (ja/zh-Hans/zh-Hant) - #40

Merged
TrainTravel merged 1 commit into
mainfrom
feat/chrome-translation-tier1
May 26, 2026
Merged

feat: chrome translation Tier 1 — Home + Breathe + badges (ja/zh-Hans/zh-Hant)#40
TrainTravel merged 1 commit into
mainfrom
feat/chrome-translation-tier1

Conversation

@TrainTravel

Copy link
Copy Markdown
Owner

Summary

First tier of the chrome translation pass. Adds Japanese, Simplified Chinese, and Traditional Chinese keys to the highest-visibility t() and bilingual() call sites — Home screen, Breathe screen, and the BADGES constant.

Pairs with #39 (bilingual dedupe). Together they fix the visible "Write today / Write today" rendering for users with target=ja and primary=zh-Hant. With both PRs merged, a Japanese learner who speaks Chinese sees natural CJK chrome on Home instead of duplicated English.

Scope

~40 calls × 3 langs = ~120 new translation keys, across:

  • HomeScreen.tsx — sign-out, hero subtitle, "Completed" badge, word counter (×2), badge tooltips, "More tools" toggle, secondary action bilingual() anchors (Brain Dump, Thought Garden, Free Write, One Thing at a Time, ABC List, Small Wins, Tiny Experiments, Zen Garden, Sand Timer), Emotion vocabulary card, "One or two sentences is enough." tagline
  • BreatheScreen.tsx — Back, three breathing phases (inhale / hold / exhale), grounding prompt, "I'm ready" CTA
  • BADGES constant + Badge type — extended with optional ja, zh-Hans, zh-Hant; all 6 badges translated (新芽, 書き手, あなたの声, 語り手, 庭師, 賢者)

Why tiered

A "full sweep" would be ~350 sites × 3 = ~1000 strings of unreviewed AI translation. That's 100× the surface area of the Japanese prompts in PR #36 that already need native review. Tier 1 covers the 80% of visual weight without committing 1000 strings; Tier 2 + Tier 3 ship after Tier 1 has had a native pass.

Test plan

  • npx tsc --noEmit — clean
  • npx vitest run — 188 passed / 189 (only pre-existing useJournal startFreeWrite fails)
  • All existing bilingual() tests still pass (the new keys don't break the dedupe behavior shipped in feat: dedupe bilingual() identical sides + add CTA ja/zh translations #39 — Tier 1 strings differ across target/primary, so dedupe doesn't trigger for them)
  • Manual on a real device: open Home with target=ja primary=en → all chrome reads naturally in Japanese where translated
  • Manual: open Home with target=fr primary=zh-Hant → primary side shows Chinese, target shows French (bilingual() pair where both sides have translations)
  • Manual: BreatheScreen with target=ja → phase prompts read 息を吸って... / 息を止めて... / 息を吐いて...

Known follow-ups (called out in CHANGELOG)

  • "French journaling practice" hero subtitle is hardcoded. It translates literally but is semantically wrong for non-French targets (a Japanese learner sees "Japanese journaling practice → フランス語日記の練習"). Future PR makes it target-aware.
  • Word counter splits on /\s+/ — produces unreliable counts for Japanese / Chinese. Counter logic itself needs a separate fix (probably a graphemes-based or character-based count for CJK targets).
  • Native review of the Japanese and Chinese strings shipped here is still planned. Same path as for the Japanese prompts in PR feat: Japanese target language + edge function consolidation #36 — iTalki / r/translator. The copy-paste consensus-check template from earlier sessions still applies.

Out of scope (Tier 2 / Tier 3)

  • WriteScreen, EmotionsScreen, ReflectionScreen, GratitudeScreen, FeedbackScreen
  • BrainDumpScreen body, ThoughtGardenScreen interior, ProgressScreen
  • LanguageSettings / Account / Font / Theme picker chrome
  • Anything in src/components/ui (shadcn primitives)
  • Error messages / edge-case toasts

🤖 Generated with Claude Code

…/zh-Hant)

First pass of CJK translations on the highest-visibility chrome.
Pairs with PR #39's bilingual() dedupe — together they fix the
"Write today / Write today" rendering when target=ja primary=zh-*.

~40 calls × 3 langs = ~120 new translation keys across:

- HomeScreen: sign-out, hero subtitle, "Completed" badge, word
  counter, badge tooltips, "More tools" toggle, secondary action
  bilingual() anchors (Brain Dump, Thought Garden, Free Write,
  One Thing at a Time, ABC List, Small Wins, Tiny Experiments,
  Zen Garden, Sand Timer), Emotion vocabulary card, tagline.
- BreatheScreen: Back button, 3 breathing phases, grounding
  prompt, "I'm ready" CTA.
- BADGES constant: Badge type extended with optional ja /
  zh-Hans / zh-Hant; all 6 badges (Seedling → Sage) translated.

Tier 2 and Tier 3 are explicitly deferred — would be ~1000
strings of unreviewed AI translation otherwise. The tiered plan
gives 80% visual weight while keeping the unreviewed surface
small enough for a single native-speaker review pass.

Known follow-ups (called out in CHANGELOG):
- "French journaling practice" hero subtitle is hardcoded —
  semantically wrong for non-French targets, future PR
- Word counter splits on /\s+/, unreliable for CJK
- Native review of these CJK strings still planned

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@TrainTravel
TrainTravel merged commit 509a9e9 into main May 26, 2026
1 check failed
TrainTravel added a commit that referenced this pull request May 27, 2026
Documents the register and structure conventions established
across PRs #40-#48 so future Claude sessions and subagents
auto-load the same rules. Covers:

- Japanese register (polite です・ます, no keigo, no あなた pronoun)
- Chinese S/T character splits (with a verified non-exhaustive list)
- Dynamic-language-name strings (LANGUAGE_NAMES helper, not literal)
- Fallback policy (optional keys + dev-mode warning)
- Native review queue (AI drafts ≠ final)
- PR scope discipline (≤ 8 files, ≤ 200 lines, cherry-pick large sweeps)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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