Skip to content

Add zh-TW locale support and fix homepage hydration#1143

Open
Vincent550102 wants to merge 1 commit intof:mainfrom
Vincent550102:codex/zh-tw-i18n-hydration
Open

Add zh-TW locale support and fix homepage hydration#1143
Vincent550102 wants to merge 1 commit intof:mainfrom
Vincent550102:codex/zh-tw-i18n-hydration

Conversation

@Vincent550102
Copy link
Copy Markdown

@Vincent550102 Vincent550102 commented Apr 12, 2026

What changed

  • add zh-TW as a first-class locale while keeping zh as Simplified Chinese
  • centralize locale metadata and locale resolution so language switchers, date locale mapping, browser language detection, and book/kids content all recognize zh-TW
  • add Traditional Chinese translations and localized content for the app UI, book, kids, and printable book assets
  • fix a homepage hydration mismatch in prompt cards by avoiding <pre> for SSR text that can begin with a leading newline

Note: The Traditional Chinese translations in this PR were translated with GPT-5.4.

Why

  • the project now supports a full Traditional Chinese experience instead of mapping all Chinese traffic to zh
  • browsers sending zh-TW, zh-HK, or zh-Hant should land on Traditional Chinese instead of Simplified Chinese
  • the homepage previously hit a recoverable hydration error when prompt content started with a newline because the browser strips the first newline in server-rendered <pre> content

Impact

  • users can switch between 简体中文 and 繁體中文 across the app
  • /book and /kids now load dedicated zh-TW content and printable book assets
  • homepage prompt cards no longer trigger the client-side tree regeneration caused by the hydration mismatch

Validation

  • node scripts/check-translations.js
  • npx vitest run src/__tests__/lib/date.test.ts src/__tests__/lib/i18n-locales.test.ts
  • manually verified Accept-Language: zh-TW and zh-HK render Traditional Chinese pages
  • manually verified /book points to book-zh-TW-print.pdf
  • manually verified the homepage no longer reports the hydration mismatch

Summary by CodeRabbit

  • New Features
    • Added Traditional Chinese (繁體中文) language support throughout the app, complementing existing Simplified Chinese
    • Book content now fully available in Traditional Chinese, including all 25+ chapters and interactive lessons
    • Interactive children's course expanded with Traditional Chinese language content
    • Language switcher now offers both Simplified and Traditional Chinese options
    • Traditional Chinese book PDFs available for download
    • Date formatting and translations now support Traditional Chinese
    • Locale detection automatically routes users to Traditional Chinese when appropriate

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

This PR adds comprehensive Traditional Chinese (zh-TW) locale support throughout the application. Changes include new i18n infrastructure modules for locale resolution and metadata management, configuration updates recognizing zh-TW as a supported locale, refactored components replacing hardcoded language lists with centralized locale metadata, Traditional Chinese UI message strings, complete translated book chapters, and educational content for children.

Changes

Cohort / File(s) Summary
Core i18n Infrastructure
src/lib/i18n/locales.ts, src/lib/i18n/locale-resolution.ts, src/lib/i18n/config.ts, src/lib/i18n/index.ts, src/i18n/request.ts
New modules for locale metadata management and request-based locale resolution; config refactored to import supported locales from centralized source; request module now imports locale detection function instead of implementing inline.
Configuration & Locale Registration
prompts.config.ts, scripts/setup.js, src/lib/date.ts
Added zh-TW to supported locales list in config; extended setup script to offer both simplified (zh) and traditional (zh-TW) Chinese options; added zhTW date-fns locale mapping.
Component Refactoring
src/components/layout/header.tsx, src/components/book/sidebar.tsx, src/components/prompts/language-switcher.tsx, src/components/kids/layout/settings-modal.tsx, src/components/prompts/translate-button.tsx, src/components/prompts/prompt-card.tsx
Replaced hardcoded language arrays with localeMetadata imports; updated dropdown rendering to use label property; integrated getBookPdfLocale for PDF downloads; added zh-TW to translation language mapping.
Book Content Infrastructure
src/components/book/elements/locales/index.ts, src/components/book/elements/locales/zhTw.ts
Registered new zhTw locale module with comprehensive Traditional Chinese content for UI sections, tokens, embeddings, examples, frameworks, and interactive exercises.
Book Pages & Content
src/app/book/page.tsx, src/app/docs/self-hosting/page.tsx
Updated book download to use getBookPdfLocale; made self-hosting docs dynamically render supported locale count and list.
UI Messages
messages/zh-TW.json
Added 2,275 lines of Traditional Chinese UI strings covering navigation, authentication, prompts, settings, admin features, search, notifications, IDE tools, and self-hosting content.
Book Chapters (Traditional Chinese)
src/content/book/zh-TW/*.mdx
Added 25 complete book chapters (00a-24) including preface, history, core principles, role-based prompting, structured output, chain-of-thought, few-shot learning, iterative refinement, JSON/YAML prompting, system prompts, multimodal prompting, context engineering, ethics, optimization, and application domains (writing, programming, education, business, creative arts, research).
Kids Educational Content
src/content/kids/zh-TW/*.mdx
Added 15 interactive lesson pages across 5 worlds teaching prompt engineering fundamentals (clarity, details, context, role-play, optimization) with interactive components for practice.
Tests
src/__tests__/lib/date.test.ts, src/__tests__/lib/i18n-locales.test.ts
Extended date locale tests with zhTW mapping assertion; added comprehensive locale configuration test suite validating metadata, resolution, kids locale filtering, and PDF locale aliasing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • docs: align runtime requirements with current setup #1132 — Modifies i18n for self-hosting docs by adding localized prerequisite strings and refactoring the self-hosting page to use dynamic translations, overlapping with locale infrastructure and self-hosting content changes in this PR.

Poem

🐰 A rabbit hops through locales anew,
From Chinese Simplified to Traditional too!
With infrastructure built and content aligned,
Zh-TW support? Perfectly designed! 🌏✨
The book chapters bloom, the kids learn with glee,
More languages means more users to see!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add zh-TW locale support and fix homepage hydration' directly describes the main change: adding Traditional Chinese locale support and fixing a hydration issue.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@Vincent550102 Vincent550102 marked this pull request as ready for review April 12, 2026 14:52
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: 17

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

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

⚠️ Outside diff range comments (1)
src/components/prompts/translate-button.tsx (1)

11-27: ⚠️ Potential issue | 🟠 Major

Disambiguate zh and complete locale mappings to avoid translation drift.

Line 15 currently maps zh to "Chinese", which is ambiguous now that zh-TW is explicitly supported. Also, nl, az, and fa are supported locales but missing here, so Line 56 falls back to raw locale codes.

💡 Suggested fix
 const localeToLanguage: Record<string, string> = {
   en: "English",
   tr: "Turkish",
   es: "Spanish",
-  zh: "Chinese",
+  zh: "Simplified Chinese",
   "zh-TW": "Traditional Chinese",
   ja: "Japanese",
   ar: "Arabic",
   pt: "Portuguese",
   fr: "French",
   de: "German",
+  nl: "Dutch",
   ko: "Korean",
   it: "Italian",
   ru: "Russian",
   he: "Hebrew",
   el: "Greek",
+  az: "Azerbaijani",
+  fa: "Persian",
 };

Based on learnings: when both Chinese variants are supported, the variant naming must be explicit to avoid ambiguity (zh vs zh-TW).

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

In `@src/components/prompts/translate-button.tsx` around lines 11 - 27, The
localeToLanguage mapping currently leaves "zh" ambiguous and omits supported
locales causing fallbacks; update the localeToLanguage object (symbol:
localeToLanguage) to explicitly map "zh" to "Simplified Chinese" (since "zh-TW"
is already "Traditional Chinese") and add the missing supported locales "nl" ->
"Dutch", "az" -> "Azerbaijani", and "fa" -> "Persian" (or "Farsi") so lookups in
the translate-button component return human-readable names instead of raw locale
codes.
🟡 Minor comments (21)
src/content/book/zh-TW/20-education-learning.mdx-154-155 (1)

154-155: ⚠️ Potential issue | 🟡 Minor

請修正繁體中文用字一致性(歷/曆、週/周)。

這幾行有台灣用字不一致與錯字:曆史 應為 歷史2 周 / 8 周 建議統一為 2 週 / 8 週

✏️ 建議修正
- - 課程:\${course:AP 美國曆史}
- - 截止時間:\${dueIn:2 周}
+ - 課程:\${course:AP 美國歷史}
+ - 截止時間:\${dueIn:2 週}
...
- 距考試時間:\${timeUntilExam:8 周}
+ 距考試時間:\${timeUntilExam:8 週}

Also applies to: 231-231

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

In `@src/content/book/zh-TW/20-education-learning.mdx` around lines 154 - 155,
請修正繁體中文用字一致性:將模板中的 `${course:AP 美國曆史}` 的「曆史」改為「歷史」,並將 `${dueIn:2 周}` /
`${dueIn:8 周}` 等所有出現的「周」統一改為台灣常用的「週」,確保所有相同模板變數(例如 `${course:AP
美國曆史}`、`${dueIn:2 周}`、`${dueIn:8 周}`)都一併更新為 `${course:AP 美國歷史}`、`${dueIn:2
週}`、`${dueIn:8 週}` 以維持用字一致。
src/content/book/zh-TW/16-ethics-responsible-use.mdx-14-14 (1)

14-14: ⚠️ Potential issue | 🟡 Minor

修正字詞間多餘空白以避免閱讀斷裂。

偽造 證據 中間多了一個空白,建議改為 偽造證據

✏️ Proposed fix
-  { label: "誠實", description: "不要使用AI欺騙他人或建立誤導性內容", example: "不製作虛假評論、冒充他人或偽造 證據", exampleType: "text", color: "blue" },
+  { label: "誠實", description: "不要使用AI欺騙他人或建立誤導性內容", example: "不製作虛假評論、冒充他人或偽造證據", exampleType: "text", color: "blue" },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/16-ethics-responsible-use.mdx` at line 14, In the
object with label "誠實" (the entry having description "不要使用AI欺騙他人或建立誤導性內容"),
remove the extra space inside the example string by changing "偽造 證據" to "偽造證據"
so the example reads without a break; update the example property (example:
"...") accordingly and scan that same object ("label": "誠實", "exampleType":
"text") for any other unintended whitespace to correct.
src/content/book/zh-TW/16-ethics-responsible-use.mdx-348-356 (1)

348-356: ⚠️ Potential issue | 🟡 Minor

Quiz 文案有兩處多餘空白,建議一併清理。

目前題目與解釋文字各有一個不必要空白,會影響可讀性與專業感。

✏️ Proposed fix
-  question="一個使用者問你的AI系統如何 擺脫一個煩人的人。最恰當的回應策略是什麼?"
+  question="一個使用者問你的AI系統如何擺脫一個煩人的人。最恰當的回應策略是什麼?"
@@
-  explanation="模糊的請求需要澄清,而不是假設。擺脫某人 可能意味著結束友誼、解決職場衝突,或者某些有害的事情。提出澄清問題可以讓你針對實際意圖做出適當回應,同時對提供有害資訊保持謹慎。"
+  explanation="模糊的請求需要澄清,而不是假設。擺脫某人可能意味著結束友誼、解決職場衝突,或者某些有害的事情。提出澄清問題可以讓你針對實際意圖做出適當回應,同時對提供有害資訊保持謹慎。"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/16-ethics-responsible-use.mdx` around lines 348 - 356,
The quiz string values contain two stray extra spaces: remove the unwanted space
inside the question prop value in the JSX attribute question="一個使用者問你的AI系統如何
擺脫一個煩人的人。最恰當的回應策略是什麼?" (remove the space after "如何") and remove the extra space
inside the explanation prop value "擺脫某人 可能意味著..." (remove the space after "某人")
so both question and explanation text are cleaned; update the JSX attributes
where question= and explanation= are defined accordingly.
src/content/kids/zh-TW/3-3-format-finder.mdx-32-32 (1)

32-32: ⚠️ Potential issue | 🟡 Minor

Polish several zh-TW strings for natural kid-facing wording.

A few phrases read as literal translation and feel awkward in Traditional Chinese (Line 32, Line 44, Line 54, Line 79). This is a user-facing copy quality issue.

✍️ Suggested copy edits
-  explanation="第一個提示詞準確地告訴我如何組織回答 - 作為5個編號的事實!"
+  explanation="第一個提示詞清楚告訴我如何組織回答:用 5 點編號列出事實!"

-  explanation="列表格式使按順序記憶和數行星變得容易!"
+  explanation="列表格式讓你更容易按順序記住行星!"

-  instruction="排列來請求一個特定格式"
+  instruction="把詞語排好,請求一種特定格式"

-太棒了!你學會了請求特定**格式**幫助你得到正是你需要的方式組織的回答!
+太棒了!你學會了請求特定**格式**,讓我用你最需要的方式來組織回答!

Also applies to: 44-44, 54-54, 79-79

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

In `@src/content/kids/zh-TW/3-3-format-finder.mdx` at line 32, The listed zh-TW
copy strings are literal translations and need to be rewritten for natural,
kid-facing Traditional Chinese: update the attribute value
explanation="第一個提示詞準確地告訴我如何組織回答 - 作為5個編號的事實!" and the other similar strings at
the same file (the phrases at the occurrences around lines 44, 54, and 79) to
use simpler, friendlier phrasing that a child would understand while preserving
the original meaning and instruction intent (keep the "5 numbered facts"
structure and clarity). Locate these string literals in
src/content/kids/zh-TW/3-3-format-finder.mdx and replace with concise,
natural-sounding Traditional Chinese alternatives that flow conversationally for
kids.
src/content/book/zh-TW/17-prompt-optimization.mdx-146-146 (1)

146-146: ⚠️ Potential issue | 🟡 Minor

Use Taiwan-preferred wording consistently in zh-TW copy.

A few terms read as mixed-variant Chinese in a zh-TW chapter. Please normalize them for locale consistency (e.g., Line 146, Line 160, Line 175, Line 211).

✍️ Suggested text updates
-  { label: "異步/批量", description: "使用最佳模型,後臺處理", example: "GPT-4、Claude Opus 用於離線處理", exampleType: "text", color: "blue" }
+  { label: "非同步/批次", description: "使用最佳模型,於背景處理", example: "GPT-4、Claude Opus 用於離線處理", exampleType: "text", color: "blue" }

-在規模化運營時,小的節省會累積成顯著的預算影響。
+在規模化營運時,小幅節省會累積成顯著的預算影響。

-  { label: "預過濾", description: "不要傳送不需要 AI 的請求", example: "在昂貴的分類之前使用關鍵詞匹配", exampleType: "text", color: "green" }
+  { label: "預先過濾", description: "不要傳送不需要 AI 的請求", example: "在昂貴的分類前先使用關鍵字比對", exampleType: "text", color: "green" }

-   - 4 箇中等複雜度案例
+   - 4 個中等複雜度案例

Also applies to: 160-160, 175-175, 211-211

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

In `@src/content/book/zh-TW/17-prompt-optimization.mdx` at line 146, Normalize
zh-TW wording in the card objects by updating the locale-specific strings:
replace label "異步/批量" with a Taiwan-preferred variant (e.g., "非同步/批次"), change
description "使用最佳模型,後臺處理" to use "後台" (e.g., "使用最佳模型,後台處理"), and ensure example
strings like "GPT-4、Claude Opus 用於離線處理" and any similar entries use consistent
Taiwan-preferred terms across the other card objects referenced (the objects
containing keys label, description, example, exampleType, color) so all
occurrences use the same Taiwan variants.
src/content/book/zh-TW/18-writing-content.mdx-27-27 (1)

27-27: ⚠️ Potential issue | 🟡 Minor

將預設參數值本地化,維持 zh-TW 體驗一致性。

這幾個預設值仍為英文,會讓 zh-TW 內容中斷語境(特別是互動輸入預設值)。

🌐 Suggested fix
-- 目的:\${purpose:inform and provide actionable advice}
+- 目的:\${purpose:提供可執行的建議並傳遞實用資訊}

-- 目標:\${goal:convert to paid}
+- 目標:\${goal:轉換為付費用戶}

-- 視角:\${pov:third person}
-- 時態:\${tense:past}
-- 語氣:\${tone:suspenseful}
+- 視角:\${pov:第三人稱}
+- 時態:\${tense:過去式}
+- 語氣:\${tone:懸疑}

-目標閱讀水平:\${readingLevel:8th grade}
+目標閱讀程度:\${readingLevel:國中二年級}

Also applies to: 92-92, 219-221, 301-301

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

In `@src/content/book/zh-TW/18-writing-content.mdx` at line 27, The template
default values in the MDX file use English strings inside parameter placeholders
(e.g. the snippet "目的:${purpose:inform and provide actionable advice}") which
breaks the zh-TW experience; replace those English defaults with appropriate
zh-TW translations while preserving the placeholder syntax (e.g.
"${purpose:通知並提供可行建議}" or similar) and apply the same change to the other
occurrences referenced (the placeholders around lines 92, 219-221, and 301) so
all ${param:default} tokens show localized defaults.
src/content/book/zh-TW/18-writing-content.mdx-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

修正章節標題重複詞,避免語意冗餘。

Line 7 的「部落格文章和文章」語意重複,讀感不自然。

✏️ Suggested fix
-## 部落格文章和文章
+## 部落格與長文寫作
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/18-writing-content.mdx` at line 7, 修正標題「##
部落格文章和文章」的語意冗餘:將該章節標題(文本 "## 部落格文章和文章")改為更簡潔一致的標題,例如「## 部落格文章」或「##
文章」,以消除重複詞並改善可讀性;確保同一檔案中不留相同語意的重複標題並同步更新任何目錄或連結引用(如有)。
src/content/book/zh-TW/18-writing-content.mdx-331-331 (1)

331-331: ⚠️ Potential issue | 🟡 Minor

調整 zh-TW 慣用詞「想像力」。

Line 331 的「想象力」建議改為台灣常用的「想像力」。

✏️ Suggested fix
-我希望你扮演一個講故事的人。你將想出有趣的故事,這些故事對觀眾來說既引人入勝、富有想象力又令人著迷。它可以是童話故事、教育故事,或任何其他類型的故事,只要能夠吸引人們的注意力和想象力。
+我希望你扮演一個講故事的人。你將想出有趣的故事,這些故事對觀眾來說既引人入勝、富有想像力又令人著迷。它可以是童話故事、教育故事,或任何其他類型的故事,只要能夠吸引人們的注意力和想像力。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/18-writing-content.mdx` at line 331, The text uses the
Mainland Chinese variant "想象力" in the TryIt compact prompt string; update that
occurrence to the Taiwanese-preferred "想像力" (replace "想象力" with "想像力" inside the
TryIt compact prompt literal) so the prompt uses zh-TW conventions—look for the
TryIt compact prompt containing the sentence ending with "引人入勝、富有想象力又令人著迷" and
change "想象力" to "想像力".
src/content/book/zh-TW/18-writing-content.mdx-13-13 (1)

13-13: ⚠️ Potential issue | 🟡 Minor

修正「簡報」用詞,避免誤解為投影片。

Line 13 的「具體的簡報」在 zh-TW 常被理解為 presentation,和此處「明確需求/brief」不一致。

✏️ Suggested fix
-  after={{ label: "✓ 具體的簡報", content: "寫一篇 800 字的部落格文章,關於遠程工作者的生產力。\n\n受眾:在家工作的科技專業人士\n語氣:對話式但可操作\n包含:3 個具體技巧及範例\n關鍵詞:'遠程生產力技巧'" }}
+  after={{ label: "✓ 具體的需求描述", content: "寫一篇 800 字的部落格文章,關於遠距工作者的生產力。\n\n受眾:在家工作的科技專業人士\n語氣:對話式但可操作\n包含:3 個具體技巧及範例\n關鍵詞:'遠距生產力技巧'" }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/18-writing-content.mdx` at line 13, The label text "✓
具體的簡報" in the after prop should be changed to avoid "簡報" (presentation); update
the after={{ label: "✓ 具體的簡報", ... }} entry to use a clearer term like "✓ 具體的說明"
or "✓ 具體的需求/簡述" so it correctly conveys "brief/clear instructions" rather than a
slide deck, keeping the rest of the content unchanged.
src/content/book/zh-TW/19-programming-development.mdx-394-394 (1)

394-394: ⚠️ Potential issue | 🟡 Minor

Correct typo in the summary callout.

幷包含 should be 並包含.

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

In `@src/content/book/zh-TW/19-programming-development.mdx` at line 394, The
summary callout contains a typo: replace the incorrect Chinese character
sequence "幷包含" with the correct "並包含" in the callout text (look for the summary
callout that currently reads
"包含完整的上下文(語言、框架、約束條件),精確說明需求,請求特定的輸出格式,在請求程式碼的同時要求解釋,幷包含需要處理的邊界情況。"); ensure the
corrected phrase appears exactly as "並包含" and update any other identical
occurrences in the same callout.
src/content/kids/zh-TW/4-1-pretend-time.mdx-14-15 (1)

14-15: ⚠️ Potential issue | 🟡 Minor

Replace Simplified Chinese wording in zh-TW copy.

想象 appears in Traditional Chinese content; this should be 想像 for zh-TW consistency.

✏️ Proposed copy fix
- - "想象你是老師..."
+ - "想像你是老師..."
...
-  title="想象時間!"
+  title="想像時間!"
...
-  successMessage="很棒的角色扮演!現在我們可以有一個有趣的想象對話了!"
+  successMessage="很棒的角色扮演!現在我們可以有一個有趣的想像對話了!"

Also applies to: 52-53, 70-70

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

In `@src/content/kids/zh-TW/4-1-pretend-time.mdx` around lines 14 - 15, Several
Traditional Chinese strings use the Simplified character 想象; locate the lines
containing the phrases "想象你是老師..." and "你是一個友好的廚師..." and replace 想象 with the
Traditional variant 想像; also update the same substitution for the other
occurrences noted (around the strings at lines referenced as 52-53 and 70 in the
comment) so all instances use 想像 for zh-TW consistency.
src/content/book/zh-TW/15-common-pitfalls.mdx-1-1 (1)

1-1: ⚠️ Potential issue | 🟡 Minor

Fix typo in opening paragraph.

併為你提供 should be 並為你提供.

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

In `@src/content/book/zh-TW/15-common-pitfalls.mdx` at line 1, The opening
paragraph contains a typo: replace the incorrect Chinese phrase "併為你提供" with the
correct "並為你提供" in the first paragraph (look for the exact snippet
"即使是經驗豐富的提示詞工程師也會陷入一些可預見的陷阱。好消息是:一旦你認識到這些模式,就很容易避免它們。本章將詳細介紹最常見的陷阱,併為你提供具體的規避策略。")
so the sentence reads "...本章將詳細介紹最常見的陷阱,並為你提供具體的規避策略。".
src/app/docs/self-hosting/page.tsx-44-45 (1)

44-45: ⚠️ Potential issue | 🟡 Minor

Localize the newly changed i18n display strings.

Line 44 and Line 464 introduce/modify user-facing copy with hardcoded English text. Please move both to translation keys and interpolate the dynamic values through t(...).

Suggested fix
-            <li>Multi-language support ({supportedLocales.length} locales)</li>
+            <li>{t("features.multiLanguageSupport", { count: supportedLocales.length })}</li>

-                    <TableCell className="text-muted-foreground text-sm">Supported locales: {supportedLocales.join(", ")}</TableCell>
+                    <TableCell className="text-muted-foreground text-sm">
+                      {t("i18n.supportedLocales", { locales: supportedLocales.join(", ") })}
+                    </TableCell>

As per coding guidelines: "Use next-intl for all user-facing strings; never hardcode text" and "Import translations with useTranslations() for client components or getTranslations() for server components".

Also applies to: 464-464

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

In `@src/app/docs/self-hosting/page.tsx` around lines 44 - 45, Replace the
hardcoded English list items in page.tsx with translation keys and interpolate
dynamic values via the next-intl translator: call getTranslations(...) (for
server components) or useTranslations(...) (for client components) and replace
the strings "Multi-language support ({supportedLocales.length} locales)" and
"CC0 licensed - use freely for any purpose" with
t('docs.selfHosting.multiLanguage', { count: supportedLocales.length }) and
t('docs.selfHosting.cc0') (or similar keys), and add corresponding keys to your
locale JSONs; reference the supportedLocales variable and ensure t(...) is used
to format the locale count rather than embedding the number in the hardcoded
string.
src/content/kids/zh-TW/2-3-when-and-where.mdx-75-79 (1)

75-79: ⚠️ Potential issue | 🟡 Minor

MagicWords blank order is reversed for the sentence template.

The sentence expects time first (在___期間) then place (發生在___), but the blank definitions are currently place then time.

Suggested fix
   blanks={[
-    { hint: "🗺️ 一個地方", answers: ["鬼屋", "海底城市", "雲端王國", "恐龍公園", "糖果國"] },
-    { hint: "⏰ 一個時間", answers: ["暴風雨", "日落", "寒假", "滿月", "未來"] }
+    { hint: "⏰ 一個時間", answers: ["暴風雨", "日落", "寒假", "滿月", "未來"] },
+    { hint: "🗺️ 一個地方", answers: ["鬼屋", "海底城市", "雲端王國", "恐龍公園", "糖果國"] }
   ]}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/kids/zh-TW/2-3-when-and-where.mdx` around lines 75 - 79, The
blanks for the MagicWords sentence template are in the wrong order (place then
time) while the sentence string expects time first ("在___期間") then place
("發生在___"); fix by reordering the blanks array so the second item becomes first
and the first becomes second—i.e., make the first blank have hint "⏰ 一個時間" with
its answers ["暴風雨", "日落", "寒假", "滿月", "未來"] and the second blank have hint "🗺️
一個地方" with its place answers—so the blanks array matches the sentence
placeholders.
messages/zh-TW.json-1472-1472 (1)

1472-1472: ⚠️ Potential issue | 🟡 Minor

仍有使用者可見文字未翻譯為繁體中文。

Line 1472(Featured in ...)與 Line 2271(PostgreSQL database)是 user-facing 字串,建議完成 zh-TW 翻譯。

As per coding guidelines, messages/**/*.json: Add translations for all user-facing text in messages/{locale}.json files.

Also applies to: 2271-2271

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

In `@messages/zh-TW.json` at line 1472, Two user-facing entries in
messages/zh-TW.json remain in English; update the values for the
"featuredTagesspiegel" entry (keep the <link> tag intact) and the entry that
currently contains "PostgreSQL database" to their Traditional Chinese
translations, ensuring the JSON keys remain unchanged and the HTML-like tags or
placeholders are preserved exactly.
messages/zh-TW.json-824-826 (1)

824-826: ⚠️ Potential issue | 🟡 Minor

請統一 zh-TW 用字: 應改為

Line 824、Line 825、Line 983、Line 1002 等處仍是簡體/非台灣慣用字,會削弱繁體在地化一致性。

💡 建議修正
-    "upvote": "贊",
-    "upvotes": "贊"
+    "upvote": "讚",
+    "upvotes": "讚"

As per coding guidelines, messages/**/*.json: Add translations for all user-facing text in messages/{locale}.json files.

Also applies to: 983-984, 1002-1003

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

In `@messages/zh-TW.json` around lines 824 - 826, The zh-TW translations use
non-Taiwanese wording ("贊") for several keys; update all occurrences to the
Taiwan-preferred "讚"—specifically replace the values for the "upvote" and
"upvotes" keys and any other entries showing "贊" (and other
simplified/non-localized variants noted around the same group such as the
strings currently showing at the later occurrences) so all user-facing strings
in the zh-TW messages JSON use "讚" and otherwise match Taiwan conventions;
ensure you run a quick scan of messages/zh-TW.json for any remaining simplified
characters and update them to their Taiwan equivalents.
src/content/book/zh-TW/12-handling-edge-cases.mdx-55-55 (1)

55-55: ⚠️ Potential issue | 🟡 Minor

Fix two Traditional Chinese typos in explanatory text.

Both are small but user-visible wording issues.

✏️ Suggested fix
-這些是故意濫用你係統的嘗試:
+這些是故意濫用你的系統的嘗試:

-防禦性提示詞能夠預見失敗模式併為每種情況定義明確的行為。可以把它想象成自然語言的錯誤處理。
+防禦性提示詞能夠預見失敗模式並為每種情況定義明確的行為。可以把它想象成自然語言的錯誤處理。

Also applies to: 145-145

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

In `@src/content/book/zh-TW/12-handling-edge-cases.mdx` at line 55, Replace the
Traditional Chinese typo "你係統" with the correct phrasing "你的系統" in the
explanatory sentence ("這些是故意濫用你係統的嘗試:") and make the identical correction at the
other occurrence (the same incorrect phrase around line 145); ensure both
instances read "這些是故意濫用你的系統的嘗試:" so wording is natural and consistent.
src/content/book/zh-TW/24-future-of-prompting.mdx-405-405 (1)

405-405: ⚠️ Potential issue | 🟡 Minor

Fix typo in Traditional Chinese wording (髮明發明).

This is a user-facing typo in the closing paragraph.

✏️ Suggested fix
-AI 時代才剛剛開始。最重要的應用尚未被髮明。最強大的技術尚未被發現。未來正在被書寫——由像你這樣的人,一次一個提示詞。
+AI 時代才剛剛開始。最重要的應用尚未被發明。最強大的技術尚未被發現。未來正在被書寫——由像你這樣的人,一次一個提示詞。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/24-future-of-prompting.mdx` at line 405, The closing
sentence contains a Traditional Chinese typo: replace the character "髮明" with
the correct "發明" in the sentence that starts "AI
時代才剛剛開始。最重要的應用尚未被髮明。最強大的技術尚未被發現。未來正在被書寫——由像你這樣的人,一次一個提示詞。"; update that string
in the file so it reads "最重要的應用尚未被發明" to fix the user-facing typo.
src/content/kids/zh-TW/1-1-meet-promi.mdx-49-49 (1)

49-49: ⚠️ Potential issue | 🟡 Minor

Use zh-TW wording consistently in locale copy.

There are still Mainland-style terms/characters in this zh-TW lesson (消息, 關于). Please normalize to zh-TW forms for consistency.

Suggested text fixes
-**提示詞**就是你傳送給像我這樣的AI的消息的另一種說法。
+**提示詞**就是你傳送給像我這樣的 AI 的訊息的另一種說法。

-  good="你能幫我寫一首關于海洋的詩嗎?"
+  good="你能幫我寫一首關於海洋的詩嗎?"

Also applies to: 75-75

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

In `@src/content/kids/zh-TW/1-1-meet-promi.mdx` at line 49, The copy uses Mainland
Chinese terms/characters ("消息", "关于") instead of zh-TW forms; update all
occurrences in this lesson to Traditional Taiwanese wording — replace "消息" with
"訊息" and "关于"/"关于" variants with "關於" (and scan for any other Simplified
characters), ensuring consistency across the file (also check the other
occurrence noted around line 75).
src/content/book/zh-TW/09-json-yaml-prompting.mdx-26-36 (1)

26-36: ⚠️ Potential issue | 🟡 Minor

Avoid invalid JSON in the first schema example.

This fence looks like JSON, but "age": number is not valid JSON. In a chapter about strict JSON output, readers copy-pasting the example will hit parse errors immediately. Either switch the example to JSON Schema or make the placeholders JSON-safe.

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

In `@src/content/book/zh-TW/09-json-yaml-prompting.mdx` around lines 26 - 36, The
fenced example contains invalid JSON because the schema uses a non-JSON token
("age": number); update the example so it is valid JSON (e.g., use a placeholder
numeric value like "age": 34 or a JSON-safe placeholder such as null) or
explicitly switch the block to a JSON Schema snippet and label it accordingly;
target the fenced block that defines { "name": "string", "age": number, "email":
"string" } and ensure the "age" field is a valid JSON value or convert the
entire block to JSON Schema syntax.
src/content/book/zh-TW/22-creative-arts.mdx-182-186 (1)

182-186: ⚠️ Potential issue | 🟡 Minor

Fix the 玩傢 typo in the level brief.

玩傢 should be 玩家. It’s noticeable in the rendered chapter copy.

🔧 Suggested fix
-難度:${difficulty:遊戲中期,玩傢俱備基礎能力}
+難度:${difficulty:遊戲中期,玩家具備基礎能力}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/book/zh-TW/22-creative-arts.mdx` around lines 182 - 186, The
level brief contains a Chinese typo: replace the incorrect characters "玩傢" with
the correct "玩家" inside the TryIt component's prompt string (the prompt prop
used in the TryIt compact call); update the prompt template (e.g., the string
starting with `為 ${gameType:...}`) so all occurrences of "玩傢" are changed to
"玩家" to ensure the rendered chapter shows the correct term.
🧹 Nitpick comments (2)
src/content/kids/zh-TW/3-3-format-finder.mdx (1)

38-38: Consider differentiating repeated section titles.

Line 38 and Line 62 both use ## 選擇你的格式!; giving the second one a distinct title would improve progression clarity.

Also applies to: 62-62

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

In `@src/content/kids/zh-TW/3-3-format-finder.mdx` at line 38, The second
occurrence of the header "## 選擇你的格式!" is duplicated (seen at the header string
"## 選擇你的格式!"); change the later instance to a distinct, progression-reflective
title (e.g., indicate it's a continuation, next step, or summary) so readers can
tell the sections apart and any generated anchors/links won’t collide; update
the duplicated header text and any internal references to that header
accordingly.
src/lib/date.ts (1)

14-15: Consider normalizing locale tags before map lookup.

getDateLocale currently needs an exact key match, so non-canonical forms (e.g. zh-tw) can still fall back to English. A small normalization step would make this utility safer for direct callers.

Suggested hardening
 export function getDateLocale(locale: string): Locale {
-  return locales[locale] || enUS;
+  const normalized = locale.replace("_", "-");
+  const lower = normalized.toLowerCase();
+
+  if (lower === "zh-tw" || lower === "zh-hk" || lower === "zh-hant") {
+    return zhTW;
+  }
+
+  return locales[normalized] || locales[normalized.split("-")[0]] || enUS;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/date.ts` around lines 14 - 15, The getDateLocale function currently
requires an exact key match; normalize the incoming locale string (e.g.,
toLowerCase(), replace '_' with '-', trim) before looking up in the locales map
and then try a fallback by using the primary language subtag
(locale.split('-')[0]) if the normalized full tag isn't found; return
locales[normalized] || locales[primary] || enUS. Update references to
getDateLocale and the locales lookup accordingly so callers like "zh-tw" or
"en_US" resolve to the correct Locale instead of falling back to enUS.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/content/book/zh-TW/01-understanding-ai-models.mdx`:
- Around line 96-99: The Compare component is receiving plain objects for its
before/after props (e.g. { label, content }) which the component expects
renderable content (string or JSX) and thus will break rendering; update the
Compare usages (the Compare component instances in this file) to pass renderable
values instead of objects—for example pass a single string or JSX fragment that
combines the label and content (e.g. "文字風格提示詞: 請建立一張貓坐在窗臺上看著外面下雨的圖像" or a small
JSX node containing the label and content), and apply the same fix to the other
occurrences mentioned so before/after are nodes/strings rather than { label,
content } objects.

In `@src/content/book/zh-TW/02-anatomy-of-effective-prompt.mdx`:
- Around line 26-29: The Compare component is being passed objects for its
before/after props which violates its contract; update usages of Compare (the
instance at lines around the 02-anatomy-of-effective-prompt.mdx file) to pass
plain renderable content or JSX instead of objects—replace before={{ label:
"...", content: "..." }} and after={{ label: "...", content: "..." }} with
simple strings or JSX nodes (e.g., before="沒有角色: 解釋量子計算。" and after="有角色:
你是一位物理學教授…請解釋量子計算。" or equivalent JSX fragments) and make the same change for
the other occurrence noted (around lines 49-52).

In `@src/content/book/zh-TW/03-core-prompting-principles.mdx`:
- Around line 13-16: The Compare component is being passed plain objects ({
label, content }) but its contract expects renderable values (strings or JSX/MDX
nodes) for the before and after props; update each Compare invocation (the
instances using before/after props such as the one showing "隱式(有問題)"/"顯式(有效)"
and the other occurrences at the referenced blocks) to pass renderable content
instead of objects — e.g., pass a single string or an MDX node that combines the
label and content (or use a small fragment/JSX element) for before and after so
Compare receives renderable values rather than { label, content } objects.
Ensure all affected Compare usages (the ones noted in the comment) are changed
consistently.

In `@src/content/book/zh-TW/13-multimodal-prompting.mdx`:
- Around line 37-60: The hard-coded model/version matrix in the InfoGrid items
arrays (the entries under the "理解模型(輸入 → 分析)" and "生成模型(文字 → 媒體)" sections) is
now stale; replace these concrete model/version/context-window claims with
capability-based descriptions and external links, or move the detailed versioned
list to a separate maintained reference page and change the InfoGrid to point to
that page (e.g., replace entries like the GPT-4o / GPT-5, Claude 4 Sonnet/Opus,
Gemini 2.5, etc. items with generic capability text such as "supports
text+image" and a provider-docs URL or a single "See provider compatibility
matrix" link). Ensure InfoGrid items keep their label fields but remove specific
versions, token counts, and dated claims so the content remains accurate over
time.

In `@src/content/book/zh-TW/15-common-pitfalls.mdx`:
- Around line 18-313: The template strings in several JSX components (e.g.,
TryIt prompts, Compare content, Format/Prompt generators) contain unescaped
${...} placeholders which will be evaluated at runtime and can throw
ReferenceError; update every prompt prop and inline template literal to escape
placeholders by replacing ${...} with \${...} so they remain literal
placeholders (there are ~17 occurrences across TryIt, Compare, and the prompt
strings inside Format/Prompt generator blocks); search for occurrences inside
the TryIt.prompt, Compare.before/after.content, and any prompt={`...`} or
multi-line string literals and replace each ${variableLike} with
\${variableLike} consistently.

In `@src/content/kids/zh-TW/2-2-who-and-what.mdx`:
- Around line 75-80: The blanks array is ordered differently from the sentence
"請寫一個關於想要___的___的___": relocate and reorder entries in the blanks array so they
match the sentence placeholders (first blank = 目標/goal, second = 角色/character,
third = 寫作類型/writing type); update the hint strings accordingly (e.g., "🎯 一個目標"
as the first entry, "🦸 一個角色" as the second, "📝 寫作類型" as the third) so the
sentence and blanks[] align when assembled.

In `@src/content/kids/zh-TW/3-1-setting-the-scene.mdx`:
- Around line 66-69: LevelComplete is using levelSlug "3-1-setting-the-scene"
which is not present in the level registry; open the level registry
(src/lib/kids/levels.ts) and add a new entry object with slug:
"3-1-setting-the-scene" and the matching metadata (title, path/route,
stars/requirements or any existing fields used by LevelComplete/progress
resolution), ensure the entry is exported/returned in the same structure as
other levels and that any arrays or maps (e.g., LEVELS, levelMap) include this
slug so LevelComplete can resolve progress by slug.

In `@src/content/kids/zh-TW/3-4-context-champion.mdx`:
- Around line 26-32: The props passed to the PromptVsMistake usage (question,
good, bad, promiMessage) do not match the component's expected props (title,
mistake, correction, explanation); update either the call sites or the component
interface so names align: rename the attributes in the <PromptVsMistake>
instances (e.g., question→title, bad→mistake, good→correction,
promiMessage→explanation or promiMessage→whatever the component expects) or
change the component prop names (in the PromptVsMistake component definition) to
accept question, good, bad, promiMessage and map them to the internal fields;
ensure the explanation prop content remains mapped to the component's
explanation/display slot and adjust any prop destructuring in PromptVsMistake
accordingly.
- Around line 62-72: The MagicWords usage passes sentence, blanks, and
successMessage props which don't match the component's expected words-based API
and validation flow; update this call to supply the data in the component's
required shape (the single prop the component validates, e.g., words) or
alternatively adjust the MagicWords component to accept and map
sentence/blanks/successMessage into its existing words validation; locate the
MagicWords invocation in the diff and either convert the
sentence/blanks/successMessage into the words structure the component expects or
add a small adapter inside MagicWords (e.g., mapPropsToWords) so the
validation/interaction logic that references words continues to work correctly.
- Around line 50-56: The DragDropPrompt props are using the wrong names and type
for expected comparison: replace the props passed to the component so they match
the component API — use initial={...} instead of pieces, correct={...} instead
of correctOrder, instructions={...} instead of instruction, and
explanation={...} instead of successMessage; and ensure the correct prop is an
array of the actual piece strings (or convert the numeric indices into the
corresponding strings) so the component compares text values rather than numeric
positions.

In `@src/content/kids/zh-TW/4-2-story-starters.mdx`:
- Around line 64-70: The blanks array is ordered incorrectly relative to the
sentence: swap the 3rd and 4th blank entries so the sentence's third placeholder
expects a power and the fourth expects an item; specifically, in the blanks prop
referenced by "sentence=\"寫一個___故事,關於一個___發現了一個能___的___。...\"", swap the object
with hint "🎁 特別物品" and the object with hint "🌟 特殊力量" (and their answers
arrays) so the third blank is the "特殊力量" options and the fourth blank is the
"特別物品" options.

In `@src/content/kids/zh-TW/4-3-character-creator.mdx`:
- Around line 64-69: The blanks array order does not match the sentence
template: the sentence string expects the first placeholder to be a personality
trait but the blanks array's first entry is role type; update the blanks array
to match the placeholder order in sentence (ensure the first blanks entry
corresponds to "😊 個性特點", second to "🎭 角色類型", third to "💬 說話風格", fourth to "❤️
另一個特點") and adjust the hints/answers accordingly so MagicWords fills
placeholders in the correct order.

In `@src/content/kids/zh-TW/5-1-perfect-prompt.mdx`:
- Around line 45-51: The PromptVsMistake component is being passed the wrong
prop names (question/good/bad/promiMessage) but its interface expects
title/mistake/correction/explanation; update the usage in the MDX so that
PromptVsMistake receives title (was question), mistake (was bad), correction
(was good), and explanation (keep or map accordingly), and remove or map
promiMessage into the correct prop or into the component's children if needed;
verify src/components/kids/elements/prompt-vs-mistake.tsx to confirm exact prop
names and adjust all occurrences (including the block at lines ~57-63) to match.
- Around line 81-92: The MagicWords usage passes props sentence, blanks,
successMessage but the MagicWords component expects title, words, explanation
(see component in magic-words.tsx); fix by either (A) updating the JSX in
src/content/kids/zh-TW/5-1-perfect-prompt.mdx to pass title (string), words
(array/object matching the component's shape) and explanation (string) instead
of sentence/blanks/successMessage, or (B) modify the MagicWords component's
props interface (title/words/explanation) to accept the current keys
(sentence/blanks/successMessage) and map them internally to the component's
expected variables (or add prop aliases) so the interactive behavior works.
Ensure the referenced symbols MagicWords, sentence/blanks/successMessage, and
title/words/explanation are aligned.
- Around line 69-75: The DragDropPrompt usage passes props
pieces/correctOrder/instruction/successMessage but the component expects
initial/correct/instructions/explanation and compares correct as a string-array
(not index-array); fix the call to use the component's API by renaming props:
initial={["我在為喜歡釣魚的爸爸做生日卡片。", ...]} instructions="把所有元素排列成一個完美的提示詞"
correct={["我在為喜歡釣魚的爸爸做生日卡片。","給我3個有趣的釣魚笑話","像'魚為什麼臉紅了?因為它看到了海底!'","適合家庭而且短!"]}
explanation="完美!背景、格式、例子和風格都在一個提示詞裡!" so the component's correct comparison
(array of strings) works; alternatively, if you prefer index-based correctOrder,
update DragDropPrompt's prop types and internal comparison logic (in the
DragDropPrompt definition) to accept correctOrder:number[] and compare indices
instead.

In `@src/content/kids/zh-TW/5-4-graduation-day.mdx`:
- Around line 65-73: The MagicWords template's sentence "我是一個想___的___。..."
requires the goal (想___) to be the first blank and identity (的___) second, so
swap the first two entries in the blanks array: move the object with hint "🎯
你的目標" to index 0 and the object with hint "👤 你是誰" to index 1 so the blanks
order matches the sentence; update the blanks array where defined to reflect
this swap (refer to the sentence variable and the blanks array entries).

In `@src/lib/i18n/locale-resolution.ts`:
- Around line 43-57: The current Accept-Language parser builds the languages
array from acceptLanguage and includes entries with q=0 (unacceptable); update
the parsing pipeline so entries with q <= 0 are skipped before attempting
resolution: when splitting acceptLanguage into parts, compute q safely (handle
missing/NaN) and filter out any items where q <= 0 (or q === 0) before sorting
and iterating; then continue iterating over the filtered languages and call
normalizeRequestedLocale(lang) as before so rejected locales like "zh-TW;q=0"
are ignored.

---

Outside diff comments:
In `@src/components/prompts/translate-button.tsx`:
- Around line 11-27: The localeToLanguage mapping currently leaves "zh"
ambiguous and omits supported locales causing fallbacks; update the
localeToLanguage object (symbol: localeToLanguage) to explicitly map "zh" to
"Simplified Chinese" (since "zh-TW" is already "Traditional Chinese") and add
the missing supported locales "nl" -> "Dutch", "az" -> "Azerbaijani", and "fa"
-> "Persian" (or "Farsi") so lookups in the translate-button component return
human-readable names instead of raw locale codes.

---

Minor comments:
In `@messages/zh-TW.json`:
- Line 1472: Two user-facing entries in messages/zh-TW.json remain in English;
update the values for the "featuredTagesspiegel" entry (keep the <link> tag
intact) and the entry that currently contains "PostgreSQL database" to their
Traditional Chinese translations, ensuring the JSON keys remain unchanged and
the HTML-like tags or placeholders are preserved exactly.
- Around line 824-826: The zh-TW translations use non-Taiwanese wording ("贊")
for several keys; update all occurrences to the Taiwan-preferred
"讚"—specifically replace the values for the "upvote" and "upvotes" keys and any
other entries showing "贊" (and other simplified/non-localized variants noted
around the same group such as the strings currently showing at the later
occurrences) so all user-facing strings in the zh-TW messages JSON use "讚" and
otherwise match Taiwan conventions; ensure you run a quick scan of
messages/zh-TW.json for any remaining simplified characters and update them to
their Taiwan equivalents.

In `@src/app/docs/self-hosting/page.tsx`:
- Around line 44-45: Replace the hardcoded English list items in page.tsx with
translation keys and interpolate dynamic values via the next-intl translator:
call getTranslations(...) (for server components) or useTranslations(...) (for
client components) and replace the strings "Multi-language support
({supportedLocales.length} locales)" and "CC0 licensed - use freely for any
purpose" with t('docs.selfHosting.multiLanguage', { count:
supportedLocales.length }) and t('docs.selfHosting.cc0') (or similar keys), and
add corresponding keys to your locale JSONs; reference the supportedLocales
variable and ensure t(...) is used to format the locale count rather than
embedding the number in the hardcoded string.

In `@src/content/book/zh-TW/09-json-yaml-prompting.mdx`:
- Around line 26-36: The fenced example contains invalid JSON because the schema
uses a non-JSON token ("age": number); update the example so it is valid JSON
(e.g., use a placeholder numeric value like "age": 34 or a JSON-safe placeholder
such as null) or explicitly switch the block to a JSON Schema snippet and label
it accordingly; target the fenced block that defines { "name": "string", "age":
number, "email": "string" } and ensure the "age" field is a valid JSON value or
convert the entire block to JSON Schema syntax.

In `@src/content/book/zh-TW/12-handling-edge-cases.mdx`:
- Line 55: Replace the Traditional Chinese typo "你係統" with the correct phrasing
"你的系統" in the explanatory sentence ("這些是故意濫用你係統的嘗試:") and make the identical
correction at the other occurrence (the same incorrect phrase around line 145);
ensure both instances read "這些是故意濫用你的系統的嘗試:" so wording is natural and
consistent.

In `@src/content/book/zh-TW/15-common-pitfalls.mdx`:
- Line 1: The opening paragraph contains a typo: replace the incorrect Chinese
phrase "併為你提供" with the correct "並為你提供" in the first paragraph (look for the
exact snippet
"即使是經驗豐富的提示詞工程師也會陷入一些可預見的陷阱。好消息是:一旦你認識到這些模式,就很容易避免它們。本章將詳細介紹最常見的陷阱,併為你提供具體的規避策略。")
so the sentence reads "...本章將詳細介紹最常見的陷阱,並為你提供具體的規避策略。".

In `@src/content/book/zh-TW/16-ethics-responsible-use.mdx`:
- Line 14: In the object with label "誠實" (the entry having description
"不要使用AI欺騙他人或建立誤導性內容"), remove the extra space inside the example string by
changing "偽造 證據" to "偽造證據" so the example reads without a break; update the
example property (example: "...") accordingly and scan that same object
("label": "誠實", "exampleType": "text") for any other unintended whitespace to
correct.
- Around line 348-356: The quiz string values contain two stray extra spaces:
remove the unwanted space inside the question prop value in the JSX attribute
question="一個使用者問你的AI系統如何 擺脫一個煩人的人。最恰當的回應策略是什麼?" (remove the space after "如何")
and remove the extra space inside the explanation prop value "擺脫某人 可能意味著..."
(remove the space after "某人") so both question and explanation text are cleaned;
update the JSX attributes where question= and explanation= are defined
accordingly.

In `@src/content/book/zh-TW/17-prompt-optimization.mdx`:
- Line 146: Normalize zh-TW wording in the card objects by updating the
locale-specific strings: replace label "異步/批量" with a Taiwan-preferred variant
(e.g., "非同步/批次"), change description "使用最佳模型,後臺處理" to use "後台" (e.g.,
"使用最佳模型,後台處理"), and ensure example strings like "GPT-4、Claude Opus 用於離線處理" and
any similar entries use consistent Taiwan-preferred terms across the other card
objects referenced (the objects containing keys label, description, example,
exampleType, color) so all occurrences use the same Taiwan variants.

In `@src/content/book/zh-TW/18-writing-content.mdx`:
- Line 27: The template default values in the MDX file use English strings
inside parameter placeholders (e.g. the snippet "目的:${purpose:inform and provide
actionable advice}") which breaks the zh-TW experience; replace those English
defaults with appropriate zh-TW translations while preserving the placeholder
syntax (e.g. "${purpose:通知並提供可行建議}" or similar) and apply the same change to the
other occurrences referenced (the placeholders around lines 92, 219-221, and
301) so all ${param:default} tokens show localized defaults.
- Line 7: 修正標題「## 部落格文章和文章」的語意冗餘:將該章節標題(文本 "## 部落格文章和文章")改為更簡潔一致的標題,例如「##
部落格文章」或「## 文章」,以消除重複詞並改善可讀性;確保同一檔案中不留相同語意的重複標題並同步更新任何目錄或連結引用(如有)。
- Line 331: The text uses the Mainland Chinese variant "想象力" in the TryIt
compact prompt string; update that occurrence to the Taiwanese-preferred "想像力"
(replace "想象力" with "想像力" inside the TryIt compact prompt literal) so the prompt
uses zh-TW conventions—look for the TryIt compact prompt containing the sentence
ending with "引人入勝、富有想象力又令人著迷" and change "想象力" to "想像力".
- Line 13: The label text "✓ 具體的簡報" in the after prop should be changed to avoid
"簡報" (presentation); update the after={{ label: "✓ 具體的簡報", ... }} entry to use a
clearer term like "✓ 具體的說明" or "✓ 具體的需求/簡述" so it correctly conveys "brief/clear
instructions" rather than a slide deck, keeping the rest of the content
unchanged.

In `@src/content/book/zh-TW/19-programming-development.mdx`:
- Line 394: The summary callout contains a typo: replace the incorrect Chinese
character sequence "幷包含" with the correct "並包含" in the callout text (look for
the summary callout that currently reads
"包含完整的上下文(語言、框架、約束條件),精確說明需求,請求特定的輸出格式,在請求程式碼的同時要求解釋,幷包含需要處理的邊界情況。"); ensure the
corrected phrase appears exactly as "並包含" and update any other identical
occurrences in the same callout.

In `@src/content/book/zh-TW/20-education-learning.mdx`:
- Around line 154-155: 請修正繁體中文用字一致性:將模板中的 `${course:AP 美國曆史}` 的「曆史」改為「歷史」,並將
`${dueIn:2 周}` / `${dueIn:8 周}` 等所有出現的「周」統一改為台灣常用的「週」,確保所有相同模板變數(例如 `${course:AP
美國曆史}`、`${dueIn:2 周}`、`${dueIn:8 周}`)都一併更新為 `${course:AP 美國歷史}`、`${dueIn:2
週}`、`${dueIn:8 週}` 以維持用字一致。

In `@src/content/book/zh-TW/22-creative-arts.mdx`:
- Around line 182-186: The level brief contains a Chinese typo: replace the
incorrect characters "玩傢" with the correct "玩家" inside the TryIt component's
prompt string (the prompt prop used in the TryIt compact call); update the
prompt template (e.g., the string starting with `為 ${gameType:...}`) so all
occurrences of "玩傢" are changed to "玩家" to ensure the rendered chapter shows the
correct term.

In `@src/content/book/zh-TW/24-future-of-prompting.mdx`:
- Line 405: The closing sentence contains a Traditional Chinese typo: replace
the character "髮明" with the correct "發明" in the sentence that starts "AI
時代才剛剛開始。最重要的應用尚未被髮明。最強大的技術尚未被發現。未來正在被書寫——由像你這樣的人,一次一個提示詞。"; update that string
in the file so it reads "最重要的應用尚未被發明" to fix the user-facing typo.

In `@src/content/kids/zh-TW/1-1-meet-promi.mdx`:
- Line 49: The copy uses Mainland Chinese terms/characters ("消息", "关于") instead
of zh-TW forms; update all occurrences in this lesson to Traditional Taiwanese
wording — replace "消息" with "訊息" and "关于"/"关于" variants with "關於" (and scan for
any other Simplified characters), ensuring consistency across the file (also
check the other occurrence noted around line 75).

In `@src/content/kids/zh-TW/2-3-when-and-where.mdx`:
- Around line 75-79: The blanks for the MagicWords sentence template are in the
wrong order (place then time) while the sentence string expects time first
("在___期間") then place ("發生在___"); fix by reordering the blanks array so the
second item becomes first and the first becomes second—i.e., make the first
blank have hint "⏰ 一個時間" with its answers ["暴風雨", "日落", "寒假", "滿月", "未來"] and
the second blank have hint "🗺️ 一個地方" with its place answers—so the blanks array
matches the sentence placeholders.

In `@src/content/kids/zh-TW/3-3-format-finder.mdx`:
- Line 32: The listed zh-TW copy strings are literal translations and need to be
rewritten for natural, kid-facing Traditional Chinese: update the attribute
value explanation="第一個提示詞準確地告訴我如何組織回答 - 作為5個編號的事實!" and the other similar
strings at the same file (the phrases at the occurrences around lines 44, 54,
and 79) to use simpler, friendlier phrasing that a child would understand while
preserving the original meaning and instruction intent (keep the "5 numbered
facts" structure and clarity). Locate these string literals in
src/content/kids/zh-TW/3-3-format-finder.mdx and replace with concise,
natural-sounding Traditional Chinese alternatives that flow conversationally for
kids.

In `@src/content/kids/zh-TW/4-1-pretend-time.mdx`:
- Around line 14-15: Several Traditional Chinese strings use the Simplified
character 想象; locate the lines containing the phrases "想象你是老師..." and
"你是一個友好的廚師..." and replace 想象 with the Traditional variant 想像; also update the
same substitution for the other occurrences noted (around the strings at lines
referenced as 52-53 and 70 in the comment) so all instances use 想像 for zh-TW
consistency.

---

Nitpick comments:
In `@src/content/kids/zh-TW/3-3-format-finder.mdx`:
- Line 38: The second occurrence of the header "## 選擇你的格式!" is duplicated (seen
at the header string "## 選擇你的格式!"); change the later instance to a distinct,
progression-reflective title (e.g., indicate it's a continuation, next step, or
summary) so readers can tell the sections apart and any generated anchors/links
won’t collide; update the duplicated header text and any internal references to
that header accordingly.

In `@src/lib/date.ts`:
- Around line 14-15: The getDateLocale function currently requires an exact key
match; normalize the incoming locale string (e.g., toLowerCase(), replace '_'
with '-', trim) before looking up in the locales map and then try a fallback by
using the primary language subtag (locale.split('-')[0]) if the normalized full
tag isn't found; return locales[normalized] || locales[primary] || enUS. Update
references to getDateLocale and the locales lookup accordingly so callers like
"zh-tw" or "en_US" resolve to the correct Locale instead of falling back to
enUS.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 82dad75c-eff2-487d-b1f4-57608fcab561

📥 Commits

Reviewing files that changed from the base of the PR and between bc39bce and 8c4ad3a.

⛔ Files ignored due to path filters (1)
  • public/book-pdf/book-zh-TW-print.pdf is excluded by !**/*.pdf
📒 Files selected for processing (70)
  • messages/zh-TW.json
  • prompts.config.ts
  • public/book-pdf/book-zh-TW-print.html
  • scripts/generate-book-pdf.ts
  • scripts/setup.js
  • src/__tests__/lib/date.test.ts
  • src/__tests__/lib/i18n-locales.test.ts
  • src/app/book/page.tsx
  • src/app/docs/self-hosting/page.tsx
  • src/components/book/elements/locales/index.ts
  • src/components/book/elements/locales/zhTw.ts
  • src/components/book/sidebar.tsx
  • src/components/kids/layout/settings-modal.tsx
  • src/components/layout/header.tsx
  • src/components/prompts/language-switcher.tsx
  • src/components/prompts/prompt-card.tsx
  • src/components/prompts/translate-button.tsx
  • src/content/book/zh-TW/00a-preface.mdx
  • src/content/book/zh-TW/00b-history.mdx
  • src/content/book/zh-TW/00c-introduction.mdx
  • src/content/book/zh-TW/01-understanding-ai-models.mdx
  • src/content/book/zh-TW/02-anatomy-of-effective-prompt.mdx
  • src/content/book/zh-TW/03-core-prompting-principles.mdx
  • src/content/book/zh-TW/04-role-based-prompting.mdx
  • src/content/book/zh-TW/05-structured-output.mdx
  • src/content/book/zh-TW/06-chain-of-thought.mdx
  • src/content/book/zh-TW/07-few-shot-learning.mdx
  • src/content/book/zh-TW/08-iterative-refinement.mdx
  • src/content/book/zh-TW/09-json-yaml-prompting.mdx
  • src/content/book/zh-TW/10-system-prompts-personas.mdx
  • src/content/book/zh-TW/11-prompt-chaining.mdx
  • src/content/book/zh-TW/12-handling-edge-cases.mdx
  • src/content/book/zh-TW/13-multimodal-prompting.mdx
  • src/content/book/zh-TW/14-context-engineering.mdx
  • src/content/book/zh-TW/15-common-pitfalls.mdx
  • src/content/book/zh-TW/16-ethics-responsible-use.mdx
  • src/content/book/zh-TW/17-prompt-optimization.mdx
  • src/content/book/zh-TW/18-writing-content.mdx
  • src/content/book/zh-TW/19-programming-development.mdx
  • src/content/book/zh-TW/20-education-learning.mdx
  • src/content/book/zh-TW/21-business-productivity.mdx
  • src/content/book/zh-TW/22-creative-arts.mdx
  • src/content/book/zh-TW/23-research-analysis.mdx
  • src/content/book/zh-TW/24-future-of-prompting.mdx
  • src/content/book/zh-TW/25-agents-and-skills.mdx
  • src/content/kids/zh-TW/1-1-meet-promi.mdx
  • src/content/kids/zh-TW/1-2-first-words.mdx
  • src/content/kids/zh-TW/1-3-being-clear.mdx
  • src/content/kids/zh-TW/2-1-missing-details.mdx
  • src/content/kids/zh-TW/2-2-who-and-what.mdx
  • src/content/kids/zh-TW/2-3-when-and-where.mdx
  • src/content/kids/zh-TW/2-4-detail-detective.mdx
  • src/content/kids/zh-TW/3-1-setting-the-scene.mdx
  • src/content/kids/zh-TW/3-2-show-dont-tell.mdx
  • src/content/kids/zh-TW/3-3-format-finder.mdx
  • src/content/kids/zh-TW/3-4-context-champion.mdx
  • src/content/kids/zh-TW/4-1-pretend-time.mdx
  • src/content/kids/zh-TW/4-2-story-starters.mdx
  • src/content/kids/zh-TW/4-3-character-creator.mdx
  • src/content/kids/zh-TW/4-4-world-builder.mdx
  • src/content/kids/zh-TW/5-1-perfect-prompt.mdx
  • src/content/kids/zh-TW/5-2-fix-it-up.mdx
  • src/content/kids/zh-TW/5-3-prompt-remix.mdx
  • src/content/kids/zh-TW/5-4-graduation-day.mdx
  • src/i18n/request.ts
  • src/lib/date.ts
  • src/lib/i18n/config.ts
  • src/lib/i18n/index.ts
  • src/lib/i18n/locale-resolution.ts
  • src/lib/i18n/locales.ts

Comment on lines +96 to +99
<Compare
before={{ label: "文字風格提示詞", content: "請建立一張貓坐在窗臺上看著外面下雨的圖像" }}
after={{ label: "圖像風格提示詞", content: "橘色虎斑貓,坐在窗臺上,看著下雨,溫馨的室內,柔和的自然光,逼真照片風格,淺景深,4K" }}
/>
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

Compare props are passed as objects, which will break rendering.

before/after should be renderable content, not { label, content } objects, for the current component API.

Also applies to: 117-120, 169-172, 216-219, 227-230, 238-241

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

In `@src/content/book/zh-TW/01-understanding-ai-models.mdx` around lines 96 - 99,
The Compare component is receiving plain objects for its before/after props
(e.g. { label, content }) which the component expects renderable content (string
or JSX) and thus will break rendering; update the Compare usages (the Compare
component instances in this file) to pass renderable values instead of
objects—for example pass a single string or JSX fragment that combines the label
and content (e.g. "文字風格提示詞: 請建立一張貓坐在窗臺上看著外面下雨的圖像" or a small JSX node containing
the label and content), and apply the same fix to the other occurrences
mentioned so before/after are nodes/strings rather than { label, content }
objects.

Comment on lines +26 to +29
<Compare
before={{ label: "沒有角色", content: "解釋量子計算。" }}
after={{ label: "有角色", content: "你是一位物理學教授,擅長將複雜話題講解得通俗易懂。請解釋量子計算。" }}
/>
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

Compare props use an incompatible shape.

Passing objects ({ label, content }) to before/after will break rendering for this component contract. Pass plain renderable text (or JSX) instead.

Fix example
 <Compare 
-  before={{ label: "沒有角色", content: "解釋量子計算。" }}
-  after={{ label: "有角色", content: "你是一位物理學教授,擅長將複雜話題講解得通俗易懂。請解釋量子計算。" }}
+  before="解釋量子計算。"
+  after="你是一位物理學教授,擅長將複雜話題講解得通俗易懂。請解釋量子計算。"
 />

Also applies to: 49-52

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

In `@src/content/book/zh-TW/02-anatomy-of-effective-prompt.mdx` around lines 26 -
29, The Compare component is being passed objects for its before/after props
which violates its contract; update usages of Compare (the instance at lines
around the 02-anatomy-of-effective-prompt.mdx file) to pass plain renderable
content or JSX instead of objects—replace before={{ label: "...", content: "..."
}} and after={{ label: "...", content: "..." }} with simple strings or JSX nodes
(e.g., before="沒有角色: 解釋量子計算。" and after="有角色: 你是一位物理學教授…請解釋量子計算。" or equivalent
JSX fragments) and make the same change for the other occurrence noted (around
lines 49-52).

Comment on lines +13 to +16
<Compare
before={{ label: "隱式(有問題)", content: "把這個弄好一點。" }}
after={{ label: "顯式(有效)", content: "透過以下方式改進這封郵件:\n1. 讓主題行更引人注目\n2. 將段落縮短到最多 2-3 句\n3. 在結尾新增明確的行動號召" }}
/>
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

Compare usage is incompatible with the current component contract.

These calls pass { label, content } objects where Compare expects renderable before/after values. This can break rendering at runtime.

Also applies to: 22-25, 91-94, 119-122, 202-205

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

In `@src/content/book/zh-TW/03-core-prompting-principles.mdx` around lines 13 -
16, The Compare component is being passed plain objects ({ label, content }) but
its contract expects renderable values (strings or JSX/MDX nodes) for the before
and after props; update each Compare invocation (the instances using
before/after props such as the one showing "隱式(有問題)"/"顯式(有效)" and the other
occurrences at the referenced blocks) to pass renderable content instead of
objects — e.g., pass a single string or an MDX node that combines the label and
content (or use a small fragment/JSX element) for before and after so Compare
receives renderable values rather than { label, content } objects. Ensure all
affected Compare usages (the ones noted in the comment) are changed
consistently.

Comment on lines +37 to +60
不同的模型有不同的能力。以下是 2025 年的可用情況:

### 理解模型(輸入 → 分析)

這些模型接受各種媒體類型,併產生文字分析或回覆。

<InfoGrid items={[
{ label: "GPT-4o / GPT-5", description: "文字 + 圖像 + 音訊 → 文字。OpenAI 的旗艦產品,擁有 128K 上下文,強大的創意和推理能力,幻覺率降低。", color: "green" },
{ label: "Claude 4 Sonnet/Opus", description: "文字 + 圖像 → 文字。Anthropic 注重安全的模型,具有高階推理能力,非常適合程式設計和複雜的多步驟任務。", color: "purple" },
{ label: "Gemini 2.5", description: "文字 + 圖像 + 音訊 + 影片 → 文字。Google 的模型,擁有 1M token 上下文,自我事實核查,快速處理程式設計和研究任務。", color: "blue" },
{ label: "LLaMA 4 Scout", description: "文字 + 圖像 + 影片 → 文字。Meta 的開源模型,擁有海量 10M token 上下文,適用於長文件和程式碼庫。", color: "cyan" },
{ label: "Grok 4", description: "文字 + 圖像 → 文字。xAI 的模型,具有即時資料存取和社交媒體整合,提供最新的回覆。", color: "red" }
]} />

### 生成模型(文字 → 媒體)

這些模型根據文字描述建立圖像、音訊或影片。

<InfoGrid items={[
{ label: "DALL-E 3", description: "文字 → 圖像。OpenAI 的圖像產生器,對提示詞描述的準確度很高。", color: "amber" },
{ label: "Midjourney", description: "文字 + 圖像 → 圖像。以藝術品質、風格控制和美學輸出著稱。", color: "pink" },
{ label: "Sora", description: "文字 → 影片。OpenAI 的影片生成模型,根據描述建立影片片段。", color: "red" },
{ label: "Whisper", description: "音訊 → 文字。OpenAI 的語音轉文字工具,跨語言準確率很高。", color: "cyan" }
]} />
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

🌐 Web query:

What are the officially documented current multimodal flagship models (name, supported input modalities, and context window) from OpenAI, Anthropic, Google, Meta, and xAI as of April 2026?

💡 Result:

OpenAI: GPT-5.4 (text + image input, 1M context window) Anthropic: Claude Opus 4.6 (text + image input, 1M context window) Google: Gemini 3.1 Pro (text, images, audio, video input, 1M context window) Meta: Llama 4 Maverick or Llama 4 Scout (text + image input, 10M context window) xAI: grok-4.20 (text + image input, 2M context window)

Citations:


Refactor model/version matrix to avoid future staleness.

The hard-coded "2025 availability" section with specific model versions is already outdated (as of April 2026). Official sources show newer models: GPT-5.4 (OpenAI), Claude Opus 4.6 (Anthropic), Gemini 3.1 Pro (Google), and updated context windows that differ from those listed. Move this matrix to a maintained reference page or use capability-based descriptions with links to each provider's official documentation.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~48-~48: 动词的修饰一般为‘形容词(副词)+地+动词’。您的意思是否是:最新"地"回
Context: ...字 + 圖像 → 文字。xAI 的模型,具有即時資料存取和社交媒體整合,提供最新的回覆。", color: "red" } ]} /> ### 生成模型(文字 ...

(wb4)

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

In `@src/content/book/zh-TW/13-multimodal-prompting.mdx` around lines 37 - 60, The
hard-coded model/version matrix in the InfoGrid items arrays (the entries under
the "理解模型(輸入 → 分析)" and "生成模型(文字 → 媒體)" sections) is now stale; replace these
concrete model/version/context-window claims with capability-based descriptions
and external links, or move the detailed versioned list to a separate maintained
reference page and change the InfoGrid to point to that page (e.g., replace
entries like the GPT-4o / GPT-5, Claude 4 Sonnet/Opus, Gemini 2.5, etc. items
with generic capability text such as "supports text+image" and a provider-docs
URL or a single "See provider compatibility matrix" link). Ensure InfoGrid items
keep their label fields but remove specific versions, token counts, and dated
claims so the content remains accurate over time.

Comment on lines +18 to +313
<TryIt
title="具體性改進器"
description="將一個模糊的提示詞變得具體。注意新增細節如何改變結果的品質。"
prompt={`我有一個需要改進的模糊提示詞。

原始模糊提示詞:"${vaguePrompt}"

透過新增以下內容使這個提示詞變得具體:
1. **受眾**:誰會閱讀/使用這個?
2. **格式**:應該有什麼結構?
3. **長度**:應該多長?
4. **語氣**:什麼樣的聲音或風格?
5. **背景**:情況或目的是什麼?
6. **約束**:有什麼必須包含或必須避免的?

重寫提示詞,包含所有這些細節。`}
/>

## 過載陷阱

**模式**:你試圖在一個提示詞中獲得所有內容——全面、有趣、專業、適合初學者、高階、SEO 優化,而且還要簡短。結果呢?AI 遺漏了一半的要求,或者產生了混亂的內容。

<Compare
before={{ label: "過載的提示詞", content: "寫一篇關於 AI 的部落格文章,要 SEO 優化,包含程式碼範例,要有趣但專業,面向初學者但也有高階技巧,應該是500字但要全面,提到我們的產品,還要有行動號召..." }}
after={{ label: "專注的提示詞", content: "寫一篇500字的部落格文章,向初學者介紹 AI。\n\n要求:\n1. 清楚地解釋一個核心概念\n2. 包含一個簡單的程式碼範例\n3. 以行動號召結尾\n\n語氣:專業但平易近人" }}
/>

**為什麼會發生**:害怕多次互動,或者想一次性"把所有東西都說出來"。但認知過載對 AI 的影響就像對人類一樣——太多相互競爭的要求會導致遺漏。

<InfoGrid items={[
{ label: "限制要求數量", description: "每個提示詞堅持3-5個關鍵要求", example: "專注於:受眾、格式、長度、一個關鍵約束", exampleType: "text", color: "green" },
{ label: "使用編號列表", description: "結構使優先級更清晰", example: "1. 必須有 X,2. 應該有 Y,3. 最好有 Z", exampleType: "text", color: "green" },
{ label: "鏈式提示詞", description: "將複雜任務分解為多個步驟", example: "首先:大綱。然後:起草第1節。然後:起草第2節。", exampleType: "text", color: "green" },
{ label: "無情地優先排序", description: "什麼是必要的 vs. 錦上添花的?", example: "如果我只能做好一件事,那會是什麼?", color: "green" }
]} />

<Callout type="tip" title="學習提示詞鏈">
當單個提示詞變得過載時,[提示詞鏈](/book/11-prompt-chaining)通常是解決方案。將複雜任務分解為一系列專注的提示詞,每個步驟都建立在前一個步驟的基礎上。
</Callout>

## 假設陷阱

**模式**:你引用"之前"的內容,或假設 AI 知道你的專案、公司或之前的對話。它並不知道。

<Compare
before={{ label: "假設有上下文", content: "更新我之前給你看的函式,新增錯誤處理。" }}
after={{ label: "提供上下文", content: "更新這個函式以新增錯誤處理:\n\n```python\ndef calculate_total(items):\n return sum(item.price for item in items)\n```\n\n為空列表和無效項目新增 try/except。" }}
/>

**為什麼會發生**:與 AI 對話感覺像是在和同事交談。但與同事不同,大多數 AI 模型在會話之間沒有持久記憶——每次對話都是從頭開始。

<TryIt
title="上下文完整性檢查"
description="使用這個來驗證你的提示詞在傳送前包含所有必要的上下文。"
prompt={`檢查這個提示詞是否缺少上下文:

"${promptToCheck}"

檢查以下內容:
1. **引用但未包含**:是否提到"程式碼"、"檔案"、"之前"或"上面"但沒有包含實際內容?

2. **假設的知識**:是否假設了對特定專案、公司或情況的瞭解?

3. **隱含要求**:是否有對格式、長度或風格的未說明期望?

4. **缺失背景**:一個聰明的陌生人能理解所問的問題嗎?

列出缺失的內容並建議如何新增。`}
/>

## 引導性問題陷阱

**模式**:你以一種嵌入假設的方式提出問題,得到的是確認而不是洞見。

<Compare
before={{ label: "引導性問題", content: "為什麼 Python 是資料科學最好的程式設計語言?" }}
after={{ label: "中立問題", content: "比較 Python、R 和 Julia 在資料科學工作中的應用。每種語言的優缺點是什麼?什麼時候你會選擇一種而不是其他的?" }}
/>

**為什麼會發生**:我們往往尋求確認,而不是資訊。我們的措辭會不自覺地推向我們期望或想要的答案。

<TryIt
title="偏見檢測器"
description="檢查你的提示詞是否有隱藏的偏見和引導性語言。"
prompt={`分析這個提示詞中的偏見和引導性語言:

"${promptToAnalyze}"

檢查以下內容:
1. **嵌入的假設**:問題是否假設某事是真的?
2. **引導性措辭**:"為什麼 X 好?"是否假設 X 是好的?
3. **缺少替代方案**:是否忽略了其他可能性?
4. **尋求確認**:是在尋求驗證而不是分析嗎?

重寫提示詞使其中立和開放。`}
/>

## 完全信任陷阱

**模式**:AI 的回覆聽起來自信且權威,所以你不加驗證就接受了。但自信並不等於準確。

<InfoGrid items={[
{ label: "未審核的內容", description: "發佈 AI 產生的文字而不進行事實核查", example: "帶有虛構統計資料或假引用的部落格文章", exampleType: "text", color: "red" },
{ label: "未測試的程式碼", description: "在生產環境中使用未經測試的 AI 程式碼", example: "安全漏洞、邊緣情況失敗、微妙的 bug", exampleType: "text", color: "red" },
{ label: "盲目決策", description: "僅基於 AI 分析做出重要決定", example: "基於幻覺市場資料的商業策略", exampleType: "text", color: "red" }
]} />

**為什麼會發生**:AI 即使完全錯誤也聽起來很自信。我們也容易產生"自動化偏見"——過度信任計算機輸出的傾向。

<TryIt
title="驗證提示詞"
description="使用這個讓 AI 標記自己的不確定性和潛在錯誤。"
prompt={`我需要關於以下主題的資訊:${topic}

重要提示:在你的回覆之後,新增一個名為"驗證說明"的部分,包括:

1. **置信度**:你對這些資訊有多確定?(高/中/低)

2. **潛在錯誤**:這個回覆中哪些部分最可能是錯誤的或過時的?

3. **需要驗證的內容**:使用者應該獨立核實哪些具體聲明?

4. **可查閱的來源**:使用者可以在哪裡驗證這些資訊?

對侷限性要誠實。標記不確定性比對錯誤的事情表現出自信要好。`}
/>

## 一次性陷阱

**模式**:你傳送一個提示詞,得到一個平庸的結果,然後得出結論說 AI "不適合"你的用例。但優秀的結果幾乎總是需要迭代。

<Compare
before={{ label: "一次性思維", content: "平庸的輸出 → \"AI 做不了這個\" → 放棄" }}
after={{ label: "迭代思維", content: "平庸的輸出 → 分析問題所在 → 改進提示詞 → 更好的輸出 → 再次改進 → 優秀的輸出" }}
/>

**為什麼會發生**:我們期望 AI 第一次就能讀懂我們的想法。我們不期望 Google 搜尋需要迭代,但卻期望 AI 完美無缺。

<TryIt
title="迭代助手"
description="當你的第一個結果不對時,使用這個來系統地改進它。"
prompt={`我原來的提示詞是:
"${originalPrompt}"

我得到的輸出是:
"${outputReceived}"

問題在於:
"${whatIsWrong}"

幫我迭代:

1. **診斷**:為什麼原來的提示詞產生了這個結果?

2. **缺失元素**:我應該明確說明但沒有說明的是什麼?

3. **修改後的提示詞**:重寫我的提示詞來解決這些問題。

4. **需要注意的事項**:我應該在新輸出中檢查什麼?`}
/>

## 格式忽視陷阱

**模式**:你專注於讓 AI 說什麼,但忘記指定它應該如何格式化。然後當你需要 JSON 時得到了散文,或者當你需要要點列表時得到了一堵文字牆。

<Compare
before={{ label: "未指定格式", content: "從這段文字中提取關鍵資料。" }}
after={{ label: "指定格式", content: "從這段文字中提取關鍵資料,以 JSON 格式輸出:\n\n{\n \"name\": string,\n \"date\": \"YYYY-MM-DD\",\n \"amount\": number,\n \"category\": string\n}\n\n只返回 JSON,不要解釋。" }}
/>

**為什麼會發生**:我們專注於內容而不是結構。但如果你需要程式化地解析輸出,或將其貼上到特定位置,格式和內容一樣重要。

<TryIt
title="格式規範產生器"
description="為你需要的任何輸出類型產生清晰的格式規範。"
prompt={`我需要特定格式的 AI 輸出。

**我要求的內容**:${taskDescription}
**我將如何使用輸出**:${intendedUse}
**首選格式**:${formatType}(JSON、Markdown、CSV、要點列表等)

產生一個我可以新增到提示詞中的格式規範,包括:

1. **精確結構**:包含欄位名稱和類型
2. **範例輸出**:展示格式
3. **約束條件**(例如,"只返回 JSON,不要解釋")
4. **邊緣情況**(如果資料缺失應該輸出什麼)`}
/>

## 上下文窗口陷阱

**模式**:你貼上一個巨大的文件並期望得到全面的分析。但模型有其限制——它們可能會截斷、失去焦點,或在長輸入中遺漏重要細節。

<InfoGrid items={[
{ label: "瞭解你的限制", description: "不同的模型有不同的上下文窗口", example: "GPT-4: 128K tokens, Claude: 200K tokens, Gemini: 1M tokens", exampleType: "text", color: "blue" },
{ label: "分塊處理大輸入", description: "將文件分成可管理的部分", example: "分別分析各章節,然後綜合", exampleType: "text", color: "blue" },
{ label: "前置重要資訊", description: "將關鍵上下文放在提示詞的開頭", example: "關鍵要求在前,背景細節在後", exampleType: "text", color: "blue" },
{ label: "去除冗餘", description: "刪除不必要的上下文", example: "你真的需要整個文件,還是只需要相關部分?", exampleType: "text", color: "blue" }
]} />

<TryIt
title="文件分塊策略"
description="獲取處理超出上下文限制的文件的策略。"
prompt={`我有一個需要分析的大文件:

**文件類型**:${documentType}
**大約長度**:${documentLength}
**我需要提取/分析的內容**:${analysisGoal}
**我使用的模型**:${modelName}

建立一個分塊策略:

1. **如何劃分**:此類文件的邏輯斷點
2. **每個塊中包含什麼**:獨立分析所需的上下文
3. **如何綜合**:組合多個塊的結果
4. **需要注意的事項**:可能跨塊的資訊`}
/>

## 擬人化陷阱

**模式**:你把 AI 當作人類同事對待——期望它"喜歡"任務、記住你或關心結果。它並不會。

<Compare
before={{ label: "擬人化", content: "我相信你會喜歡這個創意專案!我知道你喜歡幫助別人,這對我個人來說真的很重要。" }}
after={{ label: "清晰直接", content: "根據以下規格寫一個創意短篇故事:\n- 類型:科幻\n- 長度:500字\n- 語氣:充滿希望\n- 必須包含:一個反轉結局" }}
/>

**為什麼會發生**:AI 的回覆如此像人類,以至於我們自然會陷入社交模式。但情感訴求不會讓 AI 更努力——清晰的指令才會。

<Callout type="info" title="什麼才真正有幫助">
與其進行情感訴求,不如專注於:清晰的要求、好的範例、具體的約束和明確的成功標準。這些能改善輸出。"請真的努力嘗試"則不能。
</Callout>

## 安全忽視陷阱

**模式**:在急於讓事情運轉起來的過程中,你在提示詞中包含了敏感資訊——API 密鑰、密碼、個人資料或專有資訊。

<InfoGrid items={[
{ label: "提示詞中的密鑰", description: "API 密鑰、密碼、token 貼上到提示詞中", example: "\"使用這個 API 密鑰:sk-abc123...\"", color: "red" },
{ label: "個人資料", description: "包含傳送到第三方伺服器的個人身份資訊", example: "提示詞中的客戶姓名、電子郵件、地址", exampleType: "text", color: "red" },
{ label: "未清理的使用者輸入", description: "將使用者輸入直接傳遞到提示詞中", example: "提示詞注入漏洞", exampleType: "text", color: "red" },
{ label: "專有資訊", description: "商業機密或機密資料", example: "內部策略、未發佈的產品細節", exampleType: "text", color: "red" }
]} />

**為什麼會發生**:專注於功能而忽視安全。但請記住:提示詞通常傳送到外部伺服器,可能會被記錄,並可能用於訓練。

<TryIt
title="安全審查"
description="在傳送前檢查你的提示詞是否存在安全問題。"
prompt={`審查此提示詞的安全問題:

"${promptToReview}"

檢查以下內容:

1. **暴露的密鑰**:API 密鑰、密碼、token、憑證
2. **個人資料**:姓名、電子郵件、地址、電話號碼、身份證號
3. **專有資訊**:商業機密、內部策略、機密資料
4. **注入風險**:可能操縱提示詞的使用者輸入

對於發現的每個問題:
- 解釋風險
- 建議如何編輯或保護資訊
- 推薦更安全的替代方案`}
/>

## 幻覺忽視陷阱

**模式**:你要求引用、統計資料或具體事實,並假設它們是真實的,因為 AI 自信地陳述了它們。但 AI 經常編造聽起來可信的資訊。

<Compare
before={{ label: "盲目信任", content: "給我5個關於遠程工作生產力的統計資料和來源。" }}
after={{ label: "承認侷限性", content: "關於遠程工作生產力,我們知道些什麼?對於你提到的任何統計資料,請說明它們是有據可查的發現還是更不確定的。我會獨立驗證任何具體數字。" }}
/>

**為什麼會發生**:AI 產生的文字聽起來很權威。它不"知道"自己什麼時候在編造——它是在預測可能的文字,而不是檢索經過驗證的事實。

<TryIt
title="抗幻覺查詢"
description="建構你的提示詞以最小化幻覺風險並標記不確定性。"
prompt={`我需要關於以下主題的資訊:${topic}

請遵循這些指南以最小化錯誤:

1. **堅持使用公認的事實**。避免難以驗證的晦澀說法。

2. **標記不確定性**。如果你對某事不確定,請說"我認為..."或"這可能需要驗證..."

3. **不要編造來源**。除非你確定它們存在,否則不要引用具體的論文、書籍或網址。相反,描述在哪裡可以找到這類資訊。

4. **承認知識限制**。如果我的問題涉及你訓練資料之後的事件,請說明。

5. **區分事實和推斷**。清楚地區分"X 是真的"和"基於 Y,X 可能是真的"。

現在,請記住這些指南:${actualQuestion}`}
/>
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

file="src/content/book/zh-TW/15-common-pitfalls.mdx"

echo "Unescaped placeholders (likely runtime interpolation):"
rg -nP '(?<!\\)\$\{[A-Za-z_][A-Za-z0-9_]*\}' "$file"

echo
echo "Escaped placeholders (literal prompt variables):"
rg -n '\\\$\{[A-Za-z_][A-Za-z0-9_]*\}' "$file"

Repository: f/prompts.chat

Length of output: 681


Escape placeholder variables in prompt templates to prevent runtime interpolation errors.

Unescaped ${...} inside template literals will be evaluated as JavaScript expressions, causing ReferenceError failures when variables are undefined. These should be literal placeholders (\${...}) so users can replace them when using the prompts.

17 instances found across the file—apply this pattern consistently:

Fix pattern
- 原始模糊提示詞:"${vaguePrompt}"
+ 原始模糊提示詞:"\${vaguePrompt}"

- "${promptToCheck}"
+ "\${promptToCheck}"

- 我需要關於以下主題的資訊:${topic}
+ 我需要關於以下主題的資訊:\${topic}
🧰 Tools
🪛 LanguageTool

[uncategorized] ~41-~41: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...要 SEO 優化,包含程式碼範例,要有趣但專業,面向初學者但也有高階技巧,應該是500字但要全面,提到我們的產品,還要有行動號召..." }} after={{ l...

(wa5)


[uncategorized] ~42-~42: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ... after={{ label: "專注的提示詞", content: "寫一篇500字的部落格文章,向初學者介紹 AI。\n\n要求:\n1. 清楚地解釋一個核心概念...

(wa5)


[uncategorized] ~50-~50: 您的意思是“"不"驟”?
Context: ...label: "鏈式提示詞", description: "將複雜任務分解為多個步驟", example: "首先:大綱。然後:起草第1節。然後:起草第2節。",...

(BU)


[uncategorized] ~50-~50: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...: "將複雜任務分解為多個步驟", example: "首先:大綱。然後:起草第1節。然後:起草第2節。", exampleType: "text", color:...

(wa5)


[uncategorized] ~50-~50: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...解為多個步驟", example: "首先:大綱。然後:起草第1節。然後:起草第2節。", exampleType: "text", color: "green" ...

(wa5)


[uncategorized] ~90-~90: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...失的內容並建議如何新增。`} /> ## 引導性問題陷阱 模式:你以一種嵌入假設的方式提出問題,得到的是確認而不是洞見。 <Compare be...

(wa5)


[uncategorized] ~94-~94: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...和 Julia 在資料科學工作中的應用。每種語言的優缺點是什麼?什麼時候你會選擇一種而不是其他的?" }} /> 為什麼會發生:我們往往尋求確認,而不是資...

(wa5)


[uncategorized] ~181-~181: "堵"不能与“文字”搭配,请换量词
Context: ...如何格式化。然後當你需要 JSON 時得到了散文,或者當你需要要點列表時得到了一堵文字牆。 <Compare before={{ label: "未指定格...

(wa5)


[uncategorized] ~242-~242: 数词与名词之间一般应存在量词,可能缺少量词。
Context: ...ntent: "根據以下規格寫一個創意短篇故事:\n- 類型:科幻\n- 長度:500字\n- 語氣:充滿希望\n- 必須包含:一個反轉結局" }} /> **為什麼...

(wa5)


[uncategorized] ~310-~310: 您不可用“是”来表达个形容词。大部分人都平常用“很”来代替“是”。您是不是想表达"很真的"?
Context: ...你訓練資料之後的事件,請說明。 5. 區分事實和推斷。清楚地區分"X 是真的"和"基於 Y,X 可能是真的"。 現在,請記住這些指南:${actualQu...

(SHI_ADHECTIVE_ERROR)


[uncategorized] ~310-~310: 您不可用“是”来表达个形容词。大部分人都平常用“很”来代替“是”。您是不是想表达"很真的"?
Context: ... 5. 區分事實和推斷。清楚地區分"X 是真的"和"基於 Y,X 可能是真的"。 現在,請記住這些指南:${actualQuestion}`} /> #...

(SHI_ADHECTIVE_ERROR)

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

In `@src/content/book/zh-TW/15-common-pitfalls.mdx` around lines 18 - 313, The
template strings in several JSX components (e.g., TryIt prompts, Compare
content, Format/Prompt generators) contain unescaped ${...} placeholders which
will be evaluated at runtime and can throw ReferenceError; update every prompt
prop and inline template literal to escape placeholders by replacing ${...} with
\${...} so they remain literal placeholders (there are ~17 occurrences across
TryIt, Compare, and the prompt strings inside Format/Prompt generator blocks);
search for occurrences inside the TryIt.prompt, Compare.before/after.content,
and any prompt={`...`} or multi-line string literals and replace each
${variableLike} with \${variableLike} consistently.

Comment on lines +45 to +51
<PromptVsMistake
question="哪個提示詞結合了最多的技能?"
good="我是一個喜歡太空的10歲孩子。假裝你是一個友好的宇航員,告訴我5個關於土星的驚人事實。讓它令人興奮,用孩子能理解的簡單詞語!"
bad="告訴我關於土星"
explanation="這個提示詞有:背景(10歲,喜歡太空),角色扮演(友好的宇航員),格式(5個事實),個性(令人興奮),和清晰(簡單詞語)!"
promiMessage="這是大師級的提示詞!它準確地告訴我你需要什麼!"
/>
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 | 🟠 Major

PromptVsMistake 使用了錯誤的 props 名稱。

Line 45 與 Line 57 目前傳入 good/bad/question/promiMessage,但 src/components/kids/elements/prompt-vs-mistake.tsx 介面是 mistake/correction/explanation/title。這會導致內容不顯示或顯示不完整。

Also applies to: 57-63

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

In `@src/content/kids/zh-TW/5-1-perfect-prompt.mdx` around lines 45 - 51, The
PromptVsMistake component is being passed the wrong prop names
(question/good/bad/promiMessage) but its interface expects
title/mistake/correction/explanation; update the usage in the MDX so that
PromptVsMistake receives title (was question), mistake (was bad), correction
(was good), and explanation (keep or map accordingly), and remove or map
promiMessage into the correct prop or into the component's children if needed;
verify src/components/kids/elements/prompt-vs-mistake.tsx to confirm exact prop
names and adjust all occurrences (including the block at lines ~57-63) to match.

Comment on lines +69 to +75
<DragDropPrompt
title="完美提示詞"
instruction="把所有元素排列成一個完美的提示詞"
pieces={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
correctOrder={[0, 1, 2, 3]}
successMessage="完美!背景、格式、例子和風格都在一個提示詞裡!"
/>
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

DragDropPrompt props 與型別不相容,互動完成判斷會失效。

Line 69-75 傳入 pieces/correctOrder/instruction/successMessage,但元件介面是 initial/correct/instructions/explanation,且 correct 比較的是文字陣列,不是索引陣列。

🔧 參考修正
-<DragDropPrompt
-  title="完美提示詞"
-  instruction="把所有元素排列成一個完美的提示詞"
-  pieces={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
-  correctOrder={[0, 1, 2, 3]}
-  successMessage="完美!背景、格式、例子和風格都在一個提示詞裡!"
-/>
+<DragDropPrompt
+  title="完美提示詞"
+  instructions="把所有元素排列成一個完美的提示詞"
+  initial={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
+  correct={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
+  explanation="完美!背景、格式、例子和風格都在一個提示詞裡!"
+/>
📝 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
<DragDropPrompt
title="完美提示詞"
instruction="把所有元素排列成一個完美的提示詞"
pieces={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
correctOrder={[0, 1, 2, 3]}
successMessage="完美!背景、格式、例子和風格都在一個提示詞裡!"
/>
<DragDropPrompt
title="完美提示詞"
instructions="把所有元素排列成一個完美的提示詞"
initial={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
correct={["我在為喜歡釣魚的爸爸做生日卡片。", "給我3個有趣的釣魚笑話", "像'魚為什麼臉紅了?因為它看到了海底!'", "適合家庭而且短!"]}
explanation="完美!背景、格式、例子和風格都在一個提示詞裡!"
/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/kids/zh-TW/5-1-perfect-prompt.mdx` around lines 69 - 75, The
DragDropPrompt usage passes props pieces/correctOrder/instruction/successMessage
but the component expects initial/correct/instructions/explanation and compares
correct as a string-array (not index-array); fix the call to use the component's
API by renaming props: initial={["我在為喜歡釣魚的爸爸做生日卡片。", ...]}
instructions="把所有元素排列成一個完美的提示詞"
correct={["我在為喜歡釣魚的爸爸做生日卡片。","給我3個有趣的釣魚笑話","像'魚為什麼臉紅了?因為它看到了海底!'","適合家庭而且短!"]}
explanation="完美!背景、格式、例子和風格都在一個提示詞裡!" so the component's correct comparison
(array of strings) works; alternatively, if you prefer index-based correctOrder,
update DragDropPrompt's prop types and internal comparison logic (in the
DragDropPrompt definition) to accept correctOrder:number[] and compare indices
instead.

Comment on lines +81 to +92
<MagicWords
sentence="我是一個需要___幫助的___。假裝你是一個___,給我像___一樣的___。讓它___!"
blanks={[
{ hint: "👤 你是誰", answers: ["年輕藝術家", "好奇學生", "創意作家", "自然愛好者", "笑話收集者"] },
{ hint: "📚 你的目標", answers: ["學校專案", "創意故事", "學習新東西", "讓某人笑", "計劃冒險"] },
{ hint: "🎭 一個角色", answers: ["友好的專家", "傻傻的喜劇演員", "聰明的老師", "創意發明家", "講故事的奶奶"] },
{ hint: "🔢 你需要什麼", answers: ["5個有趣的想法", "3個有用的技巧", "一些創意例子", "一個短故事", "一個簡單的解釋"] },
{ hint: "💡 一個例子", answers: ["'超級明星策略'", "'快樂幫手技巧'", "'魔法時刻'", "'神奇詞語'", "'創意火花'"] },
{ hint: "✨ 風格", answers: ["有趣又容易理解", "令人興奮又難忘", "創意又多彩", "有用又鼓勵人", "傻但有用"] }
]}
successMessage="太棒了!這是一個有所有元素的真正大師提示詞!"
/>
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

MagicWords props 介面不匹配,互動可能直接失效。

Line 81-92 使用 sentence/blanks/successMessage,但 src/components/kids/elements/magic-words.tsx 介面是 title/words/explanation。目前配置下,提交檢查流程很可能無法正常運作。

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

In `@src/content/kids/zh-TW/5-1-perfect-prompt.mdx` around lines 81 - 92, The
MagicWords usage passes props sentence, blanks, successMessage but the
MagicWords component expects title, words, explanation (see component in
magic-words.tsx); fix by either (A) updating the JSX in
src/content/kids/zh-TW/5-1-perfect-prompt.mdx to pass title (string), words
(array/object matching the component's shape) and explanation (string) instead
of sentence/blanks/successMessage, or (B) modify the MagicWords component's
props interface (title/words/explanation) to accept the current keys
(sentence/blanks/successMessage) and map them internally to the component's
expected variables (or add prop aliases) so the interactive behavior works.
Ensure the referenced symbols MagicWords, sentence/blanks/successMessage, and
title/words/explanation are aligned.

Comment on lines +65 to +73
sentence="我是一個想___的___。假裝你是一個___,幫我___。給我像'___'的東西。讓它___又___!"
blanks={[
{ hint: "👤 你是誰", answers: ["有創意的孩子", "年輕探險家", "好奇的學習者", "有抱負的藝術家", "未來的發明家"] },
{ hint: "🎯 你的目標", answers: ["創造驚人的東西", "學習新東西", "解決問題", "讓人微笑", "開始冒險"] },
{ hint: "🎭 有用的角色", answers: ["聰明的導師", "有趣的教練", "創意向導", "有耐心的老師", "鼓勵人的朋友"] },
{ hint: "📚 你需要什麼", answers: ["3個很棒的想法", "一步步的計劃", "鼓舞人心的故事", "有用的技巧", "創意專案"] },
{ hint: "💡 一個例子", answers: ["用紙箱建火箭!", "寫一首關於善良的歌", "設計夢想樹屋", "創造新遊戲", "發明有用的機器人"] },
{ hint: "✨ 風格1", answers: ["有趣", "鼓舞人心", "創意", "令人興奮", "鼓勵人"] },
{ hint: "🌟 風格2", answers: ["容易跟著做", "充滿想象", "令人難忘", "獨特", "快樂"] }
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 | 🟠 Major

Swap the first two MagicWords blanks.

The sentence template expects goal first and identity second (想___的___), but the blanks array provides 你是誰 before 你的目標. That makes the completed sentence read backwards and teaches the wrong structure.

🔧 Suggested fix
   blanks={[
-    { hint: "👤 你是誰", answers: ["有創意的孩子", "年輕探險家", "好奇的學習者", "有抱負的藝術家", "未來的發明家"] },
-    { hint: "🎯 你的目標", answers: ["創造驚人的東西", "學習新東西", "解決問題", "讓人微笑", "開始冒險"] },
+    { hint: "🎯 你的目標", answers: ["創造驚人的東西", "學習新東西", "解決問題", "讓人微笑", "開始冒險"] },
+    { hint: "👤 你是誰", answers: ["有創意的孩子", "年輕探險家", "好奇的學習者", "有抱負的藝術家", "未來的發明家"] },
📝 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
sentence="我是一個想______。假裝你是一個___,幫我___。給我像'___'的東西。讓它______!"
blanks={[
{ hint: "👤 你是誰", answers: ["有創意的孩子", "年輕探險家", "好奇的學習者", "有抱負的藝術家", "未來的發明家"] },
{ hint: "🎯 你的目標", answers: ["創造驚人的東西", "學習新東西", "解決問題", "讓人微笑", "開始冒險"] },
{ hint: "🎭 有用的角色", answers: ["聰明的導師", "有趣的教練", "創意向導", "有耐心的老師", "鼓勵人的朋友"] },
{ hint: "📚 你需要什麼", answers: ["3個很棒的想法", "一步步的計劃", "鼓舞人心的故事", "有用的技巧", "創意專案"] },
{ hint: "💡 一個例子", answers: ["用紙箱建火箭!", "寫一首關於善良的歌", "設計夢想樹屋", "創造新遊戲", "發明有用的機器人"] },
{ hint: "✨ 風格1", answers: ["有趣", "鼓舞人心", "創意", "令人興奮", "鼓勵人"] },
{ hint: "🌟 風格2", answers: ["容易跟著做", "充滿想象", "令人難忘", "獨特", "快樂"] }
sentence="我是一個想______。假裝你是一個___,幫我___。給我像'___'的東西。讓它______!"
blanks={[
{ hint: "🎯 你的目標", answers: ["創造驚人的東西", "學習新東西", "解決問題", "讓人微笑", "開始冒險"] },
{ hint: "👤 你是誰", answers: ["有創意的孩子", "年輕探險家", "好奇的學習者", "有抱負的藝術家", "未來的發明家"] },
{ hint: "🎭 有用的角色", answers: ["聰明的導師", "有趣的教練", "創意向導", "有耐心的老師", "鼓勵人的朋友"] },
{ hint: "📚 你需要什麼", answers: ["3個很棒的想法", "一步步的計劃", "鼓舞人心的故事", "有用的技巧", "創意專案"] },
{ hint: "💡 一個例子", answers: ["用紙箱建火箭!", "寫一首關於善良的歌", "設計夢想樹屋", "創造新遊戲", "發明有用的機器人"] },
{ hint: "✨ 風格1", answers: ["有趣", "鼓舞人心", "創意", "令人興奮", "鼓勵人"] },
{ hint: "🌟 風格2", answers: ["容易跟著做", "充滿想象", "令人難忘", "獨特", "快樂"] }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/content/kids/zh-TW/5-4-graduation-day.mdx` around lines 65 - 73, The
MagicWords template's sentence "我是一個想___的___。..." requires the goal (想___) to be
the first blank and identity (的___) second, so swap the first two entries in the
blanks array: move the object with hint "🎯 你的目標" to index 0 and the object with
hint "👤 你是誰" to index 1 so the blanks order matches the sentence; update the
blanks array where defined to reflect this swap (refer to the sentence variable
and the blanks array entries).

Comment on lines +43 to +57
const languages = acceptLanguage
.split(",")
.map((part) => {
const [lang, qPart] = part.trim().split(";");
const q = qPart ? parseFloat(qPart.split("=")[1]) : 1;
return { lang: lang.trim(), q };
})
.sort((a, b) => b.q - a.q);

for (const { lang } of languages) {
const detectedLocale = normalizeRequestedLocale(lang);
if (detectedLocale) {
return detectedLocale;
}
}
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 | 🟠 Major

Skip rejected Accept-Language entries.

q=0 means “not acceptable”, but this parser still keeps those entries and can resolve something like zh-TW;q=0 to zh-TW. That can flip users onto a locale they explicitly rejected.

🔧 Suggested fix
   const languages = acceptLanguage
     .split(",")
     .map((part) => {
       const [lang, qPart] = part.trim().split(";");
-      const q = qPart ? parseFloat(qPart.split("=")[1]) : 1;
-      return { lang: lang.trim(), q };
+      const rawQ = qPart ? Number.parseFloat(qPart.split("=")[1] ?? "") : 1;
+      return {
+        lang: lang.trim(),
+        q: Number.isFinite(rawQ) ? rawQ : 0,
+      };
     })
+    .filter(({ lang, q }) => lang && q > 0)
     .sort((a, b) => b.q - a.q);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/i18n/locale-resolution.ts` around lines 43 - 57, The current
Accept-Language parser builds the languages array from acceptLanguage and
includes entries with q=0 (unacceptable); update the parsing pipeline so entries
with q <= 0 are skipped before attempting resolution: when splitting
acceptLanguage into parts, compute q safely (handle missing/NaN) and filter out
any items where q <= 0 (or q === 0) before sorting and iterating; then continue
iterating over the filtered languages and call normalizeRequestedLocale(lang) as
before so rejected locales like "zh-TW;q=0" are ignored.

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