[{"data":1,"prerenderedAt":524},["ShallowReactive",2],{"content-\u002Fplugins\u002Faio-epub-translate\u002Faio-epub-manage":3,"children-\u002Fplugins\u002Faio-epub-translate\u002Faio-epub-manage":523},{"id":4,"title":5,"author":6,"body":7,"budget_tier":6,"build_tags":6,"created":6,"description":514,"document_type":515,"extension":516,"game":6,"install":36,"investment_tier":6,"league":6,"meta":517,"navigation":518,"patch":6,"path":519,"plugin":24,"profit_per_hour":6,"ratings":6,"seo":520,"skills_count":6,"status":6,"stem":521,"strategy_tier":6,"tags":6,"updated":6,"version":6,"weight":6,"__hash__":522},"content\u002Fplugins\u002Faio-epub-translate\u002Faio-epub-manage.md","aio-epub-manage",null,{"type":8,"value":9,"toc":485},"minimark",[10,37,42,45,68,73,83,87,92,98,102,108,112,118,122,129,135,139,145,168,172,175,181,185,191,195,201,205,211,215,221,225,228,234,238,241,247,251,254,260,264,267,273,281,285,288,294,307,311,317,325,329,332,338,342,345,351,355,358,364,368,371,377,386,390,393,399,403,469],[11,12,13],"blockquote",{},[14,15,16,17,25,26,25,30,33,34],"p",{},"From plugin ",[18,19,21],"a",{"href":20},"\u002Fplugins\u002Faio-epub-translate",[22,23,24],"strong",{},"aio-epub-translate"," · ",[27,28,29],"code",{},"v4.0.0",[22,31,32],{},"Install:"," ",[27,35,36],{},"\u002Fplugin install aio-epub-translate@aiocean-plugins",[38,39,41],"h1",{"id":40},"epub-manage-book-management","EPUB Manage — Book Management",[14,43,44],{},"Browse, monitor, and manage EPUB books on the translation server.",[11,46,47],{},[14,48,49,52,53,56,57,59,60,63,64,67],{},[22,50,51],{},"Hub skill",": Dùng skill này để điều hướng. Cần upload? → ",[27,54,55],{},"aio-epub-upload",". Cần dịch? → ",[27,58,24],{},". Cần kiểm tra? → ",[27,61,62],{},"aio-epub-quality",". Cần xuất? → ",[27,65,66],{},"aio-epub-export",".",[69,70,72],"h2",{"id":71},"api-setup","API Setup",[74,75,81],"pre",{"className":76,"code":78,"language":79,"meta":80},[77],"language-python","import json, urllib.request, os\n\nBASE = \"https:\u002F\u002Fread-api.aiocean.dev\u002FListBooks.v1.BookService\"\nKEY = os.environ.get(\"AIO_EPUB_API_KEY\", \"duocnv\")\n\ndef api(method, body):\n    data = json.dumps(body).encode('utf-8')\n    req = urllib.request.Request(f\"{BASE}\u002F{method}\", data=data, headers={\n        \"Content-Type\": \"application\u002Fjson\",\n        \"X-License-Key\": KEY\n    })\n    with urllib.request.urlopen(req) as resp:\n        return json.loads(resp.read())\n","python","",[27,82,78],{"__ignoreMap":80},[69,84,86],{"id":85},"operations","Operations",[88,89,91],"h3",{"id":90},"list-books","List Books",[74,93,96],{"className":94,"code":95,"language":79,"meta":80},[77],"books = api(\"ListBooks\", {\"pageSize\": 50, \"pageNumber\": 1})\nfor book in books.get(\"books\", []):\n    print(f\"  {book['id'][:40]}...\")\n    print(f\"    Title: {book['title']}\")\n    print(f\"    Author: {book['author']}\")\n",[27,97,95],{"__ignoreMap":80},[88,99,101],{"id":100},"get-book-info","Get Book Info",[74,103,106],{"className":104,"code":105,"language":79,"meta":80},[77],"book = api(\"GetBook\", {\"bookId\": BOOK_ID})\nb = book[\"book\"]\nprint(f\"Title: {b['title']}\")\nprint(f\"Author: {b['author']}\")\nprint(f\"Language: {b['language']}\")\nprint(f\"Pages: {b.get('pageCount', 'N\u002FA')}\")\n",[27,107,105],{"__ignoreMap":80},[88,109,111],{"id":110},"view-table-of-contents","View Table of Contents",[74,113,116],{"className":114,"code":115,"language":79,"meta":80},[77],"toc = api(\"GetTableOfContent\", {\"bookId\": BOOK_ID})\ndef print_toc(items, indent=0):\n    for item in items:\n        prefix = \"  \" * indent\n        print(f\"{prefix}{item['title']} -> {item['filePath']}\")\n        if item.get(\"children\"):\n            print_toc(item[\"children\"], indent + 1)\n\nprint_toc(toc[\"tableOfContent\"][\"items\"])\n",[27,117,115],{"__ignoreMap":80},[88,119,121],{"id":120},"update-toc-structured","Update TOC (structured)",[14,123,124,125,128],{},"Dùng ",[27,126,127],{},"UpdateTableOfContent"," để lưu TOC đã chỉnh sửa — không cần XML:",[74,130,133],{"className":131,"code":132,"language":79,"meta":80},[77],"# Workflow: get → chỉnh sửa items → save\ntoc = api(\"GetTableOfContent\", {\"bookId\": BOOK_ID})\nitems = toc[\"tableOfContent\"][\"items\"]\n\n# Ví dụ: sửa title của chapter đầu tiên\nitems[0][\"title\"] = \"Chapter 1: The Beginning\"\n\nresult = api(\"UpdateTableOfContent\", {\n    \"bookId\": BOOK_ID,\n    \"tableOfContent\": {\"items\": items}\n})\nprint(result[\"message\"])\n",[27,134,132],{"__ignoreMap":80},[88,136,138],{"id":137},"generate-toc-với-ai","Generate TOC với AI",[74,140,143],{"className":141,"code":142,"language":79,"meta":80},[77],"result = api(\"GenerateTOC\", {\n    \"bookId\": BOOK_ID,\n    \"modelId\": \"claude-sonnet-4-6\",\n    \"language\": \"vi\"\n})\n# Note: GenerateTOC trả về {\"toc\": ...}, khác với GetTableOfContent {\"tableOfContent\": ...}\nitems = result[\"toc\"][\"items\"]\n# Save bằng UpdateTableOfContent (same pattern as structured update above)\napi(\"UpdateTableOfContent\", {\"bookId\": BOOK_ID, \"tableOfContent\": {\"items\": items}})\n",[27,144,142],{"__ignoreMap":80},[11,146,147],{},[14,148,149,152,153,156,157,159,160,163,164,167],{},[22,150,151],{},"Tip",": ",[27,154,155],{},"GetTableOfContent"," + ",[27,158,127],{}," là cặp API chính để đọc\u002Fghi TOC với structured data. ",[27,161,162],{},"GetTOC","\u002F",[27,165,166],{},"UpdateTOC"," (raw NCX XML) chỉ dùng khi cần thao tác XML trực tiếp ở mức thấp.",[88,169,171],{"id":170},"repair-book-metadata","Repair Book Metadata",[14,173,174],{},"Dùng khi cover image không hiển thị hoặc metadata thiếu (tác giả, ngôn ngữ...):",[74,176,179],{"className":177,"code":178,"language":79,"meta":80},[77],"result = api(\"RepairBookMeta\", {\"bookId\": BOOK_ID})\nprint(result[\"message\"])\nprint(f\"Cover URL: {result.get('coverImageUrl', 'none')}\")\n",[27,180,178],{"__ignoreMap":80},[88,182,184],{"id":183},"check-translation-progress","Check Translation Progress",[74,186,189],{"className":187,"code":188,"language":79,"meta":80},[77],"progress = api(\"GetTranslationProgress\", {\"bookId\": BOOK_ID})\np = progress[\"progress\"]\nprint(f\"Overall: {p['translationPercentage']:.1f}% ({p['translatedElements']}\u002F{p['totalContentElements']})\")\n\nfor fp in p.get(\"fileProgress\", []):\n    pct = fp[\"translationPercentage\"]\n    total = fp[\"totalContentElements\"]\n    done = fp[\"translatedElements\"]\n    status = \"DONE\" if pct == 100 else f\"{pct:.0f}%\"\n    indicator = \"✓\" if pct == 100 else (\"◐\" if pct > 0 else \"○\")\n    print(f\"  {indicator} {fp['filePath']}: {status} ({done}\u002F{total})\")\n",[27,190,188],{"__ignoreMap":80},[88,192,194],{"id":193},"viewupdate-guidelines","View\u002FUpdate Guidelines",[74,196,199],{"className":197,"code":198,"language":79,"meta":80},[77],"# View book guideline\ngl = api(\"GetGuideline\", {\"bookId\": BOOK_ID})\nprint(gl[\"guideline\"])\n\n# Update book guideline\napi(\"UpdateGuideline\", {\n    \"bookId\": BOOK_ID,\n    \"guideline\": \"Updated guideline text...\"\n})\n\n# View chapter guideline\ncgl = api(\"GetChapterGuideline\", {\n    \"bookId\": BOOK_ID,\n    \"chapterPath\": FILE_PATH\n})\nif cgl.get(\"exists\"):\n    print(cgl[\"guideline\"])\n\n# Update chapter guideline\napi(\"UpdateChapterGuideline\", {\n    \"bookId\": BOOK_ID,\n    \"chapterPath\": FILE_PATH,\n    \"guideline\": \"Chapter-specific guideline...\"\n})\n",[27,200,198],{"__ignoreMap":80},[88,202,204],{"id":203},"generate-ai-guideline","Generate AI Guideline",[74,206,209],{"className":207,"code":208,"language":79,"meta":80},[77],"result = api(\"GenerateGuideline\", {\n    \"bookId\": BOOK_ID,\n    \"sourceLanguage\": \"en\",\n    \"targetLanguage\": \"vi\",\n    \"templateName\": \"literary\",\n    \"modelId\": \"\"\n})\nprint(result[\"guideline\"])\n",[27,210,208],{"__ignoreMap":80},[88,212,214],{"id":213},"delete-book","Delete Book",[74,216,219],{"className":217,"code":218,"language":79,"meta":80},[77],"result = api(\"DeleteBook\", {\"bookId\": BOOK_ID})\nprint(result[\"message\"])\n",[27,220,218],{"__ignoreMap":80},[88,222,224],{"id":223},"fork-book","Fork Book",[14,226,227],{},"Nhân bản sách để tạo bản dịch riêng mà không ảnh hưởng bản gốc:",[74,229,232],{"className":230,"code":231,"language":79,"meta":80},[77],"result = api(\"ForkBook\", {\n    \"bookId\": BOOK_ID,\n    \"title\": \"My Translation of Book Title\"\n})\nnew_book_id = result[\"bookId\"]\nprint(f\"Forked: {new_book_id}\")\n",[27,233,231],{"__ignoreMap":80},[88,235,237],{"id":236},"publish-unpublish-book","Publish \u002F Unpublish Book",[14,239,240],{},"Đăng sách lên community hoặc gỡ xuống:",[74,242,245],{"className":243,"code":244,"language":79,"meta":80},[77],"# Publish\nresult = api(\"PublishBook\", {\"bookId\": BOOK_ID})\nprint(result[\"message\"])\n\n# Unpublish\nresult = api(\"UnpublishBook\", {\"bookId\": BOOK_ID})\nprint(result[\"message\"])\n",[27,246,244],{"__ignoreMap":80},[88,248,250],{"id":249},"list-community-books","List Community Books",[14,252,253],{},"Duyệt sách đã được cộng đồng đăng:",[74,255,258],{"className":256,"code":257,"language":79,"meta":80},[77],"books = api(\"ListCommunityBooks\", {\"pageSize\": 50, \"pageNumber\": 1})\nfor book in books.get(\"books\", []):\n    print(f\"  {book['title']} — {book['author']}\")\n",[27,259,257],{"__ignoreMap":80},[88,261,263],{"id":262},"reset-book","Reset Book",[14,265,266],{},"Reset toàn bộ sách về trạng thái gốc (xóa folder unpacked, giải nén lại, prepare lại):",[74,268,271],{"className":269,"code":270,"language":79,"meta":80},[77],"result = api(\"ResetBook\", {\"bookId\": BOOK_ID})\nprint(result[\"message\"])\n",[27,272,270],{"__ignoreMap":80},[11,274,275],{},[14,276,277,280],{},[22,278,279],{},"Cẩn thận",": Mất toàn bộ bản dịch và markings. Dùng khi sách bị lỗi nghiêm trọng.",[88,282,284],{"id":283},"reset-chapter","Reset Chapter",[14,286,287],{},"Reset 1 chapter — xóa bản dịch VÀ markings, trả về trạng thái gốc:",[74,289,292],{"className":290,"code":291,"language":79,"meta":80},[77],"result = api(\"ResetChapter\", {\n    \"bookId\": BOOK_ID,\n    \"filePath\": FILE_PATH\n})\nprint(result[\"message\"])\n",[27,293,291],{"__ignoreMap":80},[11,295,296],{},[14,297,298,299,302,303,306],{},"Khác với ",[27,300,301],{},"RemarkChapter"," (chỉ xóa bản dịch, giữ markings). Dùng ",[27,304,305],{},"ResetChapter"," khi cần re-mark lại từ đầu.",[88,308,310],{"id":309},"remark-chapter-remove-translations-keep-markings","Remark Chapter (remove translations, keep markings)",[74,312,315],{"className":313,"code":314,"language":79,"meta":80},[77],"result = api(\"RemarkChapter\", {\n    \"bookId\": BOOK_ID,\n    \"filePath\": FILE_PATH\n})\nprint(result[\"message\"])\n",[27,316,314],{"__ignoreMap":80},[11,318,319],{},[14,320,321,322,324],{},"Sau khi remark, dùng ",[27,323,24],{}," để dịch lại chương này.",[88,326,328],{"id":327},"view-page-content","View Page Content",[14,330,331],{},"Xem nội dung HTML của 1 trang:",[74,333,336],{"className":334,"code":335,"language":79,"meta":80},[77],"page = api(\"GetPage\", {\n    \"bookId\": BOOK_ID,\n    \"filePath\": FILE_PATH\n})\nprint(page[\"content\"][:2000])  # Preview first 2000 chars\n",[27,337,335],{"__ignoreMap":80},[88,339,341],{"id":340},"view-llm-usage-stats","View LLM Usage Stats",[14,343,344],{},"Xem thống kê token và chi phí cho 1 cuốn sách:",[74,346,349],{"className":347,"code":348,"language":79,"meta":80},[77],"usage = api(\"GetLLMUsage\", {\"bookId\": BOOK_ID})\nfor entry in usage.get(\"usage\", []):\n    print(f\"  Model: {entry['model']}\")\n    print(f\"  Tokens: {entry['inputTokens']} in \u002F {entry['outputTokens']} out\")\n    print(f\"  Cost: ${entry['cost']:.4f}\")\n",[27,350,348],{"__ignoreMap":80},[88,352,354],{"id":353},"search-translations","Search Translations",[14,356,357],{},"Tìm kiếm text trong bản gốc hoặc bản dịch xuyên toàn bộ sách:",[74,359,362],{"className":360,"code":361,"language":79,"meta":80},[77],"# Tìm trong bản gốc\nresults = api(\"SearchTranslations\", {\n    \"bookId\": BOOK_ID,\n    \"query\": \"self\",\n    \"scope\": \"SEARCH_SCOPE_ORIGINAL\",\n    \"limit\": 20\n})\nprint(f\"Found: {results['totalCount']}\")\nfor r in results.get(\"results\", []):\n    print(f\"  [{r['filePath']}] EN: {r['originalText'][:80]}\")\n    print(f\"               VI: {r.get('translatedText', '(chưa dịch)')[:80]}\")\n\n# Tìm trong bản dịch\nresults = api(\"SearchTranslations\", {\n    \"bookId\": BOOK_ID,\n    \"query\": \"bản ngã\",\n    \"scope\": \"SEARCH_SCOPE_TRANSLATION\",\n    \"limit\": 20\n})\n\n# Tìm cả hai\nresults = api(\"SearchTranslations\", {\n    \"bookId\": BOOK_ID,\n    \"query\": \"anxiety\",\n    \"scope\": \"SEARCH_SCOPE_BOTH\",\n    \"limit\": 20\n})\n",[27,363,361],{"__ignoreMap":80},[88,365,367],{"id":366},"glossary-management","Glossary Management",[14,369,370],{},"Quản lý thuật ngữ cố định cho sách:",[74,372,375],{"className":373,"code":374,"language":79,"meta":80},[77],"# Xem glossary\nglossary = api(\"GetGlossary\", {\"bookId\": BOOK_ID})\nfor entry in glossary.get(\"entries\", []):\n    note = f\" ({entry['note']})\" if entry.get(\"note\") else \"\"\n    print(f\"  {entry['original']} → {entry['translated']}{note}\")\n\n# Thêm term\napi(\"AddGlossaryTerm\", {\n    \"bookId\": BOOK_ID,\n    \"original\": \"ego\",\n    \"translated\": \"cái tôi\",\n    \"note\": \"Thuật ngữ phân tâm học\"\n})\n\n# Thay thế toàn bộ glossary\napi(\"UpdateGlossary\", {\n    \"bookId\": BOOK_ID,\n    \"entries\": [\n        {\"original\": \"self\", \"translated\": \"bản ngã\", \"note\": \"\"},\n        {\"original\": \"ego\", \"translated\": \"cái tôi\", \"note\": \"\"}\n    ]\n})\n\n# Xóa term\napi(\"DeleteGlossaryTerm\", {\n    \"bookId\": BOOK_ID,\n    \"original\": \"term_to_remove\"\n})\n",[27,376,374],{"__ignoreMap":80},[11,378,379],{},[14,380,381,382,385],{},"Glossary thủ công được merge tự động với auto-generated glossary trong ",[27,383,384],{},"GetChapterContext",". Glossary thủ công ưu tiên khi conflict.",[88,387,389],{"id":388},"book-statistics","Book Statistics",[14,391,392],{},"Xem thống kê word count và chapter sizes:",[74,394,397],{"className":395,"code":396,"language":79,"meta":80},[77],"stats = api(\"GetBookStats\", {\"bookId\": BOOK_ID})\nprint(f\"Chapters: {stats['totalChapters']}\")\nprint(f\"Original words: {stats['totalOriginalWords']}\")\nprint(f\"Translated words: {stats['totalTranslatedWords']}\")\nprint(f\"Translation ratio: {stats['avgTranslationRatio']:.1%}\")\nprint(f\"Longest: {stats['longestChapter']['filePath']} ({stats['longestChapter']['wordCount']} words)\")\nprint(f\"Shortest: {stats['shortestChapter']['filePath']} ({stats['shortestChapter']['wordCount']} words)\")\n",[27,398,396],{"__ignoreMap":80},[69,400,402],{"id":401},"điều-hướng","Điều hướng",[404,405,406,419],"table",{},[407,408,409],"thead",{},[410,411,412,416],"tr",{},[413,414,415],"th",{},"Bạn muốn...",[413,417,418],{},"Dùng skill",[420,421,422,433,442,451,460],"tbody",{},[410,423,424,428],{},[425,426,427],"td",{},"Setup API key lần đầu",[425,429,430],{},[27,431,432],{},"aio-epub-setup",[410,434,435,438],{},[425,436,437],{},"Upload sách mới",[425,439,440],{},[27,441,55],{},[410,443,444,447],{},[425,445,446],{},"Dịch một chương",[425,448,449],{},[27,450,24],{},[410,452,453,456],{},[425,454,455],{},"Kiểm tra chất lượng bản dịch",[425,457,458],{},[27,459,62],{},[410,461,462,465],{},[425,463,464],{},"Xuất sách đã dịch",[425,466,467],{},[27,468,66],{},[14,470,471,152,474,476,477,476,479,476,481,476,483],{},[22,472,473],{},"Workflow",[27,475,432],{}," → ",[27,478,55],{},[27,480,24],{},[27,482,62],{},[27,484,66],{},{"title":80,"searchDepth":486,"depth":486,"links":487},2,[488,489,513],{"id":71,"depth":486,"text":72},{"id":85,"depth":486,"text":86,"children":490},[491,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512],{"id":90,"depth":492,"text":91},3,{"id":100,"depth":492,"text":101},{"id":110,"depth":492,"text":111},{"id":120,"depth":492,"text":121},{"id":137,"depth":492,"text":138},{"id":170,"depth":492,"text":171},{"id":183,"depth":492,"text":184},{"id":193,"depth":492,"text":194},{"id":203,"depth":492,"text":204},{"id":213,"depth":492,"text":214},{"id":223,"depth":492,"text":224},{"id":236,"depth":492,"text":237},{"id":249,"depth":492,"text":250},{"id":262,"depth":492,"text":263},{"id":283,"depth":492,"text":284},{"id":309,"depth":492,"text":310},{"id":327,"depth":492,"text":328},{"id":340,"depth":492,"text":341},{"id":353,"depth":492,"text":354},{"id":366,"depth":492,"text":367},{"id":388,"depth":492,"text":389},{"id":401,"depth":486,"text":402},"Browse books, check translation progress, manage guidelines, view TOC, fork books, publish to community, reset chapters, and view usage stats.","skill","md",{},true,"\u002Fplugins\u002Faio-epub-translate\u002Faio-epub-manage",{"title":5,"description":514},"plugins\u002Faio-epub-translate\u002Faio-epub-manage","mHOBjElAYbOCoj86T58T5sH0MdtDfDoWVFvFRuTXMu8",[],1779707416378]