Studio完全解説|スプレッドシートで多言語対応の実装手順
Studioには標準の多言語化機能がありません。スプレッドシート×GAS×ID差し替え方式で、Studioの構造を崩さずに翻訳管理を外部化する実務的な多言語対応の実装手順を解説します。
Studioで作ったサイトの多言語対応の方法でお悩みを持つユーザーは多いです。海外ユーザーへの発信やインバウンド対応を考えると、サイトの多言語化は必須テーマです。
Studioには標準でサイト全体をワンクリックで多言語化できる機能はありません。そのため多言語サイトを構築しようとすると、次のような課題が発生します。
- 言語ごとにページを複製する必要がある😵
- 翻訳修正のたびに複数ページを修正する必要がある🔧
- 外部サービス(Weglotなど)はコストがかかる💰
サイト規模が大きくなるほど、運用コストは確実に増加します。この記事では、Studioの構造を崩さずに多言語対応を実現する、実務的な方法として「ID差し替え方式」を解説します。
全体構成 🧩
スプレッドシートを使ったStudioサイトの多言語化の全体構成は以下の通りです。
Google Spreadsheet(翻訳マスタ) ↓ Google Apps Script(JSON API) ↓ Studio(ID一致でテキスト差し替え)
この構成の最大の特徴は、翻訳管理をStudioの外に完全に分離できることです✨
それでは、全5ステップに分けて多言語化を実装していきましょう。
STEP1 |翻訳マスタを作成する 📊
手順1|新規に翻訳マスタとなるGoogleスプレッドシートを作成します。

手順2|シート名をi18nに変更します。

手順3|翻訳マスタを以下のカラム構成で作成します。
| key | ja | en | zh |
|---|---|---|---|
| hero_title | 理想のサイトを | Build your ideal website | 打造理想網站 |
| cta_button | まずは無料相談 | Free consultation | 免費諮詢 |
以下のように、日本語、英語、中国語をそれぞれのkeyに対応するように翻訳マスタを作成します。

- 半角英数字+アンダースコアのみ使用
- ページ単位で命名すると管理しやすい
例:home_hero_title、nav_home、blog_title
STEP2|GASで翻訳JSON APIを作成する ⚡
手順1|拡張機能「Apps Script」を使って翻訳マスタをJSON配信します。

手順2|コードの内容を以下のように書き換えます。最初に自動で入っているfunction myFunction() {}などのコードは削除してOKです。コードの中の「スプレッドシートID」に、ご自身のスプレッドシートIDを入力してください。
スプレッドシートURL内の「d/」と「/edit?」の間の文字列がIDです。
https://docs.google.com/spreadsheets/d/スプレッドシートID/edit?pli=1&gid=0#gid=0
function doGet(e) {
var lang = (e && e.parameter && e.parameter.lang) ? String(e.parameter.lang) : "ja";
var sheet = SpreadsheetApp
.openById("スプレッドシートID")
.getSheetByName("i18n");
var values = sheet.getDataRange().getValues();
var headers = values.shift(); // [key, ja, en, zh...]
var keyIndex = 0;
var langIndex = headers.indexOf(lang);
if (langIndex === -1) langIndex = headers.indexOf("ja");
var dict = {};
for (var i = 0; i < values.length; i++) {
var row = values[i];
var k = row[keyIndex];
if (!k) continue;
dict[String(k)] = (row[langIndex] != null) ? String(row[langIndex]) : "";
}
var payload = { lang: lang, dict: dict, updated_at: new Date().toISOString() };
return ContentService
.createTextOutput(JSON.stringify(payload))
.setMimeType(ContentService.MimeType.JSON);
}
STEP3 Studio側で翻訳対象にIDを設定する 🏷
Studioでは任意のdata属性を追加できないため、IDを翻訳キーとして使用します。
設定方法Studio → 要素選択 → 設定 → タグ・属性 → ID入力
例:hero_title、cta_start、nav_home
スプレッドシートのkeyと完全一致させる必要があります。
STEP4 カスタムコードを設置する 💻
サイト設定 → カスタムコード → body末尾に設置します。
<script type="module">
(async () => {
const gasUrl = "GASのURL";
const supported = ["ja", "en", "zh"];
const cacheKeyPrefix = "i18n_cache_";
const cacheTtlMs = 24 * 60 * 60 * 1000;
const qs = new URLSearchParams(location.search);
const rawLang = qs.get("lang");
const urlLang = supported.includes(rawLang) ? rawLang : "ja";
document.documentElement.setAttribute("lang", urlLang);
function setActive(target) {
const pairs = [
["lang_ja", "ja"],
["lang_en", "en"],
["lang_zh", "zh"],
["lang_ja_sp", "ja"],
["lang_en_sp", "en"],
["lang_zh_sp", "zh"]
];
pairs.forEach(([id, code]) => {
const el = document.getElementById(id);
if (!el) return;
if (code === target) el.setAttribute("aria-current", "true");
else el.removeAttribute("aria-current");
});
}
function buildUrl(target) {
const u = new URL(location.href);
if (target === "ja") u.searchParams.delete("lang");
else u.searchParams.set("lang", target);
return u.pathname + "?" + u.searchParams.toString() + u.hash;
}
function bind(id, target) {
const el = document.getElementById(id);
if (!el) return;
el.addEventListener("click", (e) => {
e.preventDefault();
setActive(target);
sessionStorage.setItem("pending_lang", target);
location.href = buildUrl(target);
});
}
setActive(urlLang);
const pending = sessionStorage.getItem("pending_lang");
if (pending && supported.includes(pending)) {
setActive(pending);
sessionStorage.removeItem("pending_lang");
}
bind("lang_ja", "ja");
bind("lang_en", "en");
bind("lang_zh", "zh");
bind("lang_ja_sp", "ja");
bind("lang_en_sp", "en");
bind("lang_zh_sp", "zh");
const cacheKey = cacheKeyPrefix + urlLang;
function apply(dict) {
Object.keys(dict).forEach((key) => {
const el = document.getElementById(key);
if (el) el.textContent = dict[key];
});
}
let cached = null;
try {
cached = JSON.parse(localStorage.getItem(cacheKey));
} catch (e) {}
if (cached && cached.dict) {
apply(cached.dict);
}
const isFresh = cached && cached.t && (Date.now() - cached.t) < cacheTtlMs;
if (!isFresh) {
try {
const res = await fetch(gasUrl + "?lang=" + urlLang, { cache: "force-cache" });
const json = await res.json();
const dict = json.dict || {};
if (!cached || JSON.stringify(cached.dict) !== JSON.stringify(dict)) {
apply(dict);
localStorage.setItem(cacheKey, JSON.stringify({
dict,
t: Date.now()
}));
}
} catch (e) {
console.error("i18n fetch error:", e);
}
}
})();
</script>
STEP5 言語切替ボタンを作成する 🔁
Studioで言語ボタンを配置します。JA / EN / 中文
それぞれのID:lang_ja、lang_en、lang_zh
言語はURLクエリで制御します。例:?lang=en
この構成のメリット ✅
- 翻訳修正はスプレッドシートのみ
- CMSページにも対応可能
- Studio側の修正が最小限
- ノーコードのまま拡張できる
- 運用コストを大幅削減できる
まとめ
Studioでも設計次第で、実用レベルの多言語サイトは十分に構築できます。スプレッドシート×GAS×ID差し替え方式はノーコード制作の自由度と運用性を両立できる現実的な解決策です。まずはクエリ方式で運用を安定させ、必要に応じてSEO対応構成へ発展させるとよいでしょう。
