2026年5月20日
2026年5月20日
WordPressのhreflang設定方法(多言語対応)
はじめに
hreflang属性はWordPressで多言語サイトを運営する際に、各ページの言語と対象地域をGoogleに伝えるための属性です。設定を誤ると意図しない言語のページが検索結果に表示されたり、重複コンテンツと認識されたりします。
症状・原因
- 日本語ページが英語圏の検索結果に表示される(またはその逆)
- 英語版・日本語版の記事が重複コンテンツとみなされている
- hreflangを設定したがSearch Consoleで「alternateページ(正規ページのhreflangなし)」エラーが出る
- PolylangやWPMLのhreflang出力が正しいか確認したい
解決手順
ステップ1:hreflangの基本ルールを理解する
【hreflangの書き方】
<!-- 言語のみ指定 -->
<link rel="alternate" hreflang="ja" href="https://example.com/ja/post/">
<link rel="alternate" hreflang="en" href="https://example.com/en/post/">
<!-- 言語 + 地域指定 -->
<link rel="alternate" hreflang="en-US" href="https://example.com/en-us/post/">
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/post/">
<link rel="alternate" hreflang="zh-TW" href="https://example.com/zh-tw/post/">
<!-- どの言語にも該当しないユーザー向けのデフォルトページ -->
<link rel="alternate" hreflang="x-default" href="https://example.com/">
【必須ルール】
1. 自己参照必須: 各ページに自分自身のhreflangも含める
2. 相互参照必須: AページがBを指したら、BページもAを指す
3. 絶対URL使用: 相対URLは不可
4. カノニカルと一致: hreflangのURLとカノニカルURLが一致すること
5. x-defaultは通常トップページまたは言語選択ページに設定
ステップ2:Polylangプラグインのhreflang設定
// Polylangが自動でhreflangを出力する
// 設定 → Polylang → 言語タブで言語を追加するだけで有効
// Polylangのhreflang出力をカスタマイズする場合
add_filter('pll_hreflang_attributes', function(array $hreflangs): array {
// x-defaultを追加
if (!isset($hreflangs['x-default'])) {
$hreflangs['x-default'] = home_url('/');
}
return $hreflangs;
});
// Polylangで翻訳ページが存在しない場合の処理
add_filter('pll_the_language_link', function(?string $url, string $slug): ?string {
if (!$url) {
// 翻訳がない場合は言語トップページへのリンク
return pll_home_url($slug);
}
return $url;
}, 10, 2);
ステップ3:WPMLのhreflang設定
// WPMLも自動でhreflangを出力する
// WPML → 言語 → 言語ネゴシエーションを設定
// WPMLのhreflang出力を確認
add_action('wp_head', function(): void {
if (defined('ICL_LANGUAGE_CODE')) {
// WPMLが有効な場合、hreflangは自動で出力される
// wpml_hreflang_output フィルターでカスタマイズ可能
}
}, 99);
// WPMLで x-default を設定
add_filter('wpml_hreflang_output', function(string $output): string {
$default_url = apply_filters('wpml_permalink', home_url('/'), 'en');
$x_default = '<link rel="alternate" hreflang="x-default" href="'
. esc_url($default_url) . '">' . PHP_EOL;
return $x_default . $output;
});
ステップ4:プラグインなしで手動hreflangを実装する
// functions.php: 手動でhreflangを実装(プラグインなし)
// ※ 記事に対応する翻訳記事IDをカスタムフィールドで管理する場合
add_action('wp_head', function(): void {
if (!is_singular()) return;
global $post;
// カスタムフィールドから対応翻訳記事を取得
// 例: _translation_ja, _translation_en にIDを保存
$translations = [
'ja' => get_post_meta($post->ID, '_translation_ja', true),
'en' => get_post_meta($post->ID, '_translation_en', true),
'zh' => get_post_meta($post->ID, '_translation_zh', true),
];
// 現在のページの言語を取得
$current_lang = get_post_meta($post->ID, '_post_language', true) ?: 'ja';
// 自己参照を含む hreflang 一覧を構築
$hreflangs = [];
// 自己参照
$hreflangs[$current_lang] = get_permalink($post->ID);
// 翻訳ページへのリンク
foreach ($translations as $lang => $trans_id) {
if ($trans_id && $lang !== $current_lang) {
$trans_url = get_permalink((int)$trans_id);
if ($trans_url) {
$hreflangs[$lang] = $trans_url;
}
}
}
// x-default(日本語をデフォルトに設定)
$hreflangs['x-default'] = $hreflangs['ja'] ?? get_permalink($post->ID);
// 出力
foreach ($hreflangs as $lang => $url) {
echo '<link rel="alternate" hreflang="' . esc_attr($lang)
. '" href="' . esc_url($url) . '">' . PHP_EOL;
}
}, 5);
ステップ5:hreflangの設定ミスを診断する
# hreflangの出力を確認
curl -s https://example.com/ja/post/ | grep -i hreflang
# 相互参照の確認(英語ページが日本語ページを指しているか)
curl -s https://example.com/en/post/ | grep -i hreflang
# Search Console でのエラー確認
# Search Console → インデックス → カバレッジ
# 「alternateページ(正規ページのhreflangなし)」エラー
# → 相互参照が欠けている可能性
# hreflang バリデーターツール(ブラウザで)
# https://www.aleydasolis.com/en/international-seo-tools/hreflang-tags-generator/
// functions.php: hreflangのデバッグ情報を管理画面に表示
add_action('admin_notices', function(): void {
if (!current_user_can('manage_options')) return;
$screen = get_current_screen();
if (!$screen || $screen->base !== 'post') return;
global $post;
if (!$post) return;
$current_lang = get_post_meta($post->ID, '_post_language', true);
$trans_ja = get_post_meta($post->ID, '_translation_ja', true);
$trans_en = get_post_meta($post->ID, '_translation_en', true);
if ($current_lang) {
echo '<div class="notice notice-info"><p>';
echo "hreflang設定: 言語={$current_lang}";
if ($trans_ja) echo " / JA翻訳ID={$trans_ja}";
if ($trans_en) echo " / EN翻訳ID={$trans_en}";
echo '</p></div>';
}
});
注意事項
- hreflangで指定するすべてのURLは正しく到達可能(200 OK)である必要があります。404や301リダイレクトのURLを指定すると無効になります
- hreflangは
rel="canonical"と矛盾してはいけません。あるページのカノニカルがA、hreflangがBを指すような設定は無効です - Googleは
x-hreflangをHTTPヘッダーまたはXMLサイトマップでも受け付けます。wp_headに出力できない場合(AMP等)はサイトマップ経由での実装を検討してください
まとめ
hreflangは①自己参照必須、②相互参照必須、③絶対URL使用、④カノニカルURLと一致、⑤x-defaultの設定、の5つのルールを守ることが重要です。Polylangはhreflangを自動出力するため最も簡単に実装できます。プラグインなしで実装する場合はwp_headフィルターで各言語の記事IDをカスタムフィールドで管理して出力します。Search Consoleの「alternateページ(正規ページのhreflangなし)」エラーは相互参照の欠如が原因のことがほとんどです。