日本語版と英語版の両方を用意したサイトで、検索結果に英語版ばかり出てしまう——そんなときに使うのが hreflang 属性です。ただしこの属性には、リンク先の言語を添えるだけの使い方と、言語別ページの対応関係を検索エンジンに伝える使い方の2種類があり、混同されがちです。この記事では両者の違いを整理したうえで、実務で主役になる <link rel="alternate" hreflang="…"> の書き方、x-default の意味、そして設定したのに出し分けが効かないときの原因までを解説します。
目次
hreflang には2つの使い道がある
hreflang は「リンク先の言語」を示す属性です。ここが最初のポイントで、そのページ自身の言語ではありません。指定できるのは href を持つ要素、つまり <a> と <link> です。同じ属性名でありながら、この2つでは実務上の役割がまったく違います。
| 書き方 | 役割 |
|---|---|
<a href="…" hreflang="en"> | このリンクの先は英語のページです、という補足情報。ブラウザーや支援技術へのヒントで、表示や動作は変わらない |
<link rel="alternate" hreflang="en" href="…"> | このページと同じ内容の英語版がここにあるという対応関係の宣言。検索エンジンが言語別ページを出し分けるために使う |
多言語サイトの運用で問題になるのは、ほぼ後者です。日本語版と英語版が別々の URL に存在するとき、検索エンジンから見ればそれは単に内容の似た2ページでしかありません。「これは同じページの言語違いです」と教えてやらないと、利用者の言語に合ったほうを出す判断ができないのです。その宣言を担うのが <link rel="alternate"> と hreflang の組み合わせです。
link rel=”alternate” で言語別ページの対応を伝える
日本語版が https://example.com/ja/、英語版が https://example.com/en/ にある2言語サイトを例にします。書く場所は各ページの <head> の中です。
<head>
<meta charset="UTF-8">
<title>サービスのご案内</title>
<!-- 自分自身(日本語版)も含めて、全言語分を並べる -->
<link rel="alternate" hreflang="ja" href="https://example.com/ja/">
<link rel="alternate" hreflang="en" href="https://example.com/en/">
</head>
rel="alternate" が「代替版がある」ことを、hreflang がその代替版の言語を、href がその URL を示しています。ここで見落としやすいのが、日本語版のページに日本語版自身への行も書いている点です。自分を除いて他言語だけを列挙するのではなく、自己参照を含めた全言語分をセットで書きます。
そして英語版のページにも、まったく同じ内容の2行を書きます。
<head>
<meta charset="UTF-8">
<title>Our Services</title>
<!-- 日本語版と同一の並び。ここを省くと対応関係が成立しない -->
<link rel="alternate" hreflang="ja" href="https://example.com/ja/">
<link rel="alternate" hreflang="en" href="https://example.com/en/">
</head>
この「お互いが相手を指し合っている状態」が hreflang の要です。Google は、2つのページが互いに参照し合っていない場合、そのタグは無視されると明記しています。片側にしか書いていない宣言は、書いていないのとほぼ同じ扱いになると考えてください。
対応関係はページ単位で成立します。トップページどうし、料金ページどうし、記事ページどうしというように、内容が対応する組み合わせごとにセットを書いていきます。サイト全体で1セットを使い回すのではない、という点に注意してください。
なお、Google はこの対応関係を伝える手段として、HTML の <link> のほかに HTTP レスポンスヘッダーと sitemap.xml も受け付けています。PDF のように HTML の <head> を持たないファイルはヘッダーで、ページ数が多くテンプレートに手を入れにくいサイトは sitemap で、という使い分けができます。どれか1つの方法で伝われば十分で、併用する必要はありません。
hreflang に指定する値|BCP 47 の言語タグと x-default
hreflang の値には BCP 47 の言語タグを書きます。これは lang 属性で使うものと同じ書式で、言語コードだけの短い形から、地域や文字表記を付け足した形まで段階的に指定できます。
| 値 | 意味 |
|---|---|
ja | 日本語。言語コード(ISO 639-1)だけの形。地域を問わない |
en | 英語。地域を問わないので、まずはこの形で十分なことが多い |
en-US | アメリカ向けの英語。言語コード+ハイフン+地域コード(ISO 3166-1 alpha-2) |
en-GB | イギリス向けの英語。同じ英語でも国ごとに出し分けたいときに使う |
zh-Hant | 繁体字の中国語。ハイフンのあとが文字表記(スクリプト)を表す形 |
zh-Hans | 簡体字の中国語 |
x-default | どの言語・地域にも一致しなかった利用者に案内する既定のページ |
地域コードは省略できますが、言語コードは省略できません。「アメリカ向け」だけを表したくても hreflang="US" とは書けず、必ず en-US のように言語から始めます。また、地域を付けるかどうかは「同じ言語で内容を出し分けているか」で判断します。英語版が1つしかないなら en で書けばよく、通貨や送料の表記を変えた米国向け・英国向けを別々に用意しているなら en-US と en-GB に分ける、という考え方です。
x-default はどの言語にも当てはまらない利用者向け
x-default は言語タグではなく、Google が定めている特別な値です。利用者のブラウザーの設定が、宣言したどの言語・地域とも一致しなかったときに案内するページを指定します。たとえば日本語版と英語版しかないサイトを、ドイツ語環境の利用者が訪れたときにどこへ導くか、を決めておくための行だと考えてください。
言語を選ばせるページや、地域判定でリダイレクトを行うトップページがあるなら、そこを x-default に指定するのが自然です。特にそうしたページがなければ、主要な言語版(多くは英語版)を指すことになります。先ほどの例に x-default を足すと、次の3行になります。
<link rel="alternate" hreflang="ja" href="https://example.com/ja/">
<link rel="alternate" hreflang="en" href="https://example.com/en/">
<!-- どちらの言語にも当てはまらない利用者を、言語選択ページへ案内する -->
<link rel="alternate" hreflang="x-default" href="https://example.com/">
x-default は必須ではありません。ただ、想定外の言語環境からの訪問をどこで受け止めるかを自分で決められるので、多言語サイトなら書いておく価値があります。この3行も、/ja/・/en/・/ のすべてのページに同じ内容で置きます。
a 要素の hreflang はリンク先の言語を添えるだけ
もう一方の使い方、<a> 要素の hreflang も見ておきましょう。日本語の文章の中から英語の資料へリンクする、といった場面で使います。
<p>
詳細は
<a href="https://example.com/en/spec/" hreflang="en" lang="en">Technical Specification</a>
(英語)で公開されています。
</p>
ここで hreflang="en" は「このリンクの飛び先が英語である」ことを、lang="en" は「このリンクテキスト自体が英語である」ことを示しています。役割が違うので、両方書くことに意味があります。スクリーンリーダーは lang を見て Technical Specification を英語の発音で読み上げられます。
大事なのは、MDN が「組み込まれている機能はありません」と明記しているとおり、hreflang を付けても表示や動作は何も変わらないということです。リンク先が自動的に翻訳されるわけでも、ブラウザーが言語に応じて別の URL へ飛ばしてくれるわけでもありません。あくまでブラウザーや支援技術、クローラーに向けた補足情報です。
また、上の例で「(英語)」と本文に書いているように、利用者に伝えたい情報は目に見える形でも書くべきです。属性だけでは、多くの利用者はリンク先が英語だと気付けません。
設定しても言語別ページが正しく出し分けられないとき
hreflang は書式がゆるく、間違っていてもエラーが出ません。ブラウザーの表示も変わらないので、書いたつもりで効いていない状態に気付きにくいのが厄介なところです。うまく出し分けられないときは、次の点を順に確認してください。
相互参照が片方向だけになっている
最も多いのがこれです。日本語版に英語版へのリンクを書いたのに、英語版側には何も書いていない。あるいは、日本語版だけテンプレートを更新して英語版のテンプレートを直し忘れている。こうした片方向の状態では、Google は宣言そのものを無視します。A が B を指しているだけでは足りず、B も A を指していて初めて対応関係が成立すると覚えてください。
ページ単位のずれも同じ結果を招きます。日本語の記事ページから英語のトップページを指してしまうと、英語のトップページ側は日本語の記事ページを指していないので、やはり成立しません。対応するページどうしで正確にペアを組む必要があります。
相対 URL で書いている
同じサイト内のページを指すので、つい /en/ と書きたくなります。しかし Google は、代替 URL は http または https といった転送プロトコルを含む完全修飾形式で指定する必要があるとしています。ドメインから書いた絶対 URL にしてください。
<!-- 悪い例:相対 URL・プロトコル省略はどちらも避ける -->
<link rel="alternate" hreflang="en" href="/en/">
<link rel="alternate" hreflang="en" href="//example.com/en/">
<!-- 良い例:スキームとドメインから書く -->
<link rel="alternate" hreflang="en" href="https://example.com/en/">
あわせて、末尾のスラッシュの有無や www の有無も、実際に配信している URL と一致させます。リダイレクトされる URL を書いていると、指し先が食い違って相互参照が崩れることがあります。
言語コードの位置に国コードを書いている
hreflang="jp" は誤りです。jp は日本という国を表すコードであって、日本語という言語のコードは ja です。日本語では国名と言語名がほぼ同義に語られるため、この取り違えは非常に起きやすく、しかも見た目には自然なのでレビューでも見逃されがちです。
同じ種類の間違いに hreflang="uk"(イギリス英語のつもり)があります。uk はウクライナ語の言語コードなので、意図とまったく違う宣言になってしまいます。イギリス英語なら en-GB です。国を指定したいときは、必ず言語コードのあとにハイフンでつなぐ形にしてください。
<!-- 悪い例:jp は国コード、uk はウクライナ語 -->
<link rel="alternate" hreflang="jp" href="https://example.com/ja/">
<link rel="alternate" hreflang="uk" href="https://example.com/en-gb/">
<!-- 良い例:先頭は必ず言語コード。国は後ろに付ける -->
<link rel="alternate" hreflang="ja" href="https://example.com/ja/">
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/">
lang 属性と hreflang を取り違えている
値の書式が同じなので混ざりやすいのですが、この2つは指している対象が違います。lang はその要素自身(そのページ自身)の言語、hreflang はリンク先の言語です。
| 属性 | 示すもの | 書く場所 |
|---|---|---|
lang | その要素の中身が何語で書かれているか | <html> をはじめ、あらゆる要素(グローバル属性) |
hreflang | リンク先の URL が何語のページか | <a> と <link>(href があるとき) |
hreflang を整えても、各ページの <html lang="…"> が全ページ ja のまま、というのもありがちです。英語版のページには <html lang="en"> を指定してください。hreflang が「他の言語版の場所」を伝えるものであるのに対し、lang は「今見ているこのページの言語」を伝えるもので、どちらも必要です。
canonical が別の言語のページを指している
<link rel="canonical"> は「重複するページのうち、正規のものはこれです」と伝えるためのものです。ここで英語版の canonical に日本語版の URL を書いてしまうと、「英語版は日本語版の重複である」と宣言することになり、hreflang の意図と真っ向から矛盾します。
言語別ページは重複コンテンツではなく、それぞれが独立した正規のページです。したがって各言語ページの canonical は、それぞれ自分自身を指します。
<!-- canonical は自分自身。日本語版を指してはいけない -->
<link rel="canonical" href="https://example.com/en/">
<!-- hreflang は全言語分をセットで -->
<link rel="alternate" hreflang="ja" href="https://example.com/ja/">
<link rel="alternate" hreflang="en" href="https://example.com/en/">
canonical と hreflang は役割が別で、canonical はサイト内の重複を整理するもの、hreflang は言語違いの関係を示すものです。多言語対応プラグインを入れているサイトでは、プラグインが出力する canonical が意図と違っていないか、実際のページのソースを表示して確かめてみてください。
まとめ
hreflang は「リンク先の言語」を示す属性で、<a> に付けた場合はブラウザーや支援技術への補足情報にとどまり、表示や動作は変わりません。多言語サイトで主役になるのは <head> に書く <link rel="alternate" hreflang="…"> のほうで、これによって同じ内容の言語別ページの対応関係を検索エンジンに伝えられます。
値は BCP 47 の言語タグを使い、ja や en のような言語コードだけの形を基本に、必要に応じて en-US や zh-Hant のように地域・文字表記を足します。どの言語にも当てはまらない利用者向けには x-default を用意しておくと安心です。
実装で外せないのは、すべてのページに自分自身を含む全言語分を書き、絶対 URL で相互に指し合うという一点です。加えて、jp ではなく ja と書くこと、lang はページ自身の言語として別に指定すること、canonical はそれぞれ自分自身を指すこと。この3つを押さえておけば、よくあるつまずきはほとんど避けられます。