Machine Translation Integration — i18n

Machine Translation Integration Machine Translation (MT) bisa mempercepat proses terjemahan secara drastis. Tapi MT bukan pengganti human translator —…

Machine Translation Integration

Machine Translation (MT) bisa mempercepat proses terjemahan secara drastis. Tapi MT bukan pengganti human translator — workflow terbaik adalah MT + Post-editing.

Provider Populer

ProviderKelebihanPricing
DeepLKualitas terbaik untuk bahasa Eropa$25/1M chars
Google Translate500+ bahasa, termasuk bahasa langka$20/1M chars
Azure TranslatorCustom training, enterprise features$10/1M chars
Amazon TranslateAWS ecosystem integration$15/1M chars
Claude/GPTContext-aware, bisa terima instruksi gaya bahasaVaries

DeepL API Integration

// Node.js: translate file terjemahan
import * as deepl from "deepl-node";

const translator = new deepl.Translator(process.env.DEEPL_API_KEY);

async function translateFile(sourceFile, targetLang) {
  const source = JSON.parse(fs.readFileSync(sourceFile, "utf-8"));
  const result = {};

  for (const [key, value] of Object.entries(source)) {
    if (typeof value === "string") {
      // Skip interpolation variables
      const cleaned = value.replace(/\{\{(\w+)\}\}/g, "<x id=\"$1\"></x>");
      const { text } = await translator.translateText(
        cleaned, "en", targetLang
      );
      result[key] = text.replace(/<x id="(\w+)"><\/x>/g, "{{$1}}");
    } else if (typeof value === "object") {
      result[key] = await translateNested(value, targetLang);
    }
  }

  return result;
}

// Usage
const translated = await translateFile(
  "locales/en/common.json", "id"
);
fs.writeFileSync("locales/id/common.json", JSON.stringify(translated, null, 2));

Post-editing Workflow

// Workflow: MT → Review → Approve
//
// 1. Developer menambah string baru (en)
// 2. CI trigger MT untuk semua target locale
// 3. MT result masuk ke TMS dengan status "machine_translated"
// 4. Human translator review & post-edit
// 5. Status berubah ke "reviewed"
// 6. PR dibuat otomatis

// Crowdin: enable MT pre-translation
// Project Settings → Machine Translation → Enable → DeepL
// Pre-translation: "Translate untranslated strings via MT"

LLM-based Translation

// Menggunakan Claude/GPT untuk terjemahan context-aware
async function translateWithLLM(strings, targetLang, context) {
  const prompt = `Translate the following UI strings from English to ${targetLang}.
Context: This is a web development learning platform.
Rules:
- Keep technical terms in English (API, HTML, CSS, etc.)
- Maintain interpolation variables like {{name}} as-is
- Use formal but friendly tone
- Keep translations concise (UI space is limited)

Strings to translate:
${JSON.stringify(strings, null, 2)}

Return as JSON with the same keys.`;

  const response = await anthropic.messages.create({
    model: "claude-sonnet-4-20250514",
    max_tokens: 4096,
    messages: [{ role: "user", content: prompt }],
  });

  return JSON.parse(response.content[0].text);
}

Quality Assurance

// Automated QA checks setelah MT
function validateTranslation(source, translated) {
  const issues = [];

  // Cek interpolation variables masih ada
  const sourceVars = source.match(/\{\{(\w+)\}\}/g) || [];
  const transVars = translated.match(/\{\{(\w+)\}\}/g) || [];
  if (sourceVars.join(",") !== transVars.join(",")) {
    issues.push("Missing/extra interpolation variables");
  }

  // Cek panjang (terjemahan biasanya 20-40% lebih panjang)
  const ratio = translated.length / source.length;
  if (ratio > 3 || ratio < 0.3) {
    issues.push(`Suspicious length ratio: ${ratio.toFixed(1)}x`);
  }

  // Cek HTML tags masih valid
  const sourceTags = source.match(/<[^>]+>/g) || [];
  const transTags = translated.match(/<[^>]+>/g) || [];
  if (sourceTags.length !== transTags.length) {
    issues.push("HTML tag mismatch");
  }

  return issues;
}

Yang akan kamu pelajari