Command Palette

Search for a command to run...

כיצד להוסיף Hreflang בוורדפרס (ללא תוסף)

כיצד להוסיף Hreflang בוורדפרס (ללא תוסף)

T
Toolz Team
|Aug 23, 2026|13 קריאה דקות

חלק מאוסף כלי SEO

רוב עצות wordPress hreflang הוא " להתקין תוסף רב לשוני והוא מטפל בו." זה בסדר כאשר התוסף הוא הבעלים של התרגומים שלך. זוהי התשובה השגויה במקרה שאני מכה לרוב: אתר עם שתיים או שלוש גרסאות שפה שנבנו כספריות משנה נפרדות, התקנות נפרדות או קבוצה של דפים מתורגמים ידנית, שבהם אף אחד לא רוצה מסגרת תרגום מלאה וסכימת מסד הנתונים שלה לארבעה עמודים.

אני שומר על מאפייני וורדפרס בצורה זו, כולל אתרי תיעוד שבהם התרגומים נכתבים בכתב יד וחיים תחתיהם /de/ ו /es/. ה-hreflang שם הוא ארבעים שורות בקובץ ערכת נושא, הוא קורא ממערך אחד, והוא מעולם לא נסחף. מדריך זה הוא הקוד הזה, בתוספת החלקים שמשתבשים כאשר תוסף פולט hreflang לצד ערכת הנושא שלך.

זה יושב מתחת ל מדריך hreflang שלם, ליד ה גרסת Next.JS.

TL;DR: וורדפרס לא פולט hreflang בפני עצמו. וו wp_head, לולאה על מפת מקום, והדפיס את הסט ההדדי המלא כולל x-default בכל עמוד בקבוצה.Build URLs with home_url() או מקור לכל מקום במקום קידוד קשיח, שמור כל עמוד 's הפניה עצמית קנונית, ובדוק שאף תוסף SEO כבר לא פולט בלוק מתחרה עבור הגדרות מרובות אתרים, get_sites() נותן לך את המפה; עבור אתר בודד עם דפים מתורגמים, די במיפוי שדה מטא של פוסטים.

האם וורדפרס מוסיפה hreflang בפני עצמה?

מס 'Core מוציא קישור קנוני, קישור קצר, וקישורי הזנה ו REST שונים מ wp_head, אבל שום דבר בשפה לא מתחלף. get_locale() יודע באיזו שפה האתר נמצא ואף חלק מהליבה לא הופך את זה להערה.

תוספים ממלאים את החסר פולילנג וWPML פולטים hreflang עבור התרגומים שהם מנהלים, ורוב התוספים לקידום אתרים יפלטו את זה אם תגדיר קשר תרגום שהם יכולים לראות אם אתה כבר משתמש באחד מאלה והוא מכסה את כל האתר שלך, השתמש בו ודלג על מאמר זה הסיבה לגלגול ידני היא שהתרגומים שלך קיימים מחוץ לכל מה שהתוסף יודע עליו, ותוסף שפולט סט חלקי גרוע יותר מאשר אחד שלא פולט אף אחד.

הגרסה המינימלית: מערך אחד, וו אחד

עבור אתר שתרגומיו הם קבוצה ידועה וקטנה של קידומות 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 );

שלושה דברים זה מסתדר שבלוקים בכתב יד בדרך כלל לא.

הוא מדפיס את הסט המלא בכל עמוד, כולל הדף&#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/, אשר לאחר מכן מקבל קידומת עם כל מקום &#39;s מקור. החתך הנגרר מטפל בעניינים יותר ממה שהוא נראה: /preise ו /preise/ האם כתובות URL שונות, והצבעת הערה בצורה הלא קנונית היא אי התאמה של קו נטוי נגרר זה מייצר שגיאות תג החזרה בסט שאחרת נראה מושלם. user_trailingslashit מכבד את הגדרת הקישור הקבוע של האתר &#39;s, כך שהוא תואם לכל מה שוורדפרס מגישה.

ההנחה כאן היא שכתובות 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 callback ממזג את הפוסט הנוכחי &#39; הכניסה שלו למפה זו לפני ההדפסה, כך שהסט שלם והפניה עצמית:

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 )
        );
    }
}

עלות התחזוקה היא שהמטא צריך להיות כתוב משני הצדדים ממשק משתמש אדמין עם בוחר מקביל הוא הפתרון הישר; פקודת WP-CLI המאכלסת את המפה מ-CSV היא המהירה. מה שאסור לך לעשות זה לאכלס אותה בצד אחד בלבד, כי הצהרה חד כיוונית היא בדיוק תג החזרה חסר כישלון.

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: הוא משקף את האתר שהוחלף רק אם האתר &#39;s WPLANG האפשרות מוגדרת, וזה המקרה הרגיל אך לא מובטח ברשתות המוגדרות באמצעות קבוע.

איזו גישה מתאימה לאתר שלך?

הגדרה גישה מאמץ
slugs מקביל, מעט אזורים מערך סטטי בתוספת נתיב נגזר הנמוך ביותר; פונקציה אחת
תורגם slugs מפת מקבילה שלאחר מטא בינוני; צריך זרימת עבודה לעריכה
מולטי-אתר, אתר אחד לכל שפה לִנְקוֹעַ get_sites(), שמור במטמון קוד נמוך, צריך משמעת מטמון
Polylang או WPML ניהול תרגומים השתמש בפלט התוסף &#39;s ודא שהוא פולט x-default
תוסף SEO עם שדות תרגום ידניים השתמש בו, ואז בדוק את הראש המעובד צפה עבור בלוקים כפולים

הכנסת hreflang למפת האתר במקום זאת

אם ראשי הדפים שלך כבר צפופים, או שיש לך מספיק מקומות שהחסימה ארוכה יותר משאר הראש, מפת האתר היא האלטרנטיבה. וורדפרס 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;
} );

שני דברים שצריך לעשות נכון. ה 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(), וזה מצביע על הפוסט & #39;s permalink משלו, וזה מה שאתה רוצה רוב תוספי SEO להחליף אותו עם משלהם, גם הפניה עצמית כברירת מחדל.

הכלל מ hreflang לעומת קנוני חל ללא שינוי: כל עמוד מתגלגל לעצמו, ו-hreflang מתאר את היחסים בין אותם דפים קנוניים עצמיים הדרך בטעם וורדפרס לשבור אותו היא הגדרת תוסף שמפרקת פוסטים מתורגמים ל-&quot;primary&quot; גרסת שפה, הנקראת כמו אפשרות ביטול כפילות הגיונית ומסירה בשקט את התרגומים שלך מהאינדקס. אם הגדרה מציעה לבצע קנוניזציה בין שפות, השאר אותה כבויה.

אימות התוצאה

אחזר שני דפי אחים והשווה את בלוקי ההערות שלהם. הם צריכים להיות זהים, כאשר רק השונה הקנוני. לאחר מכן בדוק שכל כתובת URL שציינת מחזירה 200 מבלי להפנות מחדש, מכיוון שמקומות שיצאו משימוש וקישורים קבועים שהשתנו הם הדרך שבה קבוצה נכונה נרקבת לשבורה.

הדבק את הסט לתוך גנרטור hreflang חינם כדי לאמת את הקודים: הוא בודק כל ערך מול צורת ה-ISO, מסמן תגי משנה לא מזוהים כמו en-UK, תופס כפילויות, דוחה כתובות URL יחסיות ומזהיר כאשר לסט אין נפילה. הוא פועל כולו בדפדפן, מה שחשוב כאשר כתובות האתרים מתארות אתר לקוח שעדיין אינו ציבורי. לאחר מכן השתמש ב-Search Console&#39; דוח מיקוד בינלאומי לבדיקה המתמשכת, וה מדריך כלי Hreflang לזרימת העבודה סביבו.

שאלות נפוצות

האם וורדפרס מוסיפה תגי hreflang באופן אוטומטי?

מס 'Core פולט קישור קנוני וקישורי ראש שונים אבל שום דבר על חילופי שפה. Hreflang מגיע מתוסף או משלך wp_head פלט.

איך אני מוסיף hreflang בוורדפרס ללא תוסף?

ווּק wp_head ולהדפיס א <link rel="alternate" hreflang> קו לכל מקום במפה שאתה שולט בו, כולל א x-default כניסה, בכל עמוד בקבוצה הבריחו את הערכים עם esc_attr ו esc_url.

לאן הולכים תגי hreflang בערכת נושא של וורדפרס?

בפונקציה המחוברת ל wp_head, באופן אידיאלי בתוסף mu קטן ולא בערכת הנושא, כך שהחלפת ערכות נושא לא שומטת בשקט את ההערות שלך.

מה אם לדפים המתורגמים שלי יש slugs שונה?

גזרו כלום אחסן את מזהי הפוסטים המקבילים או כתובות האתרים במטא הפוסטים וקרא את המפה בזמן העיבוד. אכלס אותו משני הצדדים, או שאתה יוצר תג החזרה חסר.

האם Polylang ו-WPML מטפלים ב-hreflang?

כן, לתרגומים שהם מנהלים ודא שהפלט כולל x-default וששום תוסף שני לא פולט בלוק מתחרה.

למה יש לי שני בלוקים hreflang בעמוד אחד?

שני דברים מדפיסים ל wp_head: בדרך כלל תוסף SEO בתוספת תוסף רב לשוני, או תוסף בתוספת פונקציה משלך הערות סותרות בדף אחד הם חוסר אמון, אז להסיר אחד ולא שכבות.

האם לכל גרסת שפת וורדפרס צריכה להיות קנונית משלה?

כן, הפניה עצמית אל תשתמש בהגדרת תוסף שמפרקת פוסטים מתורגמים לשפה ראשית, כי זה מסיר אותם מהאינדקס ומבטל את ערכת hreflang.

כיצד אוכל להוסיף hreflang ברשת מרובת אתרים של וורדפרס?

לולאה get_sites(), עבור לכל בלוג כדי לקרוא את המקום שלו ו home_url(), ושמור את המפה שהתקבלה במטמון בחולף. רָצִיץ switch_to_blog על כל בקשה ב wp_head יקר ברשת גדולה.


Comments

0 comments

0/2000 characters

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