このサイトは元々WordPressで管理していましたが、いろいろあってSanity+Astroに移行しました。(移行のまとめ記事はこちら)移行により機能追加の自由度が上がったので、日本語記事の英訳版を公開できるようにすることにしました。
きっかけは、海外(英語圏)向けにPODグッズのオンラインショップを運営し始めたことです。商品だけでなく、その母体にどのような活動や考え方があるのかも、英語圏の人に伝えられるサイトにしたいと考えました。
最初は有名プラットフォームを活用した方がいいかと思い、海外向けの記事はMediumで公開していました。ただ、複数のプラットフォームにコンテンツを分散させるのは管理が面倒です。また、SNS的な要素のあるサービスを継続的に運用するのも、自分の性分にはあまり合いません。
できるだけ自分のサイト内でどうにかしたかったので、Sanity+Astro環境に、手動で英訳記事を追加する機能を実装しました。
この記事は、小さめの個人サイトの英語対応を、どのように行ったかの記録です。
自動翻訳ではなく、人の目を通す
note、Medium、Redditなどのように、ページ全体を自動翻訳して表示する方が実装も運用も楽です。
それでも人の目で確認した英訳版を用意することにしたのは、自動翻訳では意図やニュアンスが少し違ってしまうことがあるからです。
日本語の言葉をあえてローカライズせず、そのまま残したい場合もあります。文化の違いを考えると、元の文章をそのまま訳すと変に受け取られそうな部分もあります。言葉遣いがよろしくないので、誤解を招く可能性も高いです。
人の目を通す、といっても英語力が全然ないので、変な訳になるところもありそうですが、一応、どういう表現を残し、どこを補足するか判断したいと考えました。
実現したかったこと
英語対応の要件は、次のように整理しました。
- 日本語記事は従来どおり
/{slug}/で公開する - 英訳を表示させる記事は
/en/{slug}/で公開する - 英語タイトルや本文が空の状態では公開できないようにする
- 日本語版と英語版を相互に移動できるようにする
- 検索エンジンへ、言語違いの対応ページであることを伝える
- 英語記事を読んでいる間は、前後移動、関連記事、目次、検索、脚注もできるだけ英語にする
- 記事一覧から英訳版の有無が分かるようにする
サイト全体を本格的な多言語サイトへ作り直すのではなく、まず既存の記事作成フローへ無理なく英訳を追加できる範囲に絞りました。
日本語記事の中に英語フィールドを追加する
Sanityのlogドキュメントには、もともと日本語のタイトル、本文、メタディスクリプション、slug、公開日、画像、タクソノミーなどが入っています。
そこへ、折りたたみ可能なEnglish translationフィールドセットを追加しました。
| フィールド | 役割 |
|---|---|
englishPublished | 英語版を公開するスイッチ |
titleEn | 英語タイトル |
metaDescriptionEn | 英語検索結果向けの説明文 |
bodyEn | 英語本文 |
英訳を別のSanityドキュメントにする方法も考えられますが、今回は同じlog内に持たせました。最初は改修範囲を狭くし、既存の記事作成の流れへ組み込めるシンプルな形にしたかったからです。
同じ記事に入れておけば、slug、公開日、メイン画像、カテゴリ、タグ、シリーズなどは共有できます。日本語版と英語版の対応関係も明確です。
英語本文には、日本語本文と同じPortable Textの構造を使っています。Obsidian Markdownの貼り付け変換、画像、Blog Card、callout、脚注、区切りなども利用できます。
ただし、これは現時点の要件に合わせた方法です。今後、言語ごとに公開日、画像、分類、編集フローなどを完全に分けたくなれば、別の方法を検討したくなるかもしれません。でもめちゃくちゃ大変そうなので、それまでに言語の壁がもっと薄くなることを祈ります。
固定ページは、今のところ日英併記
Sanityで管理している通常の記事とは別に、Astroで直接書いている固定ページもあります。
それらは現在、同じページ内に日本語と英語を併記しています。例えば見出しなら、日本語の後に英語を置く形です(「日本語 / English」 みたいに)。
言語ごとにURLを分けることはできるようですが、今回はSanity記事の英訳版を公開することを優先し、固定ページは既存の日英併記を続けています。個人の小さなサイトだし、英語圏のPODショップと連携したいという目的なら、これで十分です。
サイト全体で完全に一貫した多言語構造になっているわけではありません。完全に多言語対応させたらどうなるんだろうと、ちょっと興味はありますが、今後の運用で不満が出たときに、あらためて検討する予定です。
未完成の英訳を公開しないようにする
英語フィールドを追加しただけでは、タイトルだけ入力した記事や、本文が空の記事にも/en/ページが作られる可能性があります。
そこで、englishPublishedをONにする場合は、titleEnとbodyEnを必須にしました。
if (!enabled) return true
if (!document.titleEn?.trim()) return 'English titleを入力してください。'
if (!Array.isArray(document.bodyEn) || document.bodyEn.length === 0) {
return 'English bodyを入力してください。'
}
return trueさらにAstro側のGROQでも、公開対象を次の条件で絞っています。
englishPublished == true &&
defined(titleEn) &&
count(bodyEn) > 0Studioの入力チェックと、ページ生成側のクエリの両方で確認する形です。操作ミスで公開スイッチだけONになっても、不完全な英語ページが生成されにくくなります。
/en/{slug}/を生成する
日本語記事は、これまでどおりsrc/pages/[slug].astroから生成します。
英語記事用にはsrc/pages/en/[slug].astroを追加し、公開条件を満たす記事だけを静的ページとして生成します。
日本語版 https://oneoffobject.com/example-slug/
英語版 https://oneoffobject.com/en/example-slug/英語ページでは、タイトル、本文、メタディスクリプションを英語フィールドへ差し替えます。slug、公開日、画像、タクソノミーなどは日本語版と共有します。
URL生成は共通関数へまとめ、前後記事や関連記事など、各コンポーネントが個別に/en/を組み立てないようにしました。
日英切替、canonical、hreflang
日本語記事に英語版がある場合だけ、Read in Englishのリンクを表示します。英語記事からは日本語で読むで元の記事へ戻れます。
英語版がない記事には切替リンクを出さないので、存在しない/en/ページへ移動することはありません。
HTML側では、言語に応じて<html lang="ja">と<html lang="en">を切り替えます。canonicalは各言語ページ自身のURLです。そのうえで、対応する日英ページをhreflangで相互に示します。
<link rel="canonical" href="https://oneoffobject.com/en/example-slug/">
<link rel="alternate" hreflang="ja" href="https://oneoffobject.com/example-slug/">
<link rel="alternate" hreflang="en" href="https://oneoffobject.com/en/example-slug/">
<link rel="alternate" hreflang="x-default" href="https://oneoffobject.com/example-slug/">Open Graphのlocaleも、日本語はja_JP、英語はen_USへ切り替えました。
これによって、検索エンジンへ同じ内容の重複ページではなく、言語違いの対応ページであることを伝えています。
本文以外のUIも英語にする
英語本文が表示されても、その周辺に日本語が大量に残っていると、英語記事としては読みにくくなるんじゃないかと思い、次のような細かい部分も言語に応じて切り替えました。
- 記事目次
- 前の記事/次の記事
- 関連記事
- 日付表示
- 検索ダイアログ
- テーマ切替ボタン
- ヘッダーのaria-label
- 脚注見出しと本文へ戻るリンク
前後記事は、英訳が公開されている記事だけを英語タイトルで取得します。英語記事を読んでいる途中で、次の記事だけ日本語ページへ飛ばさないようにするための対応です。
ヘッダー、フッターや共通部分もあるため、英語ページに日本語がまったく出てこないわけではありませんが、記事本文を読んでいる間できるだけ余計な情報が入りにくい状態を目指しました。
タクソノミーと一覧も日英対応する
記事だけ英訳しても、カテゴリやタグが日本語だけでは、英語読者がサイト内を移動しにくくなります。
そこで、category、tag、platform、series、projectに、英語名と英語説明文を追加しました。日本語名と英語名が同じ場合は、同じ語を重複して表示しない共通処理も入れています。
記事一覧とトップページのRecent Updatesでは、日本語タイトルと英語タイトルを関連付けて表示し、英訳がある場合だけ英語版へのリンクを出します。Nonfiction一覧には、英語版の有無による絞り込みも追加しました。
日本語タイトル
[EN] English title
Category: 日本語名 (English name)ターム名が長くなりやすいのは難点です。日本語名と英語名を両方出すため、一覧の情報量も増えます。ただ、ほかに決定的に良い方法が思いつかず、現時点ではそれほど重要な問題でもないため、この形にしました。
タクソノミーや固定ページにまで英語を加えたのは、ブラウザの翻訳機能を使わなくても、一応はサイト内を巡れるようにしたかったからです。
Pagefindの日本語検索と英語検索を分ける
このサイトでは、静的サイト向け検索のPagefindを使っています。
英訳記事の追加に合わせて、日本語ページは日本語の検索インデックス、英語ページは英語の検索インデックスへ入れるようにしました。英語ページの検索UIでは、Pagefindを英語モードで初期化します。
Astro build
└── dist/
├── 日本語ページ ──→ Pagefind ja index
└── /en/ページ等 ──→ Pagefind en indexサイト内検索を使う人がどの程度いるかは分からない、というかぶっちゃけほぼいないと思います。英語検索も、対応記事が少ないうちは効果が限定的です。それでも、一人でも使う人がいるかもしれんということで、初期実装に含めました。
Publishから本番反映までの流れ
実装は、大まかに次の段階に分けました。
- 英語フィールド、
/en/ページ、日英切替を追加 - Pagefindの英語検索インデックスを追加
- タクソノミー、記事一覧、固定ページを日英対応
- 公開後に見つかった脚注や重複表示などを修正
Sanity StudioでのPublishは、production datasetを更新する操作であり、公開中の静的HTMLを直接書き換えるものではありません。ただし、このサイトではSanityのWebhookからCloudflare PagesのDeploy Hookを呼び出しているため、PublishをきっかけにAstroの再ビルドとデプロイが自動で始まります。Pagefindの検索インデックスも、このビルド時に作り直されます。
実際の運用は次のようになります。
Obsidianなどで英訳を準備
↓
Sanity Studioへ貼り付け・確認
↓
englishPublishedをONにしてPublish
↓
WebhookからCloudflare Pagesのビルドを自動実行
↓
Astroの静的HTMLとPagefindインデックスを再生成・デプロイ
↓
数分後に/en/ URL、hreflang、英語検索を確認Publish後は反映を待って、本番URLと英語検索を確認するところまでを記事公開の流れに含めています(めんどくさくて飛ばすこともあります)。
SanityのPublishから本番反映までの仕組みについては、以前の記事「WordPressからSanity+Astroへ―個人サイトを作り直した記録」でも触れています。
後から対応した細かい部分
初回実装の後、英語が入っていなかった分類一覧ページへ英語文言を追加しました。また、英語記事の脚注も、見出しをFootnotes、戻りリンクをBack to textへ変更し、aria-labelまで英語化しています。
英語本文やページタイトルはすぐ気づけますが、脚注、アクセシビリティ用ラベル、共通フッターなどは見落としやすい部分です。
まだどこかに抜けが残っている可能性は大いにあります。WordPressからSanity+Astroへの移行の段階で英語対応を考えていれば、もっとスムーズに導入できたかもしれません。
まぁ明日どうなるかなんて分からないので、このあたりは仕方ありません。そもそも英語記事を書くことにするなんて、半年前には夢にも思っていません。行き当たりばったりでも、影響範囲を確認しながら少しずつ直せば、どうにかなるもんです。
英訳する記事の基準と今後の運用
現在(2026年08月21日)、一日一記事ほどのペースで、過去記事の英訳を増やしています。
英訳するかの基準は適当です。明らかに日本国内向けの内容でなければ、内容を見てなんとなくで選んでいます。見返すついでに日本語記事で気になる所の修正もできるので一石二鳥でした。
新規の日本語記事でも、英訳する意味がありそうなら日本語版と同時に英語版も公開していく予定です。
実装したばかりで、海外からの閲覧や検索流入には、まだ明確な変化はありません。英訳の目的である海外PODショップになんらかの成果が現れるか、現時点ではなんとも言えないし、別に根拠があってやったわけでもないのでどうなるかまったくわかりません。こうやってちょこちょこ整備していくのは好きなので、特に意味はなくても続けてみようと思います。
まとめ
サイトの多言語化について調べると、対応する言語の数や、コンテンツの種類など、目的によっていろいろな手段があります。しかし、企業サイトやWebサービス向けの情報はあるものの、個人サイトでこういう感じの対応方法の情報はなさげだったので、ニッチすぎる気がしますがまとめてみました。
固定ページの日英併記や、長くなったターム名など、妥協した点もありますが、Mediumに分散していた英語コンテンツを、自分のサイトの中で管理し、公開できる土台ができたので、だいぶスッキリしました。
DID YOU ENJOY THIS ARTICLE?
制作活動を支援する / Support my work
文章、アート、デザイン、個人開発を続けるための支援を、コーヒー一杯分から受け付けています。 / Help me keep making essays, art, design, and independent software.

情報 / Information

