Token导航 LogoToken导航TokenDH.com
translator-AI logo
开发工具stdio官方级别未说明来源级核验

translator-AI

MCP Server

支持多AI提供商的高效JSON国际化翻译工具,具有智能缓存、多文件去重和MCP集成功能。

工具数

2

提示词数

0

GitHub Stars

6

资源数

0
TypeScriptClaude开发工具Claude DesktopClaude

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

DatanoiseTV

提供方

DatanoiseTV

最后核验

2026/5/17 20:22

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

pip install pyyaml

详细介绍

翻译ai

![CI](https://github.com/DatanoiseTV/translator-ai/actions/workflows/ci.yml) ](https://www.npmjs.com/package/translator-ai) ![Buy Me A Coffee](https://coff.ee/datanoisetv)

快速高效的JSON i18n翻译器支持多个AI提供商(Google Gemini、OpenAI和Ollama/DeepSeek),具有智能缓存、多文件重复数据删除和MCP集成功能。

特性

  • 多个AI提供商:在谷歌双子座、OpenAI(云)或Ollama/DeepSeek(本地)之间进行翻译选择
  • 多文件支持:使用自动重复数据消除处理多个文件以保存API调用
  • 增量缓存:只转换新的或修改过的字符串,大大减少了API调用
  • 批处理:智能地批处理翻译以获得最佳性能
  • 路径保存:保持精确的JSON结构,包括嵌套对象和数组
  • 交叉平台的:适用于Windows、macOS和Linux,具有自动缓存目录检测功能
  • 开发者友好:内置绩效统计和进度指标
  • 性价比高:通过智能缓存和重复数据消除最大限度地减少API的使用
  • 语言检测:自动检测源语言,而不是假设为英语
  • 多种目标语言:在单个命令中翻译成多种语言
  • 翻译元数据:可选择在输出文件中包含翻译详细信息以供跟踪
  • 试运行模式:在不进行API调用的情况下预览要翻译的内容
  • 格式保存:保持URL、电子邮件、日期、数字和模板变量不变

安装

全局安装(推荐)

npm install -g translator-ai

本地安装

npm install translator-ai

配置

选项1:Google Gemini API(云)

创建一个 .env 在项目根目录中创建文件或设置环境变量:

GEMINI_API_KEY=your_gemini_api_key_here

从获取API密钥 谷歌AI工作室.

选项2:OpenAI API(云)

创建一个 .env 在项目根目录中创建文件或设置环境变量:

OPENAI_API_KEY=your_openai_api_key_here

从获取API密钥 OpenAI平台.

选项3:Olama与DeepSeek-R1(本地)

对于无API费用的完全本地翻译:

  1. 安装 奥拉玛
  2. 拉取DeepSeek-R1模型:
   ollama pull deepseek-r1:latest
  1. 使用 --provider ollama 标志:
   translator-ai source.json -l es -o spanish.json --provider ollama

用法

基本用法

# Translate a single file
translator-ai source.json -l es -o spanish.json

# Translate multiple files with deduplication
translator-ai src/locales/en/*.json -l es -o "{dir}/{name}.{lang}.json"

# Use glob patterns
translator-ai "src/**/*.en.json" -l fr -o "{dir}/{name}.fr.json"

命令行选项

translator-ai  [options]

Arguments:
  inputFiles                   Path(s) to source JSON file(s) or glob patterns

Options:
  -l, --lang       Target language code(s), comma-separated for multiple
  -o, --output 
      Output file path or pattern
  --stdout                    Output to stdout instead of file
  --stats                     Show detailed performance statistics
  --no-cache                  Disable incremental translation cache
  --cache-file 
         Custom cache file path
  --provider            Translation provider: gemini, openai, or ollama (default: gemini)
  --ollama-url           Ollama API URL (default: http://localhost:11434)
  --ollama-model       Ollama model name (default: deepseek-r1:latest)
  --gemini-model       Gemini model name (default: gemini-2.0-flash-lite)
  --openai-model       OpenAI model name (default: gpt-4o-mini)
  --list-providers            List available translation providers
  --verbose                   Enable verbose output for debugging
  --detect-source             Auto-detect source language instead of assuming English
  --dry-run                   Preview what would be translated without making API calls
  --preserve-formats          Preserve URLs, emails, numbers, dates, and other formats
  --metadata                  Add translation metadata to output files (may break some i18n parsers)
  --sort-keys                 Sort output JSON keys alphabetically
  --check-keys                Verify all source keys exist in output (exit with error if keys are missing)
  -h, --help                  Display help
  -V, --version               Display version

Output Pattern Variables (for multiple files):
  {dir}   - Original directory path
  {name}  - Original filename without extension
  {lang}  - Target language code

例子

翻译单个文件

translator-ai en.json -l es -o es.json

使用图案翻译多个文件

# All JSON files in a directory
translator-ai locales/en/*.json -l es -o "locales/es/{name}.json"

# Recursive glob pattern
translator-ai "src/**/en.json" -l fr -o "{dir}/fr.json"

# Multiple specific files
translator-ai file1.json file2.json file3.json -l de -o "{name}.de.json"

通过重复数据删除节省进行翻译

# Shows statistics including how many API calls were saved
translator-ai src/i18n/*.json -l ja -o "{dir}/{name}.{lang}.json" --stats

输出到stdout(对管道有用)

translator-ai en.json -l de --stdout > de.json

用jq解析输出

translator-ai en.json -l de --stdout | jq

禁用缓存以进行新翻译

translator-ai en.json -l ja -o ja.json --no-cache

使用自定义缓存位置

translator-ai en.json -l ko -o ko.json --cache-file /path/to/cache.json

使用Ollama进行本地翻译

# Basic usage with Ollama
translator-ai en.json -l es -o es.json --provider ollama

# Use a different Ollama model
translator-ai en.json -l fr -o fr.json --provider ollama --ollama-model llama2:latest

# Connect to remote Ollama instance
translator-ai en.json -l de -o de.json --provider ollama --ollama-url http://192.168.1.100:11434

# Check available providers
translator-ai --list-providers

高级功能

# Detect source language automatically
translator-ai content.json -l es -o spanish.json --detect-source

# Translate to multiple languages at once
translator-ai en.json -l es,fr,de,ja -o translations/{lang}.json

# Dry run - see what would be translated without making API calls
translator-ai en.json -l es -o es.json --dry-run

# Preserve formats (URLs, emails, dates, numbers, template variables)
translator-ai app.json -l fr -o app-fr.json --preserve-formats

# Include translation metadata (disabled by default to ensure compatibility)
translator-ai en.json -l fr -o fr.json --metadata

# Sort keys alphabetically for consistent output
translator-ai en.json -l fr -o fr.json --sort-keys

# Verify all keys are present in the translation
translator-ai en.json -l fr -o fr.json --check-keys

# Use a different Gemini model
translator-ai en.json -l es -o es.json --gemini-model gemini-2.5-flash

# Combine features
translator-ai src/**/*.json -l es,fr,de -o "{dir}/{name}.{lang}.json" \
  --detect-source --preserve-formats --stats --check-keys

可用的Gemini型号

--gemini-model 选项允许您从各种Gemini型号中进行选择。热门选项包括:

  • gemini-2.0-flash-lite (默认)-对于大多数翻译来说,快速高效
  • gemini-2.5-flash -通过更新的功能增强性能
  • gemini-pro -对复杂翻译有更深入的理解
  • gemini-1.5-pro -上一代专业车型
  • gemini-1.5-flash -上一代快速模型

示例用法:

# Use the latest flash model
translator-ai en.json -l es -o es.json --gemini-model gemini-2.5-flash

# Use the default lightweight model
translator-ai en.json -l fr -o fr.json --gemini-model gemini-2.0-flash-lite

可用的OpenAI模型

--openai-model 选项允许您从各种OpenAI模型中进行选择。热门选项包括:

  • gpt-4o-mini (默认)-对于大多数翻译来说,既经济又快速
  • gpt-4o -最有能力的模型,具有深入的理解
  • gpt-4-turbo -上一代旗舰机型
  • gpt-3.5-turbo -快速高效,翻译更简单

示例用法:

# Use OpenAI with the default model
translator-ai en.json -l es -o es.json --provider openai

# Use GPT-4o for complex translations
translator-ai en.json -l ja -o ja.json --provider openai --openai-model gpt-4o

# Use GPT-3.5-turbo for faster, simpler translations
translator-ai en.json -l fr -o fr.json --provider openai --openai-model gpt-3.5-turbo

翻译元数据

当使用启用时 --metadata flag,翻译器ai添加元数据以帮助跟踪翻译:

{
  "_translator_metadata": {
    "tool": "translator-ai v1.1.0",
    "repository": "https://github.com/DatanoiseTV/translator-ai",
    "provider": "Google Gemini",
    "source_language": "English",
    "target_language": "fr",
    "timestamp": "2025-06-20T12:34:56.789Z",
    "total_strings": 42,
    "source_file": "en.json"
  },
  "greeting": "Bonjour",
  "farewell": "Au revoir"
}

默认情况下禁用元数据,以确保与i18n解析器的兼容性。使用 --metadata 以启用它。

按关键字分类

使用 --sort-keys flag用于在输出中按字母顺序对所有JSON键进行排序:

translator-ai en.json -l es -o es.json --sort-keys

这确保了翻译之间的顺序一致,并使差异更清晰。密钥已排序:

  • 不敏感的情况(a、B、c,而不是B、a、c)
  • 递归遍历所有嵌套对象
  • 数组保持其元素顺序

密钥验证

使用 --check-keys 标记以确保翻译的完整性:

translator-ai en.json -l es -o es.json --check-keys

此功能:

  • 验证翻译输出中是否存在所有源密钥
  • 报告任何丢失的密钥及其完整路径
  • 如果缺少任何钥匙,则退出并返回错误代码1
  • 帮助发现翻译API失败或格式问题
  • 检查时忽略元数据键

支持的语言代码

它应该支持任何标准化的语言代码。

运作原理

  1. 解析:读取JSON结构并将其扁平化为路径
  2. 去重:处理多个文件时,标识共享字符串
  3. 缓存:检查缓存中以前翻译过的字符串
  4. 困难:标识需要翻译的新字符串或修改后的字符串
  5. 批处理:将唯一字符串分组为最佳批量大小,以提高API效率
  6. 翻译:将批次发送到选定的提供商(Gemini API或本地Ollama)
  7. 重建:通过翻译重建精确的JSON结构
  8. 缓存:使用新的翻译更新缓存以供将来使用

多文件重复数据删除

翻译多个文件时,翻译器ai会自动:

  • 识别文件中的重复字符串
  • 只翻译每个唯一的字符串一次
  • 在所有文件中一致地应用相同的翻译
  • 保存重要的API调用并确保一致性

示例:如果10个文件共享其50%的字符串,则可以节省API调用的50%!

缓存管理

默认缓存位置

  • 视窗: %APPDATA%\translator-ai\translation-cache.json
  • macOS: ~/Library/Caches/translator-ai/translation-cache.json
  • Linux: ~/.cache/translator-ai/translation-cache.json

缓存文件存储按以下方式索引的翻译:

  • 源文件路径
  • 目标语言
  • 源字符串的SHA-256哈希

这确保了:

  • 修改后的字符串将被重新翻译
  • 删除的字符串将从缓存中删除
  • 多个项目可以共享同一缓存而不会发生冲突

提供商比较

谷歌双子座

  • 优点:快速、准确、高效处理大批量
  • 缺点:需要API密钥,有使用成本
  • 可用模型:

- gemini-2.0-flash-lite (默认)-最快、最具成本效益 - gemini-pro -平衡性能 - gemini-1.5-pro -高级功能 - gemini-1.5-flash -速度快,质量好

  • 最适合:生产使用,大型项目,当精度至关重要时

Ollama(当地)

  • 优点:免费,本地运行,无API限制,隐私友好
  • 缺点:速度较慢,需要本地资源,需要下载模型
  • 最适合:开发、隐私敏感数据、注重成本的项目

性能提示

  1. 使用缓存 (默认启用)以最小化API调用
  2. 批处理多个文件 在同一会话中利用热缓存
  3. 使用 --stats 旗帜 监控性能和优化机会
  4. 保持源文件一致 最大化缓存命中率
  5. 献给Ollama:使用功能强大的机器以获得更好的性能

API限制和成本

API双子星

  • 使用Gemini 2.0 Flash Lite型号,实现最佳速度和成本
  • 根据输入键计数动态选择最佳批大小
  • 每个API调用最多批处理100个字符串
  • 检查 谷歌的定价 对于当前汇率

奥拉玛

  • 无需API成本-完全在您的硬件上运行
  • 性能取决于机器的性能
  • 支持具有不同速度/质量折衷的各种型号

与模型上下文协议(MCP)一起使用

翻译器ai可以用作MCP服务器,允许像Claude Desktop这样的ai助手直接翻译文件。

MCP配置

添加到您的Claude Desktop配置中:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json\ 视窗: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "translator-ai": {
      "command": "npx",
      "args": [
        "-y",
        "translator-ai-mcp"
      ],
      "env": {
        "GEMINI_API_KEY": "your-gemini-api-key-here"
        // Or for Ollama:
        // "TRANSLATOR_PROVIDER": "ollama"
      }
    }
  }
}

MCP使用示例

配置后,您可以要求Claude翻译文件:

Human: Can you translate my English locale file to Spanish?

Claude: I'll translate your English locale file to Spanish using translator-ai.

{
  "inputFile": "locales/en.json",
  "targetLanguage": "es",
  "outputFile": "locales/es.json"
}

Successfully translated! The file has been saved to locales/es.json.

对于具有重复数据消除功能的多个文件:

Human: Translate all my English JSON files in the locales folder to German.

Claude: I'll translate all your English JSON files to German with deduplication.

{
  "pattern": "locales/en/*.json",
  "targetLanguage": "de",
  "outputPattern": "locales/de/{name}.json",
  "showStats": true
}

Translation complete! Processed 5 files with 23% deduplication savings.

MCP工具可用

  1. translate.json:翻译单个JSON文件

- inputFile:源文件的路径 - targetLanguage:目标语言代码 - outputFile:输出文件路径

  1. translate_multimate:使用重复数据删除功能翻译多个文件

- pattern:文件模式或路径 - targetLanguage:目标语言代码 - outputPattern:具有{dir}、{name}、{lang}变量的输出模式 - showStats:显示重复数据消除统计信息(可选)

与静态站点生成器集成

使用YAML文件(Hugo、Jekyll等)

由于翻译器ai处理JSON文件,您需要将YAML转换为JSON并返回。以下是一个实用的工作流程:

设置YAML转换工具

# Install yaml conversion tools
npm install -g js-yaml
# or
pip install pyyaml

使用YAML转换的Hugo示例

  1. 创建翻译脚本 (translate-hugo.sh):
#!/bin/bash
# translate-hugo.sh - Translate Hugo YAML i18n files

# Function to translate YAML file
translate_yaml() {
  local input_file=$1
  local lang=$2
  local output_file=$3
  
  echo "Translating $input_file to $lang..."
  
  # Convert YAML to JSON
  npx js-yaml $input_file > temp_input.json
  
  # Translate JSON
  translator-ai temp_input.json -l $lang -o temp_output.json
  
  # Convert back to YAML
  npx js-yaml temp_output.json > $output_file
  
  # Cleanup
  rm temp_input.json temp_output.json
}

# Translate Hugo i18n files
translate_yaml themes/your-theme/i18n/en.yaml es themes/your-theme/i18n/es.yaml
translate_yaml themes/your-theme/i18n/en.yaml fr themes/your-theme/i18n/fr.yaml
translate_yaml themes/your-theme/i18n/en.yaml de themes/your-theme/i18n/de.yaml
  1. 基于Python的转换器 对于更复杂的场景:
#!/usr/bin/env python3
# hugo-translate.py

import yaml
import json
import subprocess
import sys
import os

def yaml_to_json(yaml_file):
    """Convert YAML to JSON"""
    with open(yaml_file, 'r', encoding='utf-8') as f:
        data = yaml.safe_load(f)
    return json.dumps(data, ensure_ascii=False, indent=2)

def json_to_yaml(json_str):
    """Convert JSON back to YAML"""
    data = json.loads(json_str)
    return yaml.dump(data, allow_unicode=True, default_flow_style=False)

def translate_yaml_file(input_yaml, target_lang, output_yaml):
    """Translate a YAML file using translator-ai"""
    
    # Create temp JSON file
    temp_json_in = 'temp_in.json'
    temp_json_out = f'temp_out_{target_lang}.json'
    
    try:
        # Convert YAML to JSON
        json_content = yaml_to_json(input_yaml)
        with open(temp_json_in, 'w', encoding='utf-8') as f:
            f.write(json_content)
        
        # Run translator-ai
        cmd = [
            'translator-ai',
            temp_json_in,
            '-l', target_lang,
            '-o', temp_json_out
        ]
        subprocess.run(cmd, check=True)
        
        # Read translated JSON and convert back to YAML
        with open(temp_json_out, 'r', encoding='utf-8') as f:
            translated_json = f.read()
        
        yaml_content = json_to_yaml(translated_json)
        
        # Write YAML output
        with open(output_yaml, 'w', encoding='utf-8') as f:
            f.write(yaml_content)
        
        print(f"✓ Translated {input_yaml} to {output_yaml}")
        
    finally:
        # Cleanup temp files
        for f in [temp_json_in, temp_json_out]:
            if os.path.exists(f):
                os.remove(f)

# Usage
if __name__ == "__main__":
    languages = ['es', 'fr', 'de', 'ja']
    
    for lang in languages:
        translate_yaml_file(
            'i18n/en.yaml',
            lang,
            f'i18n/{lang}.yaml'
        )

具有正确YAML处理的Node.js解决方案

创建 translate-yaml.js:

#!/usr/bin/env node
const fs = require('fs');
const yaml = require('js-yaml');
const { execSync } = require('child_process');
const path = require('path');

function translateYamlFile(inputPath, targetLang, outputPath) {
  console.log(`Translating ${inputPath} to ${targetLang}...`);
  
  // Read and parse YAML
  const yamlContent = fs.readFileSync(inputPath, 'utf8');
  const data = yaml.load(yamlContent);
  
  // Write temporary JSON
  const tempJsonIn = `temp_${path.basename(inputPath)}.json`;
  const tempJsonOut = `temp_${path.basename(inputPath)}_${targetLang}.json`;
  
  fs.writeFileSync(tempJsonIn, JSON.stringify(data, null, 2));
  
  try {
    // Translate using translator-ai
    execSync(`translator-ai ${tempJsonIn} -l ${targetLang} -o ${tempJsonOut}`);
    
    // Read translated JSON
    const translatedData = JSON.parse(fs.readFileSync(tempJsonOut, 'utf8'));
    
    // Convert back to YAML
    const translatedYaml = yaml.dump(translatedData, {
      indent: 2,
      lineWidth: -1,
      noRefs: true
    });
    
    // Write output YAML
    fs.writeFileSync(outputPath, translatedYaml);
    console.log(`✓ Created ${outputPath}`);
    
  } finally {
    // Cleanup
    [tempJsonIn, tempJsonOut].forEach(f => {
      if (fs.existsSync(f)) fs.unlinkSync(f);
    });
  }
}

// Example usage
const languages = ['es', 'fr', 'de'];
languages.forEach(lang => {
  translateYamlFile(
    'i18n/en.yaml',
    lang,
    `i18n/${lang}.yaml`
  );
});

真实世界的Hugo工作流

Hugo支持两种翻译方法:按文件名(about.en.md, about.fr.md)或按内容目录(content/en/, content/fr/).以下是如何实现两者的自动化:

方法1:按文件名翻译

创建 hugo-translate-files.sh:

#!/bin/bash
# Translate Hugo content files using filename convention

SOURCE_LANG="en"
TARGET_LANGS=("es" "fr" "de" "ja")

# Find all English content files
find content -name "*.${SOURCE_LANG}.md" | while read -r file; do
  # Extract base filename without language suffix
  base_name="${file%.${SOURCE_LANG}.md}"
  
  for lang in "${TARGET_LANGS[@]}"; do
    output_file="${base_name}.${lang}.md"
    
    # Skip if translation already exists
    if [ -f "$output_file" ]; then
      echo "Skipping $output_file (already exists)"
      continue
    fi
    
    # Extract front matter
    awk '/^---$/{p=1; next} p&&/^---$/{exit} p' "$file" > temp_frontmatter.yaml
    
    # Convert front matter to JSON
    npx js-yaml temp_frontmatter.yaml > temp_frontmatter.json
    
    # Translate front matter
    translator-ai temp_frontmatter.json -l "$lang" -o "temp_translated.json"
    
    # Convert back to YAML
    echo "---" > "$output_file"
    npx js-yaml temp_translated.json >> "$output_file"
    echo "---" >> "$output_file"
    
    # Copy content (you might want to translate this too)
    awk '/^---$/{p++} p==2{print}' "$file" | tail -n +2 >> "$output_file"
    
    echo "Created $output_file"
  done
  
  # Cleanup
  rm -f temp_frontmatter.yaml temp_frontmatter.json temp_translated.json
done

方法2:按内容目录翻译

  1. 设置Hugo配置 (config.yaml):
defaultContentLanguage: en
defaultContentLanguageInSubdir: false

languages:
  en:
    contentDir: content/en
    languageName: English
    weight: 1
  es:
    contentDir: content/es
    languageName: Español
    weight: 2
  fr:
    contentDir: content/fr
    languageName: Français
    weight: 3

# Rest of your config...
  1. 创建翻译脚本 (hugo-translate-dirs.js):
#!/usr/bin/env node
const fs = require('fs-extra');
const path = require('path');
const yaml = require('js-yaml');
const { execSync } = require('child_process');
const glob = require('glob');

const SOURCE_LANG = 'en';
const TARGET_LANGS = ['es', 'fr', 'de'];

async function translateHugoContent() {
  // Ensure target directories exist
  for (const lang of TARGET_LANGS) {
    await fs.ensureDir(`content/${lang}`);
  }
  
  // Find all content files in source language
  const files = glob.sync(`content/${SOURCE_LANG}/**/*.md`);
  
  for (const file of files) {
    const relativePath = path.relative(`content/${SOURCE_LANG}`, file);
    
    for (const lang of TARGET_LANGS) {
      const targetFile = path.join(`content/${lang}`, relativePath);
      
      // Skip if already translated
      if (await fs.pathExists(targetFile)) {
        console.log(`Skipping ${targetFile} (exists)`);
        continue;
      }
      
      await translateFile(file, targetFile, lang);
    }
  }
}

async function translateFile(sourceFile, targetFile, targetLang) {
  console.log(`Translating ${sourceFile} to ${targetLang}...`);
  
  const content = await fs.readFile(sourceFile, 'utf8');
  const frontMatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
  
  if (!frontMatterMatch) {
    // No front matter, just copy
    await fs.ensureDir(path.dirname(targetFile));
    await fs.copyFile(sourceFile, targetFile);
    return;
  }
  
  // Parse front matter
  const frontMatter = yaml.load(frontMatterMatch[1]);
  const body = content.substring(frontMatterMatch[0].length);
  
  // Extract translatable fields
  const translatable = {
    title: frontMatter.title || '',
    description: frontMatter.description || '',
    summary: frontMatter.summary || '',
    keywords: frontMatter.keywords || []
  };
  
  // Save for translation
  await fs.writeJson('temp_meta.json', translatable);
  
  // Translate
  execSync(`translator-ai temp_meta.json -l ${targetLang} -o temp_translated.json`);
  
  // Read translations
  const translated = await fs.readJson('temp_translated.json');
  
  // Update front matter
  Object.assign(frontMatter, translated);
  
  // Write translated file
  await fs.ensureDir(path.dirname(targetFile));
  const newContent = `---\n${yaml.dump(frontMatter)}---${body}`;
  await fs.writeFile(targetFile, newContent);
  
  // Cleanup
  await fs.remove('temp_meta.json');
  await fs.remove('temp_translated.json');
  
  console.log(`✓ Created ${targetFile}`);
}

// Run translation
translateHugoContent().catch(console.error);

Hugo i18n文件翻译

  1. 安装依赖项:
npm install -g translator-ai js-yaml
  1. 创建Makefile 为了便于翻译:
# Makefile for Hugo translations
LANGUAGES := es fr de ja zh
SOURCE_YAML := i18n/en.yaml
THEME_DIR := themes/your-theme

.PHONY: translate
translate: $(foreach lang,$(LANGUAGES),translate-$(lang))

translate-%:
	@echo "Translating to $*..."
	@npx js-yaml $(SOURCE_YAML) > temp.json
	@translator-ai temp.json -l $* -o temp_$*.json
	@npx js-yaml temp_$*.json > i18n/$*.yaml
	@rm temp.json temp_$*.json
	@echo "✓ Created i18n/$*.yaml"

.PHONY: translate-theme
translate-theme:
	@for lang in $(LANGUAGES); do \
		make translate-theme-$$lang; \
	done

translate-theme-%:
	@echo "Translating theme to $*..."
	@npx js-yaml $(THEME_DIR)/i18n/en.yaml > temp_theme.json
	@translator-ai temp_theme.json -l $* -o temp_theme_$*.json
	@npx js-yaml temp_theme_$*.json > $(THEME_DIR)/i18n/$*.yaml
	@rm temp_theme.json temp_theme_$*.json

.PHONY: clean
clean:
	@rm -f temp*.json

# Translate everything
.PHONY: all
all: translate translate-theme

用途:

# Translate to all languages
make all

# Translate to specific language
make translate-es

# Translate theme files
make translate-theme

完整的Hugo翻译工作流程

这是一个处理内容和i18n翻译的综合脚本:

#!/usr/bin/env node
// hugo-complete-translator.js
const fs = require('fs-extra');
const path = require('path');
const yaml = require('js-yaml');
const { execSync } = require('child_process');
const glob = require('glob');

class HugoTranslator {
  constructor(targetLanguages = ['es', 'fr', 'de']) {
    this.targetLanguages = targetLanguages;
    this.tempFiles = [];
  }

  async translateSite() {
    console.log('Starting Hugo site translation...\n');
    
    // 1. Translate i18n files
    await this.translateI18nFiles();
    
    // 2. Translate content
    await this.translateContent();
    
    // 3. Update config
    await this.updateConfig();
    
    console.log('\nTranslation complete!');
  }

  async translateI18nFiles() {
    console.log('Translating i18n files...');
    const i18nFiles = glob.sync('i18n/en.{yaml,yml,toml}');
    
    for (const file of i18nFiles) {
      const ext = path.extname(file);
      
      for (const lang of this.targetLanguages) {
        const outputFile = `i18n/${lang}${ext}`;
        
        if (await fs.pathExists(outputFile)) {
          console.log(`  Skipping ${outputFile} (exists)`);
          continue;
        }
        
        // Convert to JSON
        const tempJson = `temp_i18n_${lang}.json`;
        await this.convertToJson(file, tempJson);
        
        // Translate
        const translatedJson = `temp_i18n_${lang}_translated.json`;
        execSync(`translator-ai ${tempJson} -l ${lang} -o ${translatedJson}`);
        
        // Convert back
        await this.convertFromJson(translatedJson, outputFile, ext);
        
        // Cleanup
        await fs.remove(tempJson);
        await fs.remove(translatedJson);
        
        console.log(`  ✓ Created ${outputFile}`);
      }
    }
  }

  async translateContent() {
    console.log('\nTranslating content...');
    
    // Detect translation method
    const useContentDirs = await fs.pathExists('content/en');
    
    if (useContentDirs) {
      await this.translateContentByDirectory();
    } else {
      await this.translateContentByFilename();
    }
  }

  async translateContentByDirectory() {
    const files = glob.sync('content/en/**/*.md');
    
    for (const file of files) {
      const relativePath = path.relative('content/en', file);
      
      for (const lang of this.targetLanguages) {
        const targetFile = path.join('content', lang, relativePath);
        
        if (await fs.pathExists(targetFile)) continue;
        
        await this.translateMarkdownFile(file, targetFile, lang);
      }
    }
  }

  async translateContentByFilename() {
    const files = glob.sync('content/**/*.en.md');
    
    for (const file of files) {
      const baseName = file.replace('.en.md', '');
      
      for (const lang of this.targetLanguages) {
        const targetFile = `${baseName}.${lang}.md`;
        
        if (await fs.pathExists(targetFile)) continue;
        
        await this.translateMarkdownFile(file, targetFile, lang);
      }
    }
  }

  async translateMarkdownFile(sourceFile, targetFile, targetLang) {
    const content = await fs.readFile(sourceFile, 'utf8');
    const frontMatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
    
    if (!frontMatterMatch) {
      await fs.copy(sourceFile, targetFile);
      return;
    }
    
    const frontMatter = yaml.load(frontMatterMatch[1]);
    const body = content.substring(frontMatterMatch[0].length);
    
    // Translate front matter
    const translatable = this.extractTranslatableFields(frontMatter);
    const tempJson = `temp_content_${path.basename(sourceFile)}.json`;
    const translatedJson = `${tempJson}.translated`;
    
    await fs.writeJson(tempJson, translatable);
    execSync(`translator-ai ${tempJson} -l ${targetLang} -o ${translatedJson}`);
    
    const translated = await fs.readJson(translatedJson);
    Object.assign(frontMatter, translated);
    
    // Write translated file
    await fs.ensureDir(path.dirname(targetFile));
    const newContent = `---\n${yaml.dump(frontMatter)}---${body}`;
    await fs.writeFile(targetFile, newContent);
    
    // Cleanup
    await fs.remove(tempJson);
    await fs.remove(translatedJson);
    
    console.log(`  ✓ ${targetFile}`);
  }

  extractTranslatableFields(frontMatter) {
    const fields = ['title', 'description', 'summary', 'keywords', 'tags'];
    const translatable = {};
    
    fields.forEach(field => {
      if (frontMatter[field]) {
        translatable[field] = frontMatter[field];
      }
    });
    
    return translatable;
  }

  async convertToJson(inputFile, outputFile) {
    const ext = path.extname(inputFile);
    const content = await fs.readFile(inputFile, 'utf8');
    let data;
    
    if (ext === '.yaml' || ext === '.yml') {
      data = yaml.load(content);
    } else if (ext === '.toml') {
      // You'd need a TOML parser here
      throw new Error('TOML support not implemented in this example');
    }
    
    await fs.writeJson(outputFile, data, { spaces: 2 });
  }

  async convertFromJson(inputFile, outputFile, format) {
    const data = await fs.readJson(inputFile);
    let content;
    
    if (format === '.yaml' || format === '.yml') {
      content = yaml.dump(data, { 
        indent: 2, 
        lineWidth: -1,
        noRefs: true 
      });
    } else if (format === '.toml') {
      throw new Error('TOML support not implemented in this example');
    }
    
    await fs.writeFile(outputFile, content);
  }

  async updateConfig() {
    console.log('\nUpdating Hugo config...');
    
    const configFile = glob.sync('config.{yaml,yml,toml,json}')[0];
    if (!configFile) return;
    
    // This is a simplified example - you'd need to properly parse and update
    console.log('  ! Remember to update your config.yaml with language settings');
  }
}

// Run the translator
if (require.main === module) {
  const translator = new HugoTranslator(['es', 'fr', 'de']);
  translator.translateSite().catch(console.error);
}

module.exports = HugoTranslator;

使用Hugo模块

如果你使用的是Hugo Modules,你可以创建一个翻译模块:

// go.mod
module github.com/yourusername/hugo-translator

go 1.19

require (
    github.com/yourusername/your-theme v1.0.0
)

然后在你的 package.json:

{
  "scripts": {
    "translate": "node hugo-complete-translator.js",
    "translate:content": "node hugo-complete-translator.js --content-only",
    "translate:i18n": "node hugo-complete-translator.js --i18n-only",
    "build": "npm run translate && hugo"
  }
}

带有YAML Front Matter的Jekyll

对于带有YAML前体的Jekyll帖子:

#!/usr/bin/env python3
# translate-jekyll-posts.py

import os
import yaml
import json
import subprocess
import frontmatter

def translate_jekyll_post(post_path, target_lang, output_dir):
    """Translate Jekyll post including front matter"""
    
    # Load post with front matter
    post = frontmatter.load(post_path)
    
    # Extract translatable front matter fields
    translatable = {
        'title': post.metadata.get('title', ''),
        'description': post.metadata.get('description', ''),
        'excerpt': post.metadata.get('excerpt', '')
    }
    
    # Save as JSON for translation
    with open('temp_meta.json', 'w', encoding='utf-8') as f:
        json.dump(translatable, f, ensure_ascii=False, indent=2)
    
    # Translate
    subprocess.run([
        'translator-ai',
        'temp_meta.json',
        '-l', target_lang,
        '-o', f'temp_meta_{target_lang}.json'
    ])
    
    # Load translations
    with open(f'temp_meta_{target_lang}.json', 'r', encoding='utf-8') as f:
        translations = json.load(f)
    
    # Update post metadata
    for key, value in translations.items():
        if value:  # Only update if translation exists
            post.metadata[key] = value
    
    # Add language to metadata
    post.metadata['lang'] = target_lang
    
    # Save translated post
    output_path = os.path.join(output_dir, os.path.basename(post_path))
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(frontmatter.dumps(post))
    
    # Cleanup
    os.remove('temp_meta.json')
    os.remove(f'temp_meta_{target_lang}.json')

# Translate all posts
for lang in ['es', 'fr', 'de']:
    os.makedirs(f'_posts/{lang}', exist_ok=True)
    for post in os.listdir('_posts/en'):
        if post.endswith('.md'):
            translate_jekyll_post(
                f'_posts/en/{post}',
                lang,
                f'_posts/{lang}'
            )

YAML与JSON转换的技巧

  1. 保留格式:使用 js-yaml 有适当的选项来维护YAML结构
  2. 处理特殊字符:确保全程正确编码(UTF-8)
  3. 验证输出:一些YAML特性(锚点、别名)可能需要特殊处理
  4. 考虑TOML:对于Hugo,您可能还需要处理TOML配置文件

替代方案:直接YAML支持(功能请求)

如果你经常使用YAML文件,可以考虑创建一个自动处理转换的包装器脚本,或者请求YAML支持作为翻译器ai的一个功能。

发展

从源头构建

git clone https://github.com/DatanoiseTV/translator-ai.git
cd translator-ai
npm install
npm run build

本地测试

npm start -- test.json -l es -o output.json

许可证

该项目需要商业和非商业用途的归属。看 许可证 文件以获取详细信息。

贡献

欢迎投稿!请随时提交拉取请求。

支持

有关问题、疑问或建议,请在 .

如果您发现此工具有用,请考虑支持开发:

![Buy Me A Coffee](https://coff.ee/datanoisetv)

目录标签

目录标签

TypeScriptClaude开发工具AI翻译本地部署JSON处理多语言支持国际化

支持客户端

Claude DesktopClaude

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

none

工具数量(toolCount,工具数)

2

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdionone部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP