Simple README Translation #19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Simple README Translation | |
| on: | |
| push: | |
| branches: | |
| - master | |
| paths: | |
| - 'README.md' | |
| workflow_dispatch: | |
| jobs: | |
| translate-simple: | |
| name: Simple README Translation | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.9' | |
| - name: Install translation dependencies | |
| run: | | |
| pip install requests | |
| - name: Create translation script | |
| run: | | |
| cat > translate_simple.py << 'EOF' | |
| import os | |
| import re | |
| import requests | |
| # 项目名和术语保护列表 | |
| PROTECTED_TERMS = [ | |
| 'Sunshine', 'README', 'GitHub', 'CI', 'API', 'Markdown', 'OpenAI', 'DeepL', 'Google Translate', | |
| # 可在此添加更多术语 | |
| ] | |
| def mask_terms(text): | |
| for term in PROTECTED_TERMS: | |
| text = re.sub(rf'(?<![`\w]){re.escape(term)}(?![`\w])', f'@@@{term}@@@', text) | |
| return text | |
| def unmask_terms(text): | |
| for term in PROTECTED_TERMS: | |
| text = text.replace(f'@@@{term}@@@', term) | |
| return text | |
| def translate_with_deepseek(text, target_lang): | |
| # 使用 DeepSeek API 进行翻译 | |
| api_key = os.getenv('DEEPSEEK_API_KEY') | |
| if not api_key: | |
| raise Exception('DEEPSEEK_API_KEY 环境变量未设置') | |
| url = 'https://api.deepseek.com/v1/chat/completions' | |
| prompt = f"请将以下 Markdown 内容翻译为{target_lang},但不要翻译项目名和术语:{', '.join(PROTECTED_TERMS)}。保持原有格式、链接和图片。\n\n{text}" | |
| headers = { | |
| 'Authorization': f'Bearer {api_key}', | |
| 'Content-Type': 'application/json' | |
| } | |
| payload = { | |
| "model": "deepseek-chat", | |
| "messages": [{"role": "user", "content": prompt}], | |
| "temperature": 0.2 | |
| } | |
| resp = requests.post(url, headers=headers, json=payload) | |
| resp.raise_for_status() | |
| result = resp.json() | |
| return result['choices'][0]['message']['content'] | |
| def translate_readme(): | |
| with open('README.md', 'r', encoding='utf-8') as f: | |
| content = f.read() | |
| languages = [ | |
| ('en', 'English'), | |
| ('fr', 'French'), | |
| ('de', 'German'), | |
| ('ja', 'Japanese') | |
| ] | |
| for lang_code, lang_name in languages: | |
| try: | |
| if lang_code == 'zh_CN': | |
| translated_content = content | |
| else: | |
| masked = mask_terms(content) | |
| translated = translate_with_deepseek(masked, lang_name) | |
| translated = unmask_terms(translated) | |
| # 去除 DeepSeek 返回的多余提示,只保留第一个 Markdown 标题及后面内容 | |
| lines = translated.splitlines() | |
| for idx, line in enumerate(lines): | |
| if line.strip().startswith('#'): | |
| translated_content = '\n'.join(lines[idx:]) | |
| break | |
| else: | |
| translated_content = translated.strip() | |
| filename = f'README.{lang_code}.md' | |
| with open(filename, 'w', encoding='utf-8') as f: | |
| f.write(translated_content) | |
| print(f"✓ Translated to {lang_name} ({lang_code})") | |
| except Exception as e: | |
| print(f"✗ Failed to translate to {lang_name}: {e}") | |
| if __name__ == "__main__": | |
| translate_readme() | |
| EOF | |
| - name: Run translation | |
| env: | |
| DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} | |
| run: python translate_simple.py | |
| - name: Add language selector to README | |
| run: | | |
| # Check if language selector already exists | |
| if grep -q "多语言支持" README.md; then | |
| echo "Language selector already exists, skipping..." | |
| else | |
| # Create a backup of the original README | |
| cp README.md README.md.backup | |
| # Create the language selector content | |
| cat > language_selector.md << 'EOF' | |
| ## 🌐 多语言支持 / Multi-language Support | |
| <div align="center"> | |
| [](README.en.md) | |
| [](README.md) | |
| [](README.fr.md) | |
| [](README.de.md) | |
| [](README.ja.md) | |
| </div> | |
| --- | |
| EOF | |
| # Insert language selector after the first line (title) | |
| head -n 1 README.md > README.md.new | |
| cat language_selector.md >> README.md.new | |
| tail -n +2 README.md >> README.md.new | |
| # Replace the original file | |
| mv README.md.new README.md | |
| # Clean up | |
| rm language_selector.md | |
| echo "✓ Added language selector to main README" | |
| fi | |
| - name: Create Pull Request | |
| uses: peter-evans/create-pull-request@v5 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| title: "docs: add multi-language README translations with language selector" | |
| body: | | |
| ## 自动翻译更新 | |
| 此PR包含以下语言的README翻译: | |
| - English (en) | |
| - French (fr) | |
| - German (de) | |
| - Japanese (ja) | |
| ### 翻译说明 | |
| - 使用Google Translate API自动翻译 | |
| - 保持原始Markdown格式 | |
| - 保留所有链接和图片 | |
| - 建议人工检查翻译质量 | |
| ### 生成的文件 | |
| - `README.en.md` - 英语版本 | |
| - `README.fr.md` - 法语版本 | |
| - `README.de.md` - 德语版本 | |
| - `README.ja.md` - 日语版本 | |
| ### 新增功能 | |
| - 在主README文件中添加了语言选择器 | |
| - 用户可以通过徽章快速访问不同语言版本 | |
| - 支持5种语言的快速切换 | |
| --- | |
| *此PR由CI自动生成,当README.md文件更新时触发* | |
| branch: docs/translations | |
| delete-branch: true | |
| commit-message: "docs: add multi-language README translations with language selector [skip ci]" | |
| - name: Create summary | |
| run: | | |
| echo "## Translation Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "The following README translations were generated:" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| for file in README.*.md; do | |
| if [ -f "$file" ]; then | |
| lang=$(echo $file | sed 's/README\.\(.*\)\.md/\1/') | |
| echo "- $lang" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| done | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "✓ Language selector added to main README" >> $GITHUB_STEP_SUMMARY |