@@ -28,6 +28,7 @@ def log(msg: str = ""):
2828 elapsed = _time .time () - _T0
2929 print (f"[{ elapsed :6.1f} s] { msg } " , flush = True )
3030
31+
3132# ---------------------------------------------------------------------------
3233# Config: display order + icons for categories, docs to skip.
3334# Everything else is data-driven from service_api_mapping.json.
@@ -159,7 +160,7 @@ def build_doc_service_map(
159160 )
160161
161162 doc_map : dict [str , Optional [str ]] = {}
162- docs_dir = backend_dir / "docs"
163+ docs_dir = backend_dir / "docs" / "zh-CN"
163164
164165 for md_file in sorted (docs_dir .glob ("development_*.md" )):
165166 doc_key = md_file .stem .removeprefix ("development_" )
@@ -591,14 +592,19 @@ def _copy_seo_pages(docs_dir: Path, output_dir: Path):
591592 log (f" WARNING: { docs_dir } not found, skipping SEO pages" )
592593 return
593594
594- counts : dict [str , int ] = {"tutorials" : 0 , "comparisons" : 0 , "use-cases" : 0 , "blog" : 0 }
595+ counts : dict [str , int ] = {
596+ "tutorials" : 0 ,
597+ "comparisons" : 0 ,
598+ "use-cases" : 0 ,
599+ "blog" : 0 ,
600+ }
595601
596602 for src in sorted (docs_dir .glob ("*.md" )):
597603 name = src .stem # e.g. tutorial_claude_python
598604
599605 if name .startswith ("tutorial_" ):
600606 # tutorial_{service}_{lang}.md → tutorials/{service}/{lang}.mdx
601- rest = name [len ("tutorial_" ):] # e.g. claude_python or nano-banana_curl
607+ rest = name [len ("tutorial_" ) :] # e.g. claude_python or nano-banana_curl
602608 # Find the last _ that separates service from lang
603609 for lang in ("python" , "javascript" , "curl" ):
604610 suffix = f"_{ lang } "
@@ -611,21 +617,21 @@ def _copy_seo_pages(docs_dir: Path, output_dir: Path):
611617 break
612618
613619 elif name .startswith ("comparison_" ):
614- slug = name [len ("comparison_" ):]
620+ slug = name [len ("comparison_" ) :]
615621 dst = output_dir / "comparisons" / f"{ slug } .mdx"
616622 dst .parent .mkdir (parents = True , exist_ok = True )
617623 _write_seo_mdx (src , dst )
618624 counts ["comparisons" ] += 1
619625
620626 elif name .startswith ("use_case_" ):
621- slug = name [len ("use_case_" ):]
627+ slug = name [len ("use_case_" ) :]
622628 dst = output_dir / "use-cases" / f"{ slug } .mdx"
623629 dst .parent .mkdir (parents = True , exist_ok = True )
624630 _write_seo_mdx (src , dst )
625631 counts ["use-cases" ] += 1
626632
627633 elif name .startswith ("blog_" ):
628- slug = name [len ("blog_" ):]
634+ slug = name [len ("blog_" ) :]
629635 dst = output_dir / "blog" / f"{ slug } .mdx"
630636 dst .parent .mkdir (parents = True , exist_ok = True )
631637 _write_seo_mdx (src , dst )
@@ -672,8 +678,6 @@ def _write_seo_mdx(src: Path, dst: Path):
672678 dst .write_text (mdx , encoding = "utf-8" )
673679
674680
675-
676-
677681def _build_simple_nav (directory : str , output_dir : Path ) -> list [str ]:
678682 """Auto-discover MDX pages in a flat directory."""
679683 d = output_dir / directory
@@ -765,12 +769,16 @@ def build_navigation(
765769 # Tab 4: 对比
766770 cmp_pages = _build_simple_nav ("comparisons" , output_dir )
767771 if cmp_pages :
768- tabs .append ({"tab" : "对比" , "groups" : [{"group" : "服务对比" , "pages" : cmp_pages }]})
772+ tabs .append (
773+ {"tab" : "对比" , "groups" : [{"group" : "服务对比" , "pages" : cmp_pages }]}
774+ )
769775
770776 # Tab 5: 用例
771777 uc_pages = _build_simple_nav ("use-cases" , output_dir )
772778 if uc_pages :
773- tabs .append ({"tab" : "用例" , "groups" : [{"group" : "应用场景" , "pages" : uc_pages }]})
779+ tabs .append (
780+ {"tab" : "用例" , "groups" : [{"group" : "应用场景" , "pages" : uc_pages }]}
781+ )
774782
775783 # Tab 6: 博客
776784 blog_pages = _build_simple_nav ("blog" , output_dir )
@@ -803,7 +811,9 @@ def build_navigation(
803811 if (output_dir / "resources" / "support.mdx" ).exists ():
804812 resource_pages .append ("resources/support" )
805813 if resource_pages :
806- tabs .append ({"tab" : "资源" , "groups" : [{"group" : "资源" , "pages" : resource_pages }]})
814+ tabs .append (
815+ {"tab" : "资源" , "groups" : [{"group" : "资源" , "pages" : resource_pages }]}
816+ )
807817
808818 return {
809819 "tabs" : tabs ,
@@ -824,6 +834,127 @@ def build_navigation(
824834 }
825835
826836
837+ # Target languages matching PlatformBackend/docs/ subdirectories
838+ TARGET_LANGUAGES = [
839+ "en" ,
840+ "zh-tw" ,
841+ "ja" ,
842+ "ko" ,
843+ "es" ,
844+ "fr" ,
845+ "de" ,
846+ "pt" ,
847+ "ru" ,
848+ "ar" ,
849+ "it" ,
850+ "fi" ,
851+ "sv" ,
852+ "el" ,
853+ "uk" ,
854+ "pl" ,
855+ "sr" ,
856+ ]
857+
858+ # Mintlify expects specific language codes (may differ from directory names)
859+ _LANG_DIR_TO_MINTLIFY = {
860+ "zh-tw" : "zh-TW" ,
861+ }
862+
863+
864+ def _mintlify_lang (lang_dir : str ) -> str :
865+ """Map PlatformBackend language directory name to Mintlify language code."""
866+ return _LANG_DIR_TO_MINTLIFY .get (lang_dir , lang_dir )
867+
868+
869+ def _sync_translated_content (
870+ backend_dir : Path ,
871+ output_dir : Path ,
872+ doc_service_map : dict [str , Optional [str ]],
873+ service_names : dict [str , str ],
874+ categories : dict [str , dict ],
875+ dev_docs_by_service : dict [str , list [str ]],
876+ ):
877+ """Copy pre-translated content from PlatformBackend/docs/{lang}/ to Mintlify
878+ language directories.
879+
880+ For each target language that has a directory in PlatformBackend/docs/,
881+ apply the same MD→MDX conversion as the zh-CN base, placing output into
882+ {output_dir}/{mintlify_lang}/guides/..., tutorials/..., etc.
883+ """
884+ total_files = 0
885+
886+ for lang_dir in TARGET_LANGUAGES :
887+ lang_docs = backend_dir / "docs" / lang_dir
888+ if not lang_docs .is_dir ():
889+ continue
890+
891+ mlang = _mintlify_lang (lang_dir )
892+ lang_out = output_dir / mlang
893+ lang_count = 0
894+
895+ # --- Development guides ---
896+ for md_file in sorted (lang_docs .glob ("development_*.md" )):
897+ doc_key = md_file .stem .removeprefix ("development_" )
898+ if doc_key .endswith ("_title" ):
899+ continue
900+ service_alias = doc_service_map .get (doc_key )
901+ if service_alias is None :
902+ continue
903+ content = md_file .read_text (encoding = "utf-8" )
904+ svc_name = service_names .get (service_alias , service_alias )
905+ mdx_content = convert_dev_doc_to_mdx (content , doc_key , svc_name )
906+ svc_dir = lang_out / "guides" / service_alias
907+ svc_dir .mkdir (parents = True , exist_ok = True )
908+ (svc_dir / f"{ doc_key } .mdx" ).write_text (mdx_content , encoding = "utf-8" )
909+ lang_count += 1
910+
911+ # --- MCP docs ---
912+ for md_file in sorted (lang_docs .glob ("mcp_*.md" )):
913+ mcp_name = md_file .stem .removeprefix ("mcp_" )
914+ content = md_file .read_text (encoding = "utf-8" )
915+ mdx_content = generate_mcp_doc (content , mcp_name )
916+ mcp_out = lang_out / "mcp"
917+ mcp_out .mkdir (parents = True , exist_ok = True )
918+ (mcp_out / f"{ mcp_name } .mdx" ).write_text (mdx_content , encoding = "utf-8" )
919+ lang_count += 1
920+
921+ # --- Extra docs (privacy, terms, support) ---
922+ for doc_key , out_rel in [
923+ ("privacy" , "resources/privacy.mdx" ),
924+ ("terms" , "resources/terms.mdx" ),
925+ ("support" , "resources/support.mdx" ),
926+ ]:
927+ src = lang_docs / f"{ doc_key } .md"
928+ if src .exists ():
929+ content = src .read_text (encoding = "utf-8" )
930+ mdx = generate_extra_doc (content , doc_key )
931+ dst = lang_out / out_rel
932+ dst .parent .mkdir (parents = True , exist_ok = True )
933+ dst .write_text (mdx , encoding = "utf-8" )
934+ lang_count += 1
935+
936+ # --- X402 guide ---
937+ x402_src = lang_docs / "x402_integration_guide.md"
938+ if x402_src .exists ():
939+ content = x402_src .read_text (encoding = "utf-8" )
940+ mdx = convert_dev_doc_to_mdx (content , "x402_integration_guide" , "x402" )
941+ guides_out = lang_out / "guides"
942+ guides_out .mkdir (parents = True , exist_ok = True )
943+ (guides_out / "x402.mdx" ).write_text (mdx , encoding = "utf-8" )
944+ lang_count += 1
945+
946+ # --- SEO pages (tutorials, comparisons, use-cases, blog) ---
947+ _copy_seo_pages (lang_docs , lang_out )
948+
949+ total_files += lang_count
950+ if lang_count > 0 :
951+ log (f" { mlang } : { lang_count } guide/mcp/resource pages (+ SEO pages)" )
952+
953+ log (
954+ f" Total translated pages: { total_files } (across { len (TARGET_LANGUAGES )} languages)"
955+ )
956+
957+
827958def main ():
828959 parser = argparse .ArgumentParser (
829960 description = "Sync PlatformBackend docs to Mintlify"
@@ -900,7 +1031,7 @@ def main():
9001031 log ("Step 2/8: Convert development guides to MDX" )
9011032 log ("=" * 60 )
9021033 dev_docs_by_service : dict [str , list [str ]] = {} # alias → [doc_key, ...]
903- docs_dir = backend_dir / "docs"
1034+ docs_dir = backend_dir / "docs" / "zh-CN"
9041035
9051036 for md_file in sorted (docs_dir .glob ("development_*.md" )):
9061037 doc_key = md_file .stem .removeprefix ("development_" )
@@ -1237,9 +1368,26 @@ def main():
12371368 log ("=" * 60 )
12381369 log ("Step 6/8: Copy pre-generated SEO pages from PlatformBackend/docs" )
12391370 log ("=" * 60 )
1240- _copy_seo_pages (backend_dir / "docs" , output_dir )
1371+ _copy_seo_pages (backend_dir / "docs" / "zh-CN" , output_dir )
12411372 log ("Step 6 done" )
12421373
1374+ # ---------------------------------------------------------------------------
1375+ # 6b. Copy pre-translated content from PlatformBackend/docs/{lang}/
1376+ # ---------------------------------------------------------------------------
1377+ log ()
1378+ log ("=" * 60 )
1379+ log ("Step 6b: Copy pre-translated content from PlatformBackend" )
1380+ log ("=" * 60 )
1381+ _sync_translated_content (
1382+ backend_dir ,
1383+ output_dir ,
1384+ doc_service_map ,
1385+ service_names ,
1386+ categories ,
1387+ dev_docs_by_service ,
1388+ )
1389+ log ("Step 6b done" )
1390+
12431391 # ---------------------------------------------------------------------------
12441392 # 7. Generate docs.json
12451393 # ---------------------------------------------------------------------------
@@ -1290,6 +1438,13 @@ def main():
12901438 {"language" : "ru" },
12911439 {"language" : "ar" },
12921440 {"language" : "it" },
1441+ {"language" : "fi" },
1442+ {"language" : "sv" },
1443+ {"language" : "el" },
1444+ {"language" : "uk" },
1445+ {"language" : "pl" },
1446+ {"language" : "sr" },
1447+ {"language" : "zh-TW" },
12931448 ],
12941449 "navigation" : navigation ,
12951450 "footer" : {
0 commit comments