Skip to content

Translate course content and error messages to Traditional Chinese; a…#14

Merged
Retsomm merged 2 commits into
mainfrom
dev
May 21, 2026
Merged

Translate course content and error messages to Traditional Chinese; a…#14
Retsomm merged 2 commits into
mainfrom
dev

Conversation

@Retsomm
Copy link
Copy Markdown
Owner

@Retsomm Retsomm commented May 21, 2026

…dd new lessons for Chinese, English, French, Japanese, Korean, and Spanish; implement shared lesson creation logic.

Summary by CodeRabbit

  • New Features

    • Fully implemented Profile screen with avatar, language display, change-language flow, and sign-out.
  • New Content

    • Added beginner lesson sets for Spanish, French, Japanese, Korean, Chinese, and English.
  • Localization

    • App UI strings translated to Traditional Chinese across screens, navigation, and controls.
    • AI teacher now defaults to Taiwan Mandarin for voice/instructions.
  • Improvements

    • Default app language switched from Spanish to Chinese.

Review Change Stack

…dd new lessons for Chinese, English, French, Japanese, Korean, and Spanish; implement shared lesson creation logic.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aaf8c9d1-a999-4562-8b02-e556d884f322

📥 Commits

Reviewing files that changed from the base of the PR and between 315fb68 and 591be73.

📒 Files selected for processing (5)
  • app/(tabs)/ai-teacher.tsx
  • app/lesson/[lessonId].tsx
  • components/audio-teacher-session.tsx
  • data/course-lessons/shared.ts
  • vision-agent/agent.py

📝 Walkthrough

Walkthrough

This PR localizes UI strings to Traditional Chinese, implements a full Profile screen, modularizes lesson data into per-language files via a shared createLesson factory, refactors lessons aggregation, and updates vision-agent prompts to Taiwan Mandarin.

Changes

Comprehensive Localization & Lesson Data Restructuring

Layer / File(s) Summary
Tab Navigation & Core Screen Localization
app/(tabs)/_layout.tsx, app/(tabs)/chat.tsx, app/(tabs)/home.tsx, app/(tabs)/learn.tsx, app/onboarding.tsx, app/lesson/[lessonId].tsx
Tab titles, onboarding headline/CTA, lesson detail fallback UI, home greeting/notifications/daily plan, learn tab labels and practice card text all translated to Chinese. Default user name fallback changed from "Learner" to "學習者".
Profile Screen Implementation with Auth & Language Store
app/(tabs)/profile.tsx
Placeholder converted to full implementation: integrates Clerk auth, reads selected language from language store, computes user initials via new getInitials helper, renders avatar (image or initials), displays current language with flag/native name/description, provides language-change and sign-out buttons, and includes stylesheet with shadow and pressed-state styling.
Language Selection & Authentication Localization
app/LanguageSelection.tsx, components/auth-screen.tsx
Language selection UI (back button, search placeholder, empty-state, confirmation text) and auth screen (sign-up/sign-in labels, email/password fields, validation messages, social provider buttons, verification modal) all translated to Chinese.
Component & Bottom Tab Bar Localization
components/bottom-tab-bar.tsx, components/lesson-card.tsx
Tab labels and lesson card status copy (completed/in-progress/not-started) and lesson number formatting (第 {number} 課) updated to Chinese. Accessibility labels localized.
Audio Teacher Session Text & Tab Routing
components/audio-teacher-session.tsx
Feedback metrics, tab labels, status messages, prompts localized to Chinese. Component API switched to route-based active tab (activeTabRoute) and LessonTabBar active-state now compares item.route === activeTabRoute. Audio call status and agent connection state messages fully localized to Chinese.
Backend API Error Message Localization
app/api/stream/audio-call+api.ts, app/api/vision-agent/session+api.ts, app/api/vision-agent/captions+api.ts, hooks/useStreamAudioCall.ts
Error messages and default fallback strings in Stream audio call creation, vision-agent session start/stop, caption loading, and audio hook lifecycle events updated to Chinese and Japanese where appropriate.
Lesson Data Factory
data/course-lessons/shared.ts
New module introducing LessonSeed type and createLesson(languageId, unitId, seed) factory function that generates structured lessons with vocabulary items (with IDs), phrases, three deterministic activities, XP rewards, and Taiwan Mandarin aiTeacherPrompt template.
Per-Language Lesson Modules
data/course-lessons/spanish.ts, data/course-lessons/french.ts, data/course-lessons/chinese.ts, data/course-lessons/english.ts, data/course-lessons/japanese.ts, data/course-lessons/korean.ts
Six modular lesson files export Lesson[] arrays created via createLesson factory, each with language-specific languageId/unitId and six lessons covering greeting, daily life, café, travel, shopping, and family topics.
Lesson Aggregation & Language Defaults
data/lessons.ts, data/units.ts, data/languages.ts
lessons.ts refactored from inline generation to aggregation of per-language lesson arrays. units.ts descriptions localized to Chinese for all six language units. defaultLanguageId changed from "spanish" to "chinese". languages array fields (name, nativeName, learnerCount, description) localized to Chinese.
Vision Agent Taiwan Mandarin Teaching
vision-agent/agent.py, vision-agent/README.md
Added USER_LANGUAGE = "台灣國語". Updated teacher instruction prompts and join_call opening prompts to Taiwan Mandarin (Traditional Chinese) and set agent display name to "Lingua AI 老師". README updated accordingly.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Retsomm/react-native-lingua#11: Modifies vision agent opening_prompt logic in join_call, related to Taiwan Mandarin opening prompt updates.
  • Retsomm/react-native-lingua#9: Introduced unit/lesson UI and AudioTeacherSession tab plumbing that this PR adjusts (route-based active tab).
  • Retsomm/react-native-lingua#5: Related changes to data/languages.ts and default language handling that overlap with this PR's language defaults/locale fields.

Poem

🐰 I nibbled through strings, from English to 中,
Tabs and lessons now hum in 台灣話。
A profile blooms, lessons neatly spun,
The teacher greets in Mandarin sun—
Hop, learn, repeat—the rabbit says 胜利!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Translate course content and error messages to Traditional Chinese; a...' is truncated and only partially describes the full scope of changes. While translation is a main component, the PR also adds lesson data for multiple languages and implements shared lesson creation logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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

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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/api/stream/audio-call+api.ts (1)

1-1: ⚠️ Potential issue | 🔴 Critical

Fix lint/typecheck failures before finishing this change (gates currently fail)

  • npm run lint fails (41 errors), including app/api/stream/audio-call+api.ts import @stream-io/node-sdk (import/no-unresolved).
  • npm run typecheck fails with TS2307 for app/api/stream/audio-call+api.ts (@stream-io/node-sdk) and many additional TS errors (e.g., TS7006 implicit any, missing type declarations) across the repo.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/api/stream/audio-call`+api.ts at line 1, The import of StreamClient from
'`@stream-io/node-sdk`' is unresolved and causing lint/typecheck failures; fix by
replacing or installing the correct SDK package and types (e.g., install the
official Stream Node SDK package that exports StreamClient or update the import
to the correct module name), add or install corresponding `@types` if needed, and
annotate any implicit- any variables used with StreamClient so TS no longer
reports TS7006 (search for StreamClient usage in this module). Also ensure
ESLint import resolver is configured or update the import to a path the resolver
recognizes, then run npm run lint and npm run typecheck and address remaining
missing type declarations across functions referenced in this diff until both
pass.
🧹 Nitpick comments (2)
vision-agent/agent.py (1)

369-383: ⚡ Quick win

Use USER_LANGUAGE in opening prompts to avoid config drift.

These prompts hardcode 台灣國語 instead of reusing the module constant.

Proposed refactor
-        "請用台灣國語溫暖地問候學習者,語氣自然、有精神、專注。"
+        f"請用{USER_LANGUAGE}溫暖地問候學習者,語氣自然、有精神、專注。"
...
-            "現在請用台灣國語,以這堂課的 AI 老師身分溫暖問候學習者。"
+            f"現在請用{USER_LANGUAGE},以這堂課的 AI 老師身分溫暖問候學習者。"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vision-agent/agent.py` around lines 369 - 383, The opening_prompt and the
earlier prompt strings currently hardcode "台灣國語"; change them to use the module
constant USER_LANGUAGE instead so config changes propagate. Locate the block
that sets opening_prompt (and any nearby literal prompt strings used when
custom_data is present) and replace the hardcoded language with USER_LANGUAGE,
preserving the rest of the text and concatenation and keeping calls to
build_teacher_instructions(custom=custom_data) and
apply_agent_instructions(agent, lesson_instructions) unchanged.
components/audio-teacher-session.tsx (1)

50-52: ⚡ Quick win

Switch tab state prop from label-based to route-based.

activeTabLabel is still an English-label union while tab behavior is now route-driven. This keeps an unnecessary i18n coupling. Prefer an activeTabRoute: "/ai-teacher" | "/learn" (or Href) prop and compare directly.

Proposed refactor
 type AudioTeacherSessionProps = {
-  activeTabLabel?: "AI Teacher" | "Learn";
+  activeTabRoute?: "/ai-teacher" | "/learn";
   autoStartCall?: boolean;
   lesson?: Lesson;
   onCallEnded?: () => void;
   showEmbeddedTabBar?: boolean;
 };

 export function AudioTeacherSession({
-  activeTabLabel = "AI Teacher",
+  activeTabRoute = "/ai-teacher",
   autoStartCall = false,
   lesson,
   onCallEnded,
   showEmbeddedTabBar = false,
 }: AudioTeacherSessionProps) {
   ...
   return (
     <AudioTeacherSessionContent
-      activeTabLabel={activeTabLabel}
+      activeTabRoute={activeTabRoute}
       ...
     />
   );
 }

 type AudioTeacherSessionContentProps = {
-  activeTabLabel: "AI Teacher" | "Learn";
+  activeTabRoute: "/ai-teacher" | "/learn";
   ...
 };

 function AudioTeacherSessionContent({
-  activeTabLabel,
+  activeTabRoute,
   ...
 }: AudioTeacherSessionContentProps) {
   ...
-  {showEmbeddedTabBar ? <LessonTabBar activeTabLabel={activeTabLabel} /> : null}
+  {showEmbeddedTabBar ? <LessonTabBar activeTabRoute={activeTabRoute} /> : null}
 }

 type LessonTabBarProps = {
-  activeTabLabel: "AI Teacher" | "Learn";
+  activeTabRoute: "/ai-teacher" | "/learn";
 };

-function LessonTabBar({ activeTabLabel }: LessonTabBarProps) {
+function LessonTabBar({ activeTabRoute }: LessonTabBarProps) {
   const insets = useSafeAreaInsets();
-  const activeRoute = activeTabLabel === "AI Teacher" ? "/ai-teacher" : "/learn";

   return (
     ...
-          const isActive = item.route === activeRoute;
+          const isActive = item.route === activeTabRoute;

Also applies to: 100-101, 761-768

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/audio-teacher-session.tsx` around lines 50 - 52, Replace the
label-based prop with a route-based prop: change AudioTeacherSessionProps to use
activeTabRoute: "/ai-teacher" | "/learn" (or Href) instead of activeTabLabel,
update the component prop destructuring and type signature in the
AudioTeacherSession component, and change all internal checks that compare
activeTabLabel (e.g., tab switching logic and conditional rendering) to compare
activeTabRoute against "/ai-teacher" or "/learn" directly; also update any
callers of AudioTeacherSessionProps to pass the new activeTabRoute value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@data/course-lessons/shared.ts`:
- Around line 28-30: The code assumes seed.vocabulary has items and directly
uses seed.vocabulary[0]/[1], which can be undefined and crash createLesson when
building goals/activities; add a guard at the start of createLesson to handle
empty or missing seed.vocabulary (e.g., if (!Array.isArray(seed.vocabulary) ||
seed.vocabulary.length === 0) either throw a clear error or set safe defaults
like primaryVocabulary = [] and secondaryVocabulary = primaryVocabulary) and
replace all direct accesses (primaryVocabulary, secondaryVocabulary and any
later uses in the goal/activity builders) to use these safe values so building
goals/activities (the code blocks referencing
primaryVocabulary/secondaryVocabulary around the goal/activity creation) cannot
dereference undefined.

In `@vision-agent/agent.py`:
- Around line 309-310: The two literals f"除非使用者明確要求換語言,否則不要用英文解釋、寒暄或串場。" and
f"英文、法文、西班牙文、日文、韓文等外語只能出現在本課要練習的目標單字或短句。" are plain strings incorrectly marked
as f-strings (causing Ruff F541); remove the leading f prefix from these string
literals in agent.py (where they appear in the list/sequence) so they become
normal string constants.

---

Outside diff comments:
In `@app/api/stream/audio-call`+api.ts:
- Line 1: The import of StreamClient from '`@stream-io/node-sdk`' is unresolved
and causing lint/typecheck failures; fix by replacing or installing the correct
SDK package and types (e.g., install the official Stream Node SDK package that
exports StreamClient or update the import to the correct module name), add or
install corresponding `@types` if needed, and annotate any implicit- any variables
used with StreamClient so TS no longer reports TS7006 (search for StreamClient
usage in this module). Also ensure ESLint import resolver is configured or
update the import to a path the resolver recognizes, then run npm run lint and
npm run typecheck and address remaining missing type declarations across
functions referenced in this diff until both pass.

---

Nitpick comments:
In `@components/audio-teacher-session.tsx`:
- Around line 50-52: Replace the label-based prop with a route-based prop:
change AudioTeacherSessionProps to use activeTabRoute: "/ai-teacher" | "/learn"
(or Href) instead of activeTabLabel, update the component prop destructuring and
type signature in the AudioTeacherSession component, and change all internal
checks that compare activeTabLabel (e.g., tab switching logic and conditional
rendering) to compare activeTabRoute against "/ai-teacher" or "/learn" directly;
also update any callers of AudioTeacherSessionProps to pass the new
activeTabRoute value.

In `@vision-agent/agent.py`:
- Around line 369-383: The opening_prompt and the earlier prompt strings
currently hardcode "台灣國語"; change them to use the module constant USER_LANGUAGE
instead so config changes propagate. Locate the block that sets opening_prompt
(and any nearby literal prompt strings used when custom_data is present) and
replace the hardcoded language with USER_LANGUAGE, preserving the rest of the
text and concatenation and keeping calls to
build_teacher_instructions(custom=custom_data) and
apply_agent_instructions(agent, lesson_instructions) unchanged.
🪄 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 Plus

Run ID: 0878c903-307a-4d30-bc23-8ada5bd302c6

📥 Commits

Reviewing files that changed from the base of the PR and between 385614e and 315fb68.

📒 Files selected for processing (28)
  • app/(tabs)/_layout.tsx
  • app/(tabs)/chat.tsx
  • app/(tabs)/home.tsx
  • app/(tabs)/learn.tsx
  • app/(tabs)/profile.tsx
  • app/LanguageSelection.tsx
  • app/api/stream/audio-call+api.ts
  • app/api/vision-agent/captions+api.ts
  • app/api/vision-agent/session+api.ts
  • app/lesson/[lessonId].tsx
  • app/onboarding.tsx
  • components/audio-teacher-session.tsx
  • components/auth-screen.tsx
  • components/bottom-tab-bar.tsx
  • components/lesson-card.tsx
  • data/course-lessons/chinese.ts
  • data/course-lessons/english.ts
  • data/course-lessons/french.ts
  • data/course-lessons/japanese.ts
  • data/course-lessons/korean.ts
  • data/course-lessons/shared.ts
  • data/course-lessons/spanish.ts
  • data/languages.ts
  • data/lessons.ts
  • data/units.ts
  • hooks/useStreamAudioCall.ts
  • vision-agent/README.md
  • vision-agent/agent.py

Comment thread data/course-lessons/shared.ts Outdated
Comment thread vision-agent/agent.py Outdated
…ateLesson 函數以確保詞彙項目有效性,並更新教師指示以使用動態語言變數。
@Retsomm Retsomm merged commit fa37b5c into main May 21, 2026
1 check 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.

1 participant