Browse by section

Web Design & Dev 日本語

Building a Four-Language Translation API with Google Apps Script

Being able to translate Japanese into English, Korean, and Chinese at once would make some conversations easier, so I built a four-language translation API with Google Apps Script.

This article was published in 2023 and revised in September 2026. The gooLabs API I originally used for furigana was discontinued in March 2025, so the original code no longer runs. I have replaced it and also corrected a design error that was in the original.

  • The gooLabs API (labs.goo.ne.jp) stopped serving requests on 3 March 2025; the endpoint no longer connects
  • That API converted Japanese into hiragana and katakana, so applying it to Korean or Chinese was never going to produce the katakana readings I wanted

Furigana is now applied to the Japanese side, and I have written separately about what would actually be needed for Korean and Chinese readings.

Sponsored

What the API does

You send text in one language and it returns automatic translations into the other three.

The original intention was to attach katakana readings to the Korean and Chinese output, but the furigana API only handles Japanese, so that design cannot work. The corrected arrangement is:

  • Japanese: readings can be added with the furigana API
  • Korean and Chinese: what you would need is transliteration, not furigana, which is a different mechanism entirely

The full script

function translateText(text, targetLanguage) {
  const apiKey = "YOUR_GOOGLE_TRANSLATE_API_KEY";
  const sourceLanguage = "auto"; // detect the input language

  const response = UrlFetchApp.fetch(
    "https://translation.googleapis.com/language/translate/v2?key=" + apiKey +
    "&q=" + encodeURIComponent(text) +
    "&source=" + sourceLanguage +
    "&target=" + targetLanguage
  );

  const json = response.getContentText();
  const data = JSON.parse(json);
  const translatedText = data.data.translations[0].translatedText;

  return translatedText;
}

function addFurigana(text) {
  const appId = "YOUR_YAHOO_CLIENT_ID";

  const payload = {
    id: "1",
    jsonrpc: "2.0",
    method: "jlp.furiganaservice.furigana",
    params: { q: text, grade: 1 }
  };

  const response = UrlFetchApp.fetch("https://jlp.yahooapis.jp/FuriganaService/V2/furigana", {
    method: "post",
    contentType: "application/json",
    headers: { "User-Agent": "Yahoo AppID: " + appId },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });

  const data = JSON.parse(response.getContentText());
  return data.result.word.map(w => w.furigana || w.surface).join("");
}

function toKatakana(hiragana) {
  return hiragana.replace(/[ぁ-ゖ]/g, function (ch) {
    return String.fromCharCode(ch.charCodeAt(0) + 0x60);
  });
}

function main(inputLanguage, inputText) {
  const languages = ["en", "ko", "zh"];
  const responses = {};

  for (const targetLanguage of languages) {
    if (targetLanguage === inputLanguage) {
      continue; // do not translate into the input language
    }
    responses[targetLanguage] = translateText(inputText, targetLanguage);
  }

  // furigana applies to Japanese input
  if (inputLanguage === "ja") {
    responses["ja_furigana"] = toKatakana(addFurigana(inputText));
  }

  return JSON.stringify(responses);
}

Each function is explained below.

Sponsored

translateText(): calling Google Translate

Calls the Google Cloud Translation API and returns the translated string.

function translateText(text, targetLanguage) {
  const apiKey = "YOUR_GOOGLE_TRANSLATE_API_KEY";
  const sourceLanguage = "auto";

  const response = UrlFetchApp.fetch(
    "https://translation.googleapis.com/language/translate/v2?key=" + apiKey +
    "&q=" + encodeURIComponent(text) +
    "&source=" + sourceLanguage +
    "&target=" + targetLanguage
  );

  const json = response.getContentText();
  const data = JSON.parse(json);
  const translatedText = data.data.translations[0].translatedText;

  return translatedText;
}

addFurigana(): adding readings to Japanese

In short: this adds furigana to Japanese text. Because the gooLabs API shut down, it now uses Yahoo! Japan’s Furigana Web API.

That endpoint takes a JSON POST, so in Apps Script you pass options to UrlFetchApp.fetch.

function addFurigana(text) {
  const appId = "YOUR_YAHOO_CLIENT_ID"; // from the Yahoo! Developer Network

  const payload = {
    id: "1",
    jsonrpc: "2.0",
    method: "jlp.furiganaservice.furigana",
    params: {
      q: text,
      grade: 1
    }
  };

  const response = UrlFetchApp.fetch("https://jlp.yahooapis.jp/FuriganaService/V2/furigana", {
    method: "post",
    contentType: "application/json",
    headers: { "User-Agent": "Yahoo AppID: " + appId },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });

  const data = JSON.parse(response.getContentText());

  // readings come back per word, so join them into one string
  return data.result.word
    .map(w => w.furigana || w.surface)
    .join("");
}

The response is an array of words. Unlike the gooLabs API, it does not hand back a single converted string, so you need the join(). Words with no furigana field—symbols, numerals—fall back to surface, the original text.

grade selects a school year: setting it to 1 annotates essentially every kanji. Raising the number omits readings for kanji taught up to that grade.

Readings come back in hiragana. Convert them yourself if you want katakana.

function toKatakana(hiragana) {
  return hiragana.replace(/[ぁ-ゖ]/g, ch =>
    String.fromCharCode(ch.charCodeAt(0) + 0x60)
  );
}

Sponsored

The main function

function main(inputLanguage, inputText) {
  const languages = ["en", "ko", "zh"];
  const responses = {};

  for (const targetLanguage of languages) {
    if (targetLanguage === inputLanguage) {
      continue;
    }
    responses[targetLanguage] = translateText(inputText, targetLanguage);
  }

  // furigana goes on Japanese input
  if (inputLanguage === "ja") {
    responses["ja_furigana"] = toKatakana(addFurigana(inputText));
  }

  return JSON.stringify(responses);
}

In the code as originally published, the Korean and Chinese translations were passed through addFurigana. That was wrong. The furigana API performs Japanese morphological analysis, so handing it Hangul or simplified Chinese returns no readings. The version above applies furigana to the Japanese input itself.

Summary

This is a Google Apps Script API that translates Japanese into English, Korean, and Chinese simultaneously.

What building it taught me is that “adding readings” is a separate problem from translation. The furigana API assumes Japanese morphological analysis and cannot be applied to other languages. Producing katakana readings for Korean or Chinese requires a transliteration service, which is a different piece of infrastructure.

Anything built on an external API stops working when that service closes. That is exactly what happened here in March 2025. For a personal tool you can just rebuild it, but if you hand the thing to someone else, note down which APIs it depends on—recovery is much faster with that list.

The debugging approach for external API calls in Apps Script is the same as the one in outputting strings in PHP: log the raw response first and inspect its structure before writing any parsing.

If you are looking for books on HTML, CSS and JavaScript, see four books for learning web coding.