Support Log in

41. Language-Specific Redirects

Developer Guide
Prefer video? Watch the Lang Forge tutorials 9 short guides covering every feature Watch

Control how visitors are redirected based on language preferences.

Browser Language Detection Redirect

Lang Forge ships a built-in, SEO-safe Accept-Language redirect. Enable it with update_option('lf_auto_detect_language', true) (or the Settings checkbox). On the visitor’s first page load the plugin:

  1. Skips if lf_language or lf_autodetect_done cookies exist, if the request is not GET, or if X-Requested-With: XMLHttpRequest is set — so AJAX, POST, and logged-in admin flows are never redirected.
  2. Parses the browser’s Accept-Language header against the site’s active languages.
  3. If a non-default language matches, issues wp_safe_redirect('/' . $detected . '/', 302) and sets lf_autodetect_done=1 (1-year cookie, is_ssl()-aware, Secure when serving HTTPS) so the browser never gets redirected again.
  4. If the detected language matches the default (or nothing matches), simply writes the lf_autodetect_done marker and continues — subsequent visits stay on /.

This replaces the earlier behaviour of silently serving translated content at the canonical URL, which broke hreflang and confused crawlers.

#### Overriding or extending the built-in redirect

If you need custom logic (geo-IP, user-agent allowlists, subdomain-specific opt-outs, etc.), disable the built-in flag and hook template_redirect yourself. The recipe below mirrors the plugin’s own implementation and is a good starting point:

php
/**
 * Custom first-visit language redirect. Run only when the built-in
 * `lf_auto_detect_language` option is OFF — otherwise you'll double-redirect.
 */
add_action('template_redirect', function () {
    if (get_option('lf_auto_detect_language', false)) return;       // plugin already handles it
    if (!empty($_COOKIE['lf_language']))              return;       // visitor has chosen
    if (!empty($_COOKIE['lf_autodetect_done']))       return;       // already redirected
    if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'GET') return;    // POST/PUT never redirect
    if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']))    return;       // AJAX

    $current = lf_get_current_language();
    $default = lf_get_default_language();
    if ($current !== $default) return;                              // already on a language URL

    $accept = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
    $preferred = [];
    foreach (explode(',', $accept) as $part) {
        $part = trim($part);
        [$lang, $q] = array_pad(explode(';', $part, 2), 2, 'q=1');
        $preferred[substr(trim($lang), 0, 2)] = floatval(str_replace('q=', '', $q));
    }
    arsort($preferred);

    $languages = lf_get_languages();
    foreach ($preferred as $code => $q) {
        if (!isset($languages[$code]) || $code === $default) continue;

        // Match the plugin's cookie name so the two paths share state.
        setcookie(
            'lf_autodetect_done', '1',
            time() + YEAR_IN_SECONDS,
            COOKIEPATH, COOKIE_DOMAIN, is_ssl()
        );
        wp_safe_redirect(home_url('/' . $code . '/'), 302);
        exit;
    }
}, 5);

Stick to the lf_autodetect_done cookie name — when the built-in redirect is later flipped on, it’ll honour the cookie your custom code already set and won’t re-redirect the same visitor.

Country-Based Redirects

php
/**
 * Redirect based on IP geolocation.
 * Requires a geolocation service or database.
 */
add_action('template_redirect', function () {
    if (isset($_COOKIE['lf_geo_redirect'])) return;
    if (!is_front_page()) return;

    $country_map = [
        'DE' => 'de', 'AT' => 'de', 'CH' => 'de',
        'FR' => 'fr', 'BE' => 'fr',
        'US' => 'en', 'GB' => 'en', 'AU' => 'en',
    ];

    // Use your preferred geolocation method
    $country = apply_filters('theme_detect_country', '');

    if ($country && isset($country_map[$country])) {
        $target_lang = $country_map[$country];
        $current = lf_get_current_language();

        if ($target_lang !== $current && isset(lf_get_languages()[$target_lang])) {
            $core = LF_Core::instance();
            setcookie('lf_geo_redirect', '1', time() + 86400 * 7, '/');
            wp_redirect($core->get_language_url($target_lang), 302);
            exit;
        }
    }
}, 4);

Forge AI Assistant Online

Hi! I'm the Lang Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs