diff --git a/README.md b/README.md index dcb4021..05f19e6 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ make docs # Build the documentation server make server -# Run the server locally (http://localhost:3000) +# Run the server locally (http://localhost:5169) make run # Create a distribution package (zip with server + docs) @@ -70,7 +70,7 @@ make server # Run it ./hem-doc-server -# Serving docs at http://localhost:3000 +# Serving docs at http://localhost:5169 ``` The server provides: diff --git a/build_docs.hml b/build_docs.hml index aa8e6c6..d9603d3 100644 --- a/build_docs.hml +++ b/build_docs.hml @@ -35,6 +35,7 @@ let SUPPORTED_LANGUAGES = { zh: "中文", de: "Deutsch", es: "Español", + fr: "Français", ja: "日本語", pt: "Português" }; @@ -110,6 +111,20 @@ let SECTION_TRANSLATIONS = { "hpm: Package Development": "hpm: Desenvolvimento de Pacotes", "hpm: Reference": "hpm: Referência", "hpm: Other": "hpm: Outros" + }, + fr: { + "Language Reference": "Référence du Langage", + "Getting Started": "Prise en Main", + "Language Guide": "Guide du Langage", + "Advanced Topics": "Sujets Avancés", + "API Reference": "Référence API", + "Design & Philosophy": "Conception et Philosophie", + "Contributing": "Contribuer", + "hpm: Getting Started": "hpm : Prise en Main", + "hpm: User Guide": "hpm : Guide Utilisateur", + "hpm: Package Development": "hpm : Développement de Paquets", + "hpm: Reference": "hpm : Référence", + "hpm: Other": "hpm : Autres" } }; @@ -359,6 +374,55 @@ let TITLE_TRANSLATIONS = { "Versioning": "Versionamento", "Architecture": "Arquitetura", "Exit Codes": "Códigos de Saída" + }, + fr: { + "Installation": "Installation", + "Quick Start": "Démarrage Rapide", + "Tutorial": "Tutoriel", + "Learning Paths": "Parcours d'Apprentissage", + "Syntax": "Syntaxe", + "Types": "Types", + "Functions": "Fonctions", + "Arrays": "Tableaux", + "Strings": "Chaînes de Caractères", + "Objects": "Objets", + "Control Flow": "Flux de Contrôle", + "Error Handling": "Gestion des Erreurs", + "Modules": "Modules", + "Memory": "Gestion de la Mémoire", + "Pattern Matching": "Filtrage par Motif", + "Runes": "Runes", + "Async Concurrency": "Asynchronisme et Concurrence", + "Atomics": "Opérations Atomiques", + "Bundling Packaging": "Empaquetage et Distribution", + "Command Execution": "Exécution de Commandes", + "Command Line Args": "Arguments en Ligne de Commande", + "FFI": "FFI (Interface de Fonctions Étrangères)", + "File IO": "E/S de Fichiers", + "Profiling": "Profilage", + "Signals": "Signaux", + "Array API": "API des Tableaux", + "String API": "API des Chaînes", + "File API": "API des Fichiers", + "Memory API": "API Mémoire", + "Concurrency API": "API de Concurrence", + "Builtins": "Fonctions Intégrées", + "Operators": "Opérateurs", + "Type System": "Système de Types", + "Philosophy": "Philosophie", + "Implementation": "Implémentation", + "Signature Syntax": "Syntaxe des Signatures", + "Guidelines": "Directives", + "Testing": "Tests", + "Commands": "Commandes", + "Configuration": "Configuration", + "Project Setup": "Configuration du Projet", + "Troubleshooting": "Dépannage", + "Creating Packages": "Création de Paquets", + "Package Spec": "Spécification des Paquets", + "Versioning": "Gestion des Versions", + "Architecture": "Architecture", + "Exit Codes": "Codes de Sortie" } }; @@ -368,6 +432,7 @@ let PAGE_TITLES = { zh: "Hemlock 语言手册", de: "Hemlock-Sprachhandbuch", es: "Manual del Lenguaje Hemlock", + fr: "Manuel du Langage Hemlock", ja: "Hemlock言語マニュアル", pt: "Manual da Linguagem Hemlock" }; @@ -378,6 +443,7 @@ let WELCOME_TITLE_TRANSLATIONS = { zh: "欢迎", de: "Willkommen", es: "Bienvenido", + fr: "Bienvenue", ja: "ようこそ", pt: "Bem-vindo" }; @@ -2629,12 +2695,12 @@ fn main() { // Determine which languages to build let languages = []; if (lang == "all") { - languages = ["en", "zh", "de", "es", "ja", "pt"]; + languages = ["en", "zh", "de", "es", "fr", "ja", "pt"]; } else if (SUPPORTED_LANGUAGES[lang] != null) { languages = [lang]; } else { print("Error: Unknown language '" + lang + "'"); - print("Supported languages: en, zh, de, es, ja, pt"); + print("Supported languages: en, zh, de, es, fr, ja, pt"); exit(1); } diff --git a/build_docs.py b/build_docs.py index 6217ab1..6497a85 100644 --- a/build_docs.py +++ b/build_docs.py @@ -160,8 +160,8 @@ 'Bundling Packaging': '打包与发布', 'Command Execution': '命令执行', 'Command Line Args': '命令行参数', - 'Ffi': 'FFI (外部函数接口)', - 'File Io': '文件 I/O', + 'FFI': 'FFI (外部函数接口)', + 'File IO': '文件 I/O', 'Profiling': '性能分析', 'Signals': '信号处理', # Reference @@ -216,8 +216,8 @@ 'Bundling Packaging': 'Bündeln & Paketieren', 'Command Execution': 'Befehlsausführung', 'Command Line Args': 'Kommandozeilenargumente', - 'Ffi': 'FFI (Fremdsprachenschnittstelle)', - 'File Io': 'Datei-I/O', + 'FFI': 'FFI (Fremdsprachenschnittstelle)', + 'File IO': 'Datei-I/O', 'Profiling': 'Profilerstellung', 'Signals': 'Signalverarbeitung', # Reference @@ -272,8 +272,8 @@ 'Bundling Packaging': 'Empaquetado y Distribución', 'Command Execution': 'Ejecución de Comandos', 'Command Line Args': 'Argumentos de Línea de Comandos', - 'Ffi': 'FFI (Interfaz de Funciones Externas)', - 'File Io': 'E/S de Archivos', + 'FFI': 'FFI (Interfaz de Funciones Externas)', + 'File IO': 'E/S de Archivos', 'Profiling': 'Perfilado', 'Signals': 'Señales', # Reference @@ -328,8 +328,8 @@ 'Bundling Packaging': 'バンドルとパッケージング', 'Command Execution': 'コマンド実行', 'Command Line Args': 'コマンドライン引数', - 'Ffi': 'FFI(外部関数インターフェース)', - 'File Io': 'ファイルI/O', + 'FFI': 'FFI(外部関数インターフェース)', + 'File IO': 'ファイルI/O', 'Profiling': 'プロファイリング', 'Signals': 'シグナル処理', # Reference @@ -384,8 +384,8 @@ 'Bundling Packaging': 'Empacotamento e Distribuição', 'Command Execution': 'Execução de Comandos', 'Command Line Args': 'Argumentos de Linha de Comando', - 'Ffi': 'FFI (Interface de Funções Estrangeiras)', - 'File Io': 'E/S de Arquivos', + 'FFI': 'FFI (Interface de Funções Estrangeiras)', + 'File IO': 'E/S de Arquivos', 'Profiling': 'Perfilamento', 'Signals': 'Sinais', # Reference @@ -440,8 +440,8 @@ 'Bundling Packaging': 'Empaquetage et Distribution', 'Command Execution': 'Exécution de Commandes', 'Command Line Args': 'Arguments en Ligne de Commande', - 'Ffi': 'FFI (Interface de Fonctions Étrangères)', - 'File Io': 'E/S de Fichiers', + 'FFI': 'FFI (Interface de Fonctions Étrangères)', + 'File IO': 'E/S de Fichiers', 'Profiling': 'Profilage', 'Signals': 'Signaux', # Reference diff --git a/serve.hml b/serve.hml index 32b7cb2..f7489d6 100644 --- a/serve.hml +++ b/serve.hml @@ -4,10 +4,20 @@ import { App } from "hemlang/sprout"; import { read_file } from "@stdlib/fs"; -// Supported languages for documentation -let supported_langs = ["en", "de", "es", "fr", "ja", "pt", "zh"]; - -// Read the docs HTML at startup +// Supported languages for documentation (excluding English which is the default) +let non_english_langs = ["de", "es", "fr", "ja", "pt", "zh"]; + +// Language display names for logging +let lang_names = { + de: "German", + es: "Spanish", + fr: "French", + ja: "Japanese", + pt: "Portuguese", + zh: "Chinese" +}; + +// Read the docs HTML at startup (English is required) let docs_html = read_file("docs.html"); if (docs_html == null) { print("Error: docs.html not found"); @@ -15,35 +25,22 @@ if (docs_html == null) { exit(1); } -// Read language-specific documentation files -let docs_de = read_file("docs-de.html"); -if (docs_de == null) { - print("Warning: docs-de.html not found, German docs will fall back to English"); -} - -let docs_es = read_file("docs-es.html"); -if (docs_es == null) { - print("Warning: docs-es.html not found, Spanish docs will fall back to English"); -} - -let docs_fr = read_file("docs-fr.html"); -if (docs_fr == null) { - print("Warning: docs-fr.html not found, French docs will fall back to English"); -} +// Read language-specific documentation files into objects +let docs = {}; +let llms = {}; -let docs_zh = read_file("docs-zh.html"); -if (docs_zh == null) { - print("Warning: docs-zh.html not found, Chinese docs will fall back to English"); -} - -let docs_ja = read_file("docs-ja.html"); -if (docs_ja == null) { - print("Warning: docs-ja.html not found, Japanese docs will fall back to English"); -} +for (let lang in non_english_langs) { + let doc_file = read_file("docs-" + lang + ".html"); + if (doc_file == null) { + print("Warning: docs-" + lang + ".html not found, " + lang_names[lang] + " docs will fall back to English"); + } + docs[lang] = doc_file; -let docs_pt = read_file("docs-pt.html"); -if (docs_pt == null) { - print("Warning: docs-pt.html not found, Portuguese docs will fall back to English"); + let llm_file = read_file("llms-" + lang + ".txt"); + if (llm_file == null) { + print("Warning: llms-" + lang + ".txt not found, " + lang_names[lang] + " LLM docs will fall back to English"); + } + llms[lang] = llm_file; } // Read the LLM-friendly documentation at startup @@ -52,37 +49,6 @@ if (llms_txt == null) { print("Warning: llms.txt not found, /llms.txt endpoint will be unavailable"); } -// Read language-specific LLM documentation files -let llms_de = read_file("llms-de.txt"); -if (llms_de == null) { - print("Warning: llms-de.txt not found, German LLM docs will fall back to English"); -} - -let llms_es = read_file("llms-es.txt"); -if (llms_es == null) { - print("Warning: llms-es.txt not found, Spanish LLM docs will fall back to English"); -} - -let llms_fr = read_file("llms-fr.txt"); -if (llms_fr == null) { - print("Warning: llms-fr.txt not found, French LLM docs will fall back to English"); -} - -let llms_zh = read_file("llms-zh.txt"); -if (llms_zh == null) { - print("Warning: llms-zh.txt not found, Chinese LLM docs will fall back to English"); -} - -let llms_ja = read_file("llms-ja.txt"); -if (llms_ja == null) { - print("Warning: llms-ja.txt not found, Japanese LLM docs will fall back to English"); -} - -let llms_pt = read_file("llms-pt.txt"); -if (llms_pt == null) { - print("Warning: llms-pt.txt not found, Portuguese LLM docs will fall back to English"); -} - let app = App(null); // Serve the documentation (English at root and /docs.html) @@ -94,55 +60,50 @@ app.get("/docs.html", fn(req, res, next) { res.type("html").send(docs_html); }); -// Serve German documentation +// Serve language-specific documentation app.get("/docs-de.html", fn(req, res, next) { - if (docs_de != null) { - res.type("html").send(docs_de); + if (docs["de"] != null) { + res.type("html").send(docs["de"]); } else { res.type("html").send(docs_html); } }); -// Serve Spanish documentation app.get("/docs-es.html", fn(req, res, next) { - if (docs_es != null) { - res.type("html").send(docs_es); + if (docs["es"] != null) { + res.type("html").send(docs["es"]); } else { res.type("html").send(docs_html); } }); -// Serve French documentation app.get("/docs-fr.html", fn(req, res, next) { - if (docs_fr != null) { - res.type("html").send(docs_fr); + if (docs["fr"] != null) { + res.type("html").send(docs["fr"]); } else { res.type("html").send(docs_html); } }); -// Serve Chinese documentation -app.get("/docs-zh.html", fn(req, res, next) { - if (docs_zh != null) { - res.type("html").send(docs_zh); +app.get("/docs-ja.html", fn(req, res, next) { + if (docs["ja"] != null) { + res.type("html").send(docs["ja"]); } else { res.type("html").send(docs_html); } }); -// Serve Japanese documentation -app.get("/docs-ja.html", fn(req, res, next) { - if (docs_ja != null) { - res.type("html").send(docs_ja); +app.get("/docs-pt.html", fn(req, res, next) { + if (docs["pt"] != null) { + res.type("html").send(docs["pt"]); } else { res.type("html").send(docs_html); } }); -// Serve Portuguese documentation -app.get("/docs-pt.html", fn(req, res, next) { - if (docs_pt != null) { - res.type("html").send(docs_pt); +app.get("/docs-zh.html", fn(req, res, next) { + if (docs["zh"] != null) { + res.type("html").send(docs["zh"]); } else { res.type("html").send(docs_html); } @@ -157,10 +118,10 @@ app.get("/llms.txt", fn(req, res, next) { } }); -// Serve German LLM documentation +// Serve language-specific LLM documentation app.get("/llms-de.txt", fn(req, res, next) { - if (llms_de != null) { - res.type("text").send(llms_de); + if (llms["de"] != null) { + res.type("text").send(llms["de"]); } else if (llms_txt != null) { res.type("text").send(llms_txt); } else { @@ -168,10 +129,9 @@ app.get("/llms-de.txt", fn(req, res, next) { } }); -// Serve Spanish LLM documentation app.get("/llms-es.txt", fn(req, res, next) { - if (llms_es != null) { - res.type("text").send(llms_es); + if (llms["es"] != null) { + res.type("text").send(llms["es"]); } else if (llms_txt != null) { res.type("text").send(llms_txt); } else { @@ -179,10 +139,9 @@ app.get("/llms-es.txt", fn(req, res, next) { } }); -// Serve French LLM documentation app.get("/llms-fr.txt", fn(req, res, next) { - if (llms_fr != null) { - res.type("text").send(llms_fr); + if (llms["fr"] != null) { + res.type("text").send(llms["fr"]); } else if (llms_txt != null) { res.type("text").send(llms_txt); } else { @@ -190,36 +149,33 @@ app.get("/llms-fr.txt", fn(req, res, next) { } }); -// Serve Chinese LLM documentation -app.get("/llms-zh.txt", fn(req, res, next) { - if (llms_zh != null) { - res.type("text").send(llms_zh); +app.get("/llms-ja.txt", fn(req, res, next) { + if (llms["ja"] != null) { + res.type("text").send(llms["ja"]); } else if (llms_txt != null) { res.type("text").send(llms_txt); } else { - res.status(404).type("text").send("llms-zh.txt not found. Run 'make docs' to generate it."); + res.status(404).type("text").send("llms-ja.txt not found. Run 'make docs' to generate it."); } }); -// Serve Japanese LLM documentation -app.get("/llms-ja.txt", fn(req, res, next) { - if (llms_ja != null) { - res.type("text").send(llms_ja); +app.get("/llms-pt.txt", fn(req, res, next) { + if (llms["pt"] != null) { + res.type("text").send(llms["pt"]); } else if (llms_txt != null) { res.type("text").send(llms_txt); } else { - res.status(404).type("text").send("llms-ja.txt not found. Run 'make docs' to generate it."); + res.status(404).type("text").send("llms-pt.txt not found. Run 'make docs' to generate it."); } }); -// Serve Portuguese LLM documentation -app.get("/llms-pt.txt", fn(req, res, next) { - if (llms_pt != null) { - res.type("text").send(llms_pt); +app.get("/llms-zh.txt", fn(req, res, next) { + if (llms["zh"] != null) { + res.type("text").send(llms["zh"]); } else if (llms_txt != null) { res.type("text").send(llms_txt); } else { - res.status(404).type("text").send("llms-pt.txt not found. Run 'make docs' to generate it."); + res.status(404).type("text").send("llms-zh.txt not found. Run 'make docs' to generate it."); } }); @@ -228,19 +184,19 @@ app.get("/health", fn(req, res, next) { res.json({ status: "ok", docs_size: docs_html.length, - docs_de_size: docs_de != null ? docs_de.length : 0, - docs_es_size: docs_es != null ? docs_es.length : 0, - docs_fr_size: docs_fr != null ? docs_fr.length : 0, - docs_ja_size: docs_ja != null ? docs_ja.length : 0, - docs_pt_size: docs_pt != null ? docs_pt.length : 0, - docs_zh_size: docs_zh != null ? docs_zh.length : 0, + docs_de_size: docs["de"] != null ? docs["de"].length : 0, + docs_es_size: docs["es"] != null ? docs["es"].length : 0, + docs_fr_size: docs["fr"] != null ? docs["fr"].length : 0, + docs_ja_size: docs["ja"] != null ? docs["ja"].length : 0, + docs_pt_size: docs["pt"] != null ? docs["pt"].length : 0, + docs_zh_size: docs["zh"] != null ? docs["zh"].length : 0, llms_size: llms_txt != null ? llms_txt.length : 0, - llms_de_size: llms_de != null ? llms_de.length : 0, - llms_es_size: llms_es != null ? llms_es.length : 0, - llms_fr_size: llms_fr != null ? llms_fr.length : 0, - llms_ja_size: llms_ja != null ? llms_ja.length : 0, - llms_pt_size: llms_pt != null ? llms_pt.length : 0, - llms_zh_size: llms_zh != null ? llms_zh.length : 0 + llms_de_size: llms["de"] != null ? llms["de"].length : 0, + llms_es_size: llms["es"] != null ? llms["es"].length : 0, + llms_fr_size: llms["fr"] != null ? llms["fr"].length : 0, + llms_ja_size: llms["ja"] != null ? llms["ja"].length : 0, + llms_pt_size: llms["pt"] != null ? llms["pt"].length : 0, + llms_zh_size: llms["zh"] != null ? llms["zh"].length : 0 }); });