diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 674eb3b..ba431a0 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -30,7 +30,13 @@ jobs: run: cp -r assets website/assets - name: Update asset paths - run: sed -i 's|\.\./assets/|assets/|g' website/index.html website/docs.html + run: | + # Update asset paths in all HTML files + for file in website/*.html; do + if [ -f "$file" ]; then + sed -i 's|\.\./assets/|assets/|g' "$file" + fi + done - name: Upload artifact uses: actions/upload-pages-artifact@v3 diff --git a/.github/workflows/protect-translated-docs.yml b/.github/workflows/protect-translated-docs.yml new file mode 100644 index 0000000..7d499ff --- /dev/null +++ b/.github/workflows/protect-translated-docs.yml @@ -0,0 +1,59 @@ +# Protect Translated Documentation +# +# Prevents direct edits to auto-translated documentation. +# Only English docs should be edited by humans: +# - wiki/*.md (excluding language folders) +# - website/docs.html +# Translated docs are auto-generated and should not be manually modified: +# - wiki/ko/, wiki/zh/, wiki/ja/, wiki/es/, wiki/pt/ +# - website/docs-ko.html, website/docs-zh.html, etc. + +name: Protect Translated Docs + +on: + pull_request: + paths: + - 'wiki/ko/**' + - 'wiki/zh/**' + - 'wiki/ja/**' + - 'wiki/es/**' + - 'wiki/pt/**' + - 'website/docs-ko.html' + - 'website/docs-zh.html' + - 'website/docs-ja.html' + - 'website/docs-es.html' + - 'website/docs-pt.html' + +jobs: + check-translated-docs: + runs-on: ubuntu-latest + steps: + - name: Check for unauthorized translation edits + run: | + echo "::warning::This PR modifies auto-translated documentation." + echo "" + echo "Translated documentation is automatically generated:" + echo " - wiki/ko/, wiki/zh/, wiki/ja/, wiki/es/, wiki/pt/" + echo " - website/docs-{ko,zh,ja,es,pt}.html" + echo "" + echo "To update translations:" + echo "1. Edit the English documentation:" + echo " - wiki/*.md (for markdown docs)" + echo " - website/docs.html (for website)" + echo "2. Push to main branch" + echo "3. The translation workflow will automatically update all translations" + echo "" + echo "If you need to fix a translation issue, please edit the English source" + echo "and let the automation regenerate the translations." + echo "" + + # Check if this is from the translation bot + if [[ "${{ github.actor }}" == "github-actions[bot]" ]] || \ + [[ "${{ github.head_ref }}" == "docs/auto-translate" ]]; then + echo "This is an automated translation PR - allowing." + exit 0 + fi + + echo "::error::Direct edits to translated documentation are not allowed." + echo "Please edit the English source documentation instead." + exit 1 diff --git a/.github/workflows/translate-docs.yml b/.github/workflows/translate-docs.yml new file mode 100644 index 0000000..73dff39 --- /dev/null +++ b/.github/workflows/translate-docs.yml @@ -0,0 +1,245 @@ +# Documentation Translation Workflow +# +# Automatically translates documentation to multiple languages when English docs change. +# Only English documentation should be edited by humans: +# - wiki/*.md, wiki/**/*.md (excluding language folders) +# - website/docs.html +# All other language files are auto-generated: +# - wiki/ko/, wiki/zh/, wiki/ja/, wiki/es/, wiki/pt/ +# - website/docs-ko.html, website/docs-zh.html, etc. +# +# Supported languages: +# - ko (Korean) - Strong crypto/prediction market community +# - zh (Chinese) - Largest developer population +# - ja (Japanese) - Strong tech community +# - es (Spanish) - Large global developer population +# - pt (Portuguese) - Large Brazilian developer community + +name: Translate Documentation + +on: + push: + branches: + - main + paths: + - 'wiki/**/*.md' + - 'website/docs.html' + - '!wiki/ko/**' + - '!wiki/zh/**' + - '!wiki/ja/**' + - '!wiki/es/**' + - '!wiki/pt/**' + workflow_dispatch: + inputs: + force_translate: + description: 'Force translate all documents' + required: false + default: 'false' + type: boolean + languages: + description: 'Languages to translate (comma-separated, e.g., ko,zh,ja)' + required: false + default: 'ko,zh,ja,es,pt' + type: string + +env: + SUPPORTED_LANGUAGES: 'ko,zh,ja,es,pt' + +jobs: + detect-changes: + runs-on: ubuntu-latest + outputs: + wiki_files: ${{ steps.changes.outputs.wiki_files }} + docs_html: ${{ steps.changes.outputs.docs_html }} + has_changes: ${{ steps.changes.outputs.has_changes }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Detect changed English documentation + id: changes + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.force_translate }}" == "true" ]]; then + # Force translate: get all English docs + WIKI_FILES=$(find wiki -name "*.md" -type f | grep -v -E "wiki/(ko|zh|ja|es|pt)/" | tr '\n' ',') + echo "wiki_files=$WIKI_FILES" >> $GITHUB_OUTPUT + echo "docs_html=website/docs.html" >> $GITHUB_OUTPUT + echo "has_changes=true" >> $GITHUB_OUTPUT + else + # Get changed files from the push + WIKI_CHANGED=$(git diff --name-only HEAD~1 HEAD -- 'wiki/**/*.md' | grep -v -E "wiki/(ko|zh|ja|es|pt)/" || true) + DOCS_CHANGED=$(git diff --name-only HEAD~1 HEAD -- 'website/docs.html' || true) + + if [ -n "$WIKI_CHANGED" ] || [ -n "$DOCS_CHANGED" ]; then + WIKI_FILES=$(echo "$WIKI_CHANGED" | tr '\n' ',' | sed 's/,$//') + echo "wiki_files=$WIKI_FILES" >> $GITHUB_OUTPUT + echo "docs_html=$DOCS_CHANGED" >> $GITHUB_OUTPUT + echo "has_changes=true" >> $GITHUB_OUTPUT + else + echo "wiki_files=" >> $GITHUB_OUTPUT + echo "docs_html=" >> $GITHUB_OUTPUT + echo "has_changes=false" >> $GITHUB_OUTPUT + fi + fi + + translate: + needs: detect-changes + if: needs.detect-changes.outputs.has_changes == 'true' + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + id-token: write + strategy: + matrix: + lang: [ko, zh, ja, es, pt] + fail-fast: false + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Check if language should be translated + id: check_lang + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + LANGS="${{ inputs.languages }}" + else + LANGS="${{ env.SUPPORTED_LANGUAGES }}" + fi + if echo ",$LANGS," | grep -q ",${{ matrix.lang }},"; then + echo "should_translate=true" >> $GITHUB_OUTPUT + else + echo "should_translate=false" >> $GITHUB_OUTPUT + fi + + - name: Create translation prompt + if: steps.check_lang.outputs.should_translate == 'true' + id: prompt + run: | + LANG="${{ matrix.lang }}" + WIKI_FILES="${{ needs.detect-changes.outputs.wiki_files }}" + DOCS_HTML="${{ needs.detect-changes.outputs.docs_html }}" + + case $LANG in + ko) LANG_NAME="Korean" ;; + zh) LANG_NAME="Chinese (Simplified)" ;; + ja) LANG_NAME="Japanese" ;; + es) LANG_NAME="Spanish" ;; + pt) LANG_NAME="Portuguese (Brazilian)" ;; + esac + + cat << 'PROMPT_EOF' > /tmp/translate_prompt.txt + Translate documentation to TARGET_LANG. + + IMPORTANT TRANSLATION RULES: + 1. Preserve all formatting exactly (markdown, HTML structure, code blocks) + 2. DO NOT translate: + - Code snippets inside code blocks or
 tags
+             - Variable names, function names, class names
+             - File paths and URLs
+             - CSS class names and HTML attributes
+             - Technical terms commonly kept in English (API, WebSocket, SDK, etc.)
+          3. Translate:
+             - Prose text, descriptions, and visible UI text
+             - Comments inside code blocks (marked with # or //)
+             - Table descriptions (but not technical column names)
+             - HTML title and meta description
+          4. Use natural, fluent TARGET_LANG that a native developer would use
+          5. Keep technical accuracy - don't change the meaning
+
+          TASK 1 - Wiki Markdown Files:
+          For each wiki file in WIKI_FILES (if any):
+          1. Read the English source file from wiki/
+          2. Create the translated version in wiki/LANG_CODE/
+          3. Ensure directory structure is mirrored (e.g., wiki/exchanges/foo.md -> wiki/LANG_CODE/exchanges/foo.md)
+
+          TASK 2 - Website Documentation HTML:
+          If DOCS_HTML is not empty:
+          1. Read website/docs.html
+          2. Create translated version at website/docs-LANG_CODE.html
+          3. Update the  to 
+          4. Keep the language selector working (don't modify the JavaScript)
+
+          Wiki files to translate: WIKI_FILES
+          Docs HTML to translate: DOCS_HTML
+          Target language code: LANG_CODE
+          Target language name: TARGET_LANG
+          PROMPT_EOF
+
+          sed -i "s/TARGET_LANG/$LANG_NAME/g" /tmp/translate_prompt.txt
+          sed -i "s/LANG_CODE/$LANG/g" /tmp/translate_prompt.txt
+          sed -i "s|WIKI_FILES|$WIKI_FILES|g" /tmp/translate_prompt.txt
+          sed -i "s|DOCS_HTML|$DOCS_HTML|g" /tmp/translate_prompt.txt
+
+          PROMPT=$(cat /tmp/translate_prompt.txt)
+          echo "prompt<> $GITHUB_OUTPUT
+          echo "$PROMPT" >> $GITHUB_OUTPUT
+          echo "EOF" >> $GITHUB_OUTPUT
+
+      - name: Run Claude Code for translation
+        if: steps.check_lang.outputs.should_translate == 'true'
+        uses: anthropics/claude-code-action@v1
+        with:
+          claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          direct_prompt: ${{ steps.prompt.outputs.prompt }}
+          allowed_tools: |
+            Read
+            Write
+            Glob
+            Grep
+          timeout_minutes: 30
+
+  create-pr:
+    needs: [detect-changes, translate]
+    if: always() && needs.detect-changes.outputs.has_changes == 'true'
+    runs-on: ubuntu-latest
+    permissions:
+      contents: write
+      pull-requests: write
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 1
+
+      - name: Check for translation changes
+        id: check_changes
+        run: |
+          git add -A
+          if git diff --staged --quiet; then
+            echo "has_translations=false" >> $GITHUB_OUTPUT
+          else
+            echo "has_translations=true" >> $GITHUB_OUTPUT
+          fi
+
+      - name: Create Pull Request
+        if: steps.check_changes.outputs.has_translations == 'true'
+        uses: peter-evans/create-pull-request@v6
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          commit-message: "docs: auto-translate documentation"
+          title: "docs: Update translated documentation"
+          body: |
+            ## Automated Documentation Translation
+
+            This PR contains automatically translated documentation for the following languages:
+            - Korean (ko)
+            - Chinese (zh)
+            - Japanese (ja)
+            - Spanish (es)
+            - Portuguese (pt)
+
+            ### Changed English files:
+            **Wiki files:** ${{ needs.detect-changes.outputs.wiki_files || 'none' }}
+            **Docs HTML:** ${{ needs.detect-changes.outputs.docs_html || 'none' }}
+
+            ---
+            *Generated automatically by the translation workflow*
+          branch: docs/auto-translate
+          delete-branch: true
+          labels: documentation,automated
diff --git a/website/docs.html b/website/docs.html
index a2f89ce..aa16c67 100644
--- a/website/docs.html
+++ b/website/docs.html
@@ -145,6 +145,102 @@
             height: 18px;
         }
 
+        /* Language Selector */
+        .lang-selector {
+            position: relative;
+            display: inline-block;
+        }
+
+        .lang-btn {
+            display: flex;
+            align-items: center;
+            gap: 0.5rem;
+            padding: 0.5rem 0.9rem;
+            background: transparent;
+            border: 1px solid var(--border-subtle);
+            border-radius: 6px;
+            color: var(--text-primary);
+            font-size: 0.85rem;
+            font-weight: 500;
+            cursor: pointer;
+            transition: all 0.3s;
+            font-family: inherit;
+        }
+
+        .lang-btn:hover {
+            border-color: var(--manhattan-blue);
+            background: rgba(0, 180, 255, 0.1);
+        }
+
+        .lang-btn svg {
+            width: 14px;
+            height: 14px;
+            transition: transform 0.2s;
+        }
+
+        .lang-selector.open .lang-btn svg {
+            transform: rotate(180deg);
+        }
+
+        .lang-dropdown {
+            position: absolute;
+            top: calc(100% + 8px);
+            right: 0;
+            min-width: 160px;
+            background: var(--deep-space);
+            border: 1px solid var(--border-subtle);
+            border-radius: 8px;
+            padding: 0.5rem;
+            opacity: 0;
+            visibility: hidden;
+            transform: translateY(-10px);
+            transition: all 0.2s;
+            z-index: 200;
+            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
+        }
+
+        .lang-selector.open .lang-dropdown {
+            opacity: 1;
+            visibility: visible;
+            transform: translateY(0);
+        }
+
+        .lang-option {
+            display: flex;
+            align-items: center;
+            gap: 0.75rem;
+            padding: 0.6rem 0.75rem;
+            border-radius: 6px;
+            cursor: pointer;
+            transition: all 0.2s;
+            color: var(--text-secondary);
+            font-size: 0.85rem;
+        }
+
+        .lang-option:hover {
+            background: rgba(0, 180, 255, 0.1);
+            color: var(--text-primary);
+        }
+
+        .lang-option.active {
+            background: rgba(0, 180, 255, 0.15);
+            color: var(--manhattan-glow);
+        }
+
+        .lang-option .flag {
+            font-size: 1.1rem;
+        }
+
+        .lang-option .lang-name {
+            flex: 1;
+        }
+
+        .lang-option .lang-code {
+            color: var(--text-muted);
+            font-size: 0.75rem;
+            text-transform: uppercase;
+        }
+
         /* Main Layout */
         .docs-layout {
             display: flex;
@@ -534,6 +630,45 @@
             Getting Started
             API Reference
             Exchanges
+            
+ +
+
+ EN + English + en +
+
+ KO + Korean + ko +
+
+ ZH + Chinese + zh +
+
+ JA + Japanese + ja +
+
+ ES + Spanish + es +
+
+ PT + Portuguese + pt +
+
+
GitHub @@ -1203,6 +1338,78 @@

MCP Server

window.addEventListener('scroll', highlightActiveSection); highlightActiveSection(); + + // Language selector functionality + const languages = { + en: { flag: 'EN', name: 'English' }, + ko: { flag: 'KO', name: 'Korean' }, + zh: { flag: 'ZH', name: 'Chinese' }, + ja: { flag: 'JA', name: 'Japanese' }, + es: { flag: 'ES', name: 'Spanish' }, + pt: { flag: 'PT', name: 'Portuguese' } + }; + + function toggleLangDropdown() { + document.getElementById('langSelector').classList.toggle('open'); + } + + function selectLanguage(lang) { + localStorage.setItem('preferredLanguage', lang); + updateLanguageUI(lang); + document.getElementById('langSelector').classList.remove('open'); + + // Redirect to language-specific docs if not English + if (lang !== 'en') { + const currentPath = window.location.pathname; + const basePath = currentPath.replace(/\/docs(-\w+)?\.html$/, ''); + window.location.href = basePath + '/docs-' + lang + '.html'; + } else { + const currentPath = window.location.pathname; + if (currentPath.includes('docs-')) { + const basePath = currentPath.replace(/\/docs(-\w+)?\.html$/, ''); + window.location.href = basePath + '/docs.html'; + } + } + } + + function updateLanguageUI(lang) { + const langData = languages[lang] || languages.en; + document.getElementById('currentLangFlag').textContent = langData.flag; + document.getElementById('currentLangName').textContent = langData.name; + + document.querySelectorAll('.lang-option').forEach(option => { + option.classList.remove('active'); + if (option.dataset.lang === lang) { + option.classList.add('active'); + } + }); + } + + // Close dropdown when clicking outside + document.addEventListener('click', function(e) { + const selector = document.getElementById('langSelector'); + if (!selector.contains(e.target)) { + selector.classList.remove('open'); + } + }); + + // Initialize language from localStorage or URL + (function initLanguage() { + const path = window.location.pathname; + const match = path.match(/docs-(\w+)\.html/); + let lang = 'en'; + + if (match && languages[match[1]]) { + lang = match[1]; + } else { + const saved = localStorage.getItem('preferredLanguage'); + if (saved && languages[saved]) { + lang = saved; + } + } + + updateLanguageUI(lang); + })();