Command Palette

Search for a command to run...

WordPress에서 Hreflang을 추가하는 방법(플러그인 없음)

WordPress에서 Hreflang을 추가하는 방법(플러그인 없음)

T
Toolz Team
|Aug 23, 2026|13 최소 읽기

SEO 도구 모음의 일부

대부분의 워드 프레스 hreflang 조언은 & quot;다국어 플러그인을 설치하고 그것을 처리합니다.& quot; 플러그인이 번역을 소유 할 때 괜찮습니다. 내가 가장 자주 히트 경우 잘못된 답변입니다: 두 개 또는 세 개의 언어 버전이 별도의 하위 디렉토리로 구축 된 사이트,별도의 설치,또는 수동으로 번역 된 페이지의 집합,아무도 전체 번역 프레임 워크와 네 페이지에 대한 데이터베이스 스키마를 원하지 않는 곳.

나는 번역이 손으로 작성되고 아래에 살고있는 문서 사이트를 포함하여 그 모양으로 워드 프레스 속성을 유지 /de/ 그리고 /es/. hreflang 테마 파일에는 40줄이 있고 하나의 배열에서 읽혀지며 표류한 적이 없습니다. 이 가이드는 해당 코드와 플러그인이 테마와 함께 hreflang을 방출할 때 잘못되는 부분입니다.

그것은 아래에 있습니다 완전한 흐레플랑 가이드, 옆에 Next.js 버전.

TL;DR: 워드프레스는 스스로 흐레플랑을 방출하지 않습니다. Hook wp_head를 사용하여 로케일 맵을 반복하고 다음을 포함한 전체 역수 세트를 인쇄합니다 x-default 그룹의 모든 페이지에서. Build URLs with home_url() 또는 하드 코딩보다는 로케일별 원본을 유지하고 각 페이지's 표준 자체 참조를 유지하고 SEO 플러그인이 이미 경쟁 블록을 방출하지 않는지 확인하십시오. 다중 사이트 설정의 경우 get_sites() 지도를 제공합니다; 번역된 페이지가 있는 단일 사이트의 경우 포스트 메타 필드 매핑 대응으로 충분합니다.

WordPress는 그 자체로 hreflang을 추가합니까?

No. Core는 표준 링크, 짧은 링크, 다양한 피드 및 REST 링크를 출력합니다 wp_head하지만 언어에 관한 어떤 것도 번갈아 가며 사용되지 않습니다. get_locale() 사이트가 어떤 언어에 있는지 알고 있으며 코어의 어떤 부분도 이를 주석으로 바꾸지 않습니다.

플러그인은 공백을 메웁니다. Polylang 과 WPML 은 그들이 관리하는 번역에 대해 hreflang 을 방출하며,대부분의 SEO 플러그인은 그들이 볼 수있는 번역 관계를 구성하면 그것을 방출합니다. 이미 그 중 하나를 사용하고 전체 사이트를 다루는 경우,사용하고이 기사를 건너 뛰십시오. 손으로 굴리는 이유는 플러그인이 알고있는 모든 것 외부에 번역이 존재하며 부분 세트를 방출하는 플러그인은 아무 것도 방출하지 않는 플러그인보다 나쁘기 때문입니다.

최소 버전: 배열 하나, 후크 하나

알려진 작은 URL 접두사 집합으로 번역된 사이트의 경우:

<?php
/**
 * Hreflang annotations for a hand-translated multilingual site.
 * Drop in the theme's functions.php or a small mu-plugin.
 */
function mysite_hreflang_map(): array {
    return [
        'en-US'     => 'https://example.com',
        'de-DE'     => 'https://example.com/de',
        'es-ES'     => 'https://example.com/es',
        'x-default' => 'https://example.com',
    ];
}

function mysite_print_hreflang(): void {
    $path = mysite_current_path(); // e.g. '/pricing/'
    foreach ( mysite_hreflang_map() as $hreflang => $origin ) {
        printf(
            '<link rel="alternate" hreflang="%s" href="%s" />' . "\n",
            esc_attr( $hreflang ),
            esc_url( untrailingslashit( $origin ) . $path )
        );
    }
}
add_action( 'wp_head', 'mysite_print_hreflang', 1 );

손으로 쓴 블록은 일반적으로 그렇지 않은 세 가지 사항이 있습니다.

모든 페이지에 전체 세트를 인쇄합니다를 포함하여 page&#39;s 자신의 언어. 상호성은 구조적으로 만족된다: 항목이 생략될 수 있는 브랜치가 없다,왜냐하면 브랜치가 전혀 없기 때문이다.

x-default 는 같은 배열의 행입니다따라서 동일한 루프에 의해 방출되며 하나의 템플릿에서 잊혀질 수 없습니다.

URL이 이스케이프됩니다. esc_url href에서 wp_head 는 선택 사항이 아니며, hreflang 값이 통과합니다 esc_attr 같은 이유로.

현재 경로를 알아봅니다

길은 보살핌이 필요한 부분이다. 왜냐하면 길이어야 하기 때문이다 이내에 전체 요청 URI가 아닌 언어입니다.

function mysite_current_path(): string {
    $home = wp_parse_url( home_url(), PHP_URL_PATH ) ?: '';
    $req  = wp_parse_url( $_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH ) ?: '/';

    // Strip the language prefix this install is served under.
    if ( $home && str_starts_with( $req, $home ) ) {
        $req = substr( $req, strlen( $home ) );
    }
    return user_trailingslashit( '/' . ltrim( $req, '/' ) );
}

독일 설치가 살아있는 경우 example.com/de 그리고 방문자는 켜져 있습니다 example.com/de/preise/, 이것이 돌아옵니다 /preise/그 때 각 locale&#39;s 근원으로 접두어를 얻는. 뒤에 오는 슬래시 취급은 그것이 보는 보다는 더 많은 것을 중요합니다: /preise 그리고 /preise/ 는 다른 URL이며, 비정규 형식에 주석을 가리키는 것은 입니다 후행 슬래시 불일치 이는 세트에서 완벽해 보이는 반환 태그 오류를 생성합니다. user_trailingslashit 사이트 존중&#39;s permalink 설정, 그래서 워드 프레스가 제공하는 무엇이든 일치합니다.

여기서 가정은 번역된 URL이 구조적으로 평행하다는 것입니다: /pricing/ 지도 /de/pricing/. 만약 당신의 독일어 slugs 도 번역되어 있다면, /de/preise/는, 이 함수는 충분하지 않으며, 다음 섹션인 명시적 매핑이 필요합니다.

slugs가 다를 때: 포스트 메타 매핑

번역 slugs는 사용자와 순위에 더 나은, 그리고 그들은 경로가 파생 될 수 없습니다 의미 대신: 상대를 저장

/**
 * Meta key holds a JSON map: {"de-DE": 123, "es-ES": 456} of post IDs,
 * or absolute URLs for external installs.
 */
function mysite_alternates_for( int $post_id ): array {
    $raw = get_post_meta( $post_id, '_hreflang_alternates', true );
    $map = $raw ? json_decode( $raw, true ) : [];
    if ( ! is_array( $map ) ) {
        return [];
    }

    $out = [];
    foreach ( $map as $hreflang => $target ) {
        $url = is_numeric( $target ) ? get_permalink( (int) $target ) : $target;
        if ( $url ) {
            $out[ $hreflang ] = $url;
        }
    }
    return $out;
}

그럼 wp_head 콜백은 현재 post&#39;s 자신의 엔트리를 인쇄하기 전에 그 맵에 병합하므로,세트는 완전하고 자기 참조적이다:

function mysite_print_hreflang_mapped(): void {
    if ( ! is_singular() ) {
        return;
    }
    $post_id = get_queried_object_id();
    $alts    = mysite_alternates_for( $post_id );
    if ( count( $alts ) < 1 ) {
        return; // Nothing to declare: a one-entry cluster is not a cluster.
    }

    $alts[ mysite_hreflang_for_locale( get_locale() ) ] = get_permalink( $post_id );
    $alts['x-default'] = $alts['en-US'] ?? get_permalink( $post_id );

    foreach ( $alts as $hreflang => $url ) {
        printf(
            '<link rel="alternate" hreflang="%s" href="%s" />' . "\n",
            esc_attr( $hreflang ),
            esc_url( $url )
        );
    }
}

유지 관리 비용은 메타가 양쪽에 작성되어야한다는 것입니다. 대응 피커가있는 관리자 UI 가 정직한 솔루션입니다; CSV 에서지도를 채우는 WP-CLI 명령이 빠른 것입니다. 단방향 선언이 정확히이기 때문에 한 쪽에만 채우지 않아야합니다 반환 태그 누락 실패.

Multisite: 네트워크에서 지도를 파생합니다

각 언어가 다중 사이트 네트워크의 사이트인 경우 지도가 이미 존재합니다:

function mysite_network_hreflang_map(): array {
    $map = [];
    foreach ( get_sites( [ 'number' => 50 ] ) as $site ) {
        switch_to_blog( (int) $site->blog_id );
        $map[ mysite_hreflang_for_locale( get_locale() ) ] = home_url();
        restore_current_blog();
    }
    return $map;
}

결과를 임시로 캐시합니다; switch_to_blog a에서 wp_head 모든 요청에 대한 후크는 모든 규모의 네트워크에서 실제 비용입니다. 그리고 조심하십시오 get_locale() 언더 switch_to_blog: site&#39;s인 경우에만 전환된 사이트를 반영합니다 WPLANG 옵션이 설정되어 있는데, 이는 일반적인 경우이지만 상수를 통해 구성된 네트워크에서는 보장되지 않습니다.

귀하의 사이트에 맞는 접근 방식은 무엇입니까?

설정 접근 노력
병렬 slugs, 로케일이 거의 없습니다 정적 배열과 파생 경로 가장 낮은; 하나의 기능
번역됨 slugs 포스트 메타 대응 맵 보통; 편집 워크플로가 필요합니다
다중 사이트, 언어당 하나의 사이트 에서 파생 get_sites(), 캐시되었습니다 낮은 코드, 캐시 규율이 필요합니다
번역을 관리하는 Polylang 또는 WPML 플러그인&#39;s 출력을 사용합니다 x-default 를 방출하는지 확인합니다
수동 번역 필드가 있는 SEO 플러그인 그것을 사용하고, 그 다음 렌더링된 헤드를 확인한다 중복 블록을 감시합니다

대신 사이트맵에 hreflang을 넣습니다

페이지 헤드가 이미 혼잡하거나 블록이 헤드의 나머지 부분보다 길어질 정도로 충분한 로케일이 있는 경우 사이트맵이 대안입니다. WordPress 5,5 이상 제공 핵심 사이트맵그리고 필터는 대체 항목과 네임스페이스 선언을 염두에 두고 설계되지 않았지만 필터링이 가능합니다 <urlset> 은 코어가 깔끔하게 만질 수 있는 것이 아니다.

실용적인 경로는 싸움이 아닌 재작성 규칙에 따라 제공되는 독립형 사이트맵입니다 wp_sitemaps:

add_action( 'init', function () {
    add_rewrite_rule( '^sitemap-i18n\.xml$', 'index.php?mysite_i18n_sitemap=1', 'top' );
} );

add_filter( 'query_vars', fn( $vars ) => array_merge( $vars, [ 'mysite_i18n_sitemap' ] ) );

add_action( 'template_redirect', function () {
    if ( ! get_query_var( 'mysite_i18n_sitemap' ) ) {
        return;
    }
    header( 'Content-Type: application/xml; charset=UTF-8' );

    echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" ';
    echo 'xmlns:xhtml="http://www.w3.org/1999/xhtml">' . "\n";

    foreach ( mysite_translated_paths() as $path ) {
        echo "  <url>\n    <loc>" . esc_url( home_url( $path ) ) . "</loc>\n";
        foreach ( mysite_hreflang_map() as $hreflang => $origin ) {
            printf(
                '    <xhtml:link rel="alternate" hreflang="%s" href="%s"/>' . "\n",
                esc_attr( $hreflang ),
                esc_url( untrailingslashit( $origin ) . $path )
            );
        }
        echo "  </url>\n";
    }
    echo '</urlset>';
    exit;
} );

제대로 하기 위한 두 가지. The xmlns:xhtml 선언 <urlset> 필수입니다; 그것 없이 대체 항목은 무시 되 고 파일은 여전히 다시 무음-실패 패턴인 사이트맵으로 유효성을 검사 합니다. 그리고 모든 요청이 아닌 활성화 시 규칙을 추가 한 후 규칙을 다시 작성 합니다.

이 작업을 수행한 후 헤드 출력을 제거합니다. 둘 다 방출하는 것은 구현 방법을 혼합합니다표류하는 두 가지 소스를 제공합니다.

중복 블록 문제

이것은 워드 프레스 특정 실패와 당신이 어떤 코드를 작성하기 전에 확인 가치가 하나입니다. 여러 플러그인은 hreflang 을 방출,그리고 하나 이상이 한 번에 활성화 될 수 있습니다. 번역 관계로 구성된 SEO 플러그인,다국어 플러그인,그리고 새로운 테마 기능은 모두 행복하게 인쇄 할 것입니다 wp_head그리고 그 결과는 내용이 다른 두세 개의 블록이고 아마도 두 개일 수도 있습니다 x-default 항목.

Google&#39;s 한 페이지 안에 모순 주석을 취급하는 것은 그들을 불신하는 것입니다. 그래서 hreflang 이 없었고 이제 세 개의 블록이있는 사이트는 이전보다 더 나빠질 수 있습니다.

플러그인 설정이 아닌 렌더링된 출력 확인:

curl -s https://example.com/de/preise/ | grep 'rel="alternate"' | grep hreflang

줄을 세고 구별되는 코드를 세어보세요. 로케일당 하나의 항목 더하기 하나 x-default그리고 아무것도 반복되지 않습니다. 플러그인이 구성할 수 없는 세트를 방출하는 경우 일반적인 이스케이프 해치는 해당 작업을 제거하는 것입니다 wp_head 위에 귀하의 항목을 추가하는 대신:

// Example shape: find the real hook and callback with `has_action`.
add_action( 'init', function () {
    remove_action( 'wp_head', 'some_plugin_hreflang_output', 10 );
} );

정식 태그를 깨지 않습니다

워드 프레스 방출 rel="canonical" 통해 단수 뷰의 경우 rel_canonical()그리고,그것은 당신이 원하는 무슨 post&#39;s 자신의 permalink 를 가리킨다. 대부분의 SEO 플러그인은 자신의 것으로 대체,또한 기본적으로 자기 참조.

에서의 규칙 흐레플랑 vs 캐노니컬 변경되지 않은 적용: 모든 페이지는 자체적으로 표준화되고 hreflang은 자체 표준 페이지 간의 관계를 설명합니다. 이를 깨는 WordPress 풍미의 방법은 번역된 게시물을 &quot;primary&quot;로 표준화하는 플러그인 설정입니다. 합리적인 중복 제거 옵션처럼 읽혀지고 색인에서 번역을 조용히 제거합니다. 설정이 언어 간 표준화를 제공하는 경우 해당 설정을 그대로 두십시오.

결과를 검증합니다

두 형제 페이지를 가져와 주석 블록을 비교합니다. 표준만 다르므로 동일해야 합니다. 그런 다음 이름을 지정한 모든 URL이 리디렉션 없이 200을 반환하는지 확인하세요. 왜냐하면 폐기된 로케일과 변경된 영구 링크는 올바른 집합이 깨진 집합으로 썩는 방식이기 때문입니다.

세트를 에 붙여넣습니다 무료 hreflang 발전기 코드 유효성 검사: ISO 모양과 비교하여 각 값을 확인하고 인식할 수 없는 하위 태그를 표시합니다 en-UK는,중복된 것을 잡아내어 상대 URL 을 거부하며,세트에 대체가 없을 때 경고한다. URL 이 아직 공개되지 않은 클라이언트 사이트를 설명할 때 중요한 브라우저에서 완전히 실행된다. 그리고 Search Console&#39;s International Targeting report 를 사용하여 진행 중인 체크를 하고,그리고 hreflang 도구 가이드 그 주변의 워크플로우를 위해.

자주 묻는 질문

WordPress는 hreflang 태그를 자동으로 추가합니까?

아니. 코어는 표준 링크와 다양한 헤드 링크를 방출하지만 언어에 대한 아무것도 대체. Hreflang 플러그인에서 또는 자신의에서 온다 wp_head 출력.

플러그인 없이 WordPress에서 hreflang을 어떻게 추가합니까?

후크 wp_head 그리고 a를 인쇄하세요 <link rel="alternate" hreflang> 다음을 포함하여 제어하는 지도의 모든 로케일에 대한 라인입니다 x-default 항목, 그룹의 모든 페이지에. 값에서 탈출 esc_attr 그리고 esc_url.

워드 프레스 테마에서 hreflang 태그는 어디로 이동합니까?

에 푹 기능에서 wp_head이상적으로는 테마가 아닌 작은 뮤 플러그인에 있으므로 테마를 전환해도 주석이 자동으로 삭제되지 않습니다.

만약 번역된 페이지가 다른 slugs를 가지고 있다면?

아무것도 도출하지 않습니다. 대응 게시물 ID 또는 URL 을 게시물 메타에 저장하고 렌더링 시 지도를 읽습니다. 양쪽에 채우거나 누락된 반환 태그를 만듭니다.

Polylang과 WPML은 hreflang을 처리합니까?

예, 그들이 관리하는 번역에 대한. 출력을 확인 포함 x-default 그리고 두 번째 플러그인은 경쟁 블록을 방출하지 않습니다.

왜 한 페이지에 두 개의 hreflang 블록이 있습니까?

두 가지가 인쇄됩니다 wp_head: 일반적으로 SEO 플러그인과 다국어 플러그인 또는 플러그인과 자신의 기능을 더한 것입니다. 한 페이지의 모순된 주석은 신뢰할 수 없으므로 레이어링보다는 하나를 제거하십시오.

각 워드 프레스 언어 버전은 자신의 정경을 가져야 하는가?

네,자기 참조입니다. 번역된 포스트를 기본 언어로 표준화하는 플러그인 설정을 사용하지 마세요,왜냐하면 그러면 인덱스에서 제거되고 hreflang 세트가 취소되기 때문입니다.

WordPress 멀티사이트 네트워크에서 hreflang을 어떻게 추가하나요?

루프 get_sites(), 각 블로그로 전환하여 해당 로케일과 home_url()를,그리고 결과 맵을 transient 에 캐시합니다. 실행 중 switch_to_blog 모든 요청에 따라 wp_head 는 큰 네트워크에서 비싸다.


Comments

0 comments

0/2000 characters

No comments yet. Be the first to share your thoughts!