Support Log in

3. Post Translation Functions

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

Functions for retrieving and managing translation relationships between posts. These are the primary API for working with post translations from theme templates and custom plugins.

lf_get_post_language($post_id)

Returns the language code assigned to a specific post.

php
/**
 * Get the language of a post.
 *
 * @param  int    $post_id WordPress post ID
 * @return string Language code. Falls back to the default language
 *                if no language meta is set.
 */
$lang = lf_get_post_language(42);
// Returns: 'en'
ParameterTypeDescription
$post_idintWordPress post ID
Return TypeDescription
stringLanguage code (e.g., 'en'). Returns the default language if no _lf_language meta exists.
Example 1: Display language badge on posts
php
// In The Loop
$lang = lf_get_post_language(get_the_ID());
$languages = lf_get_languages();
$lang_name = $languages[$lang]['native_name'] ?? $lang;
$flag = $languages[$lang]['flag'] ?? $lang;
$flag_url = plugins_url('langforge/assets/flags/' . $flag . '.svg');

echo '<span class="lang-badge">';
echo '<img src="' . esc_url($flag_url) . '" alt="" width="16" height="12"> ';
echo esc_html($lang_name);
echo '</span>';
Example 2: Group posts by language in an admin report
php
// Build a language breakdown for a set of posts
$all_posts = get_posts(['posts_per_page' => -1, 'post_type' => 'post']);
$by_language = [];

foreach ($all_posts as $post) {
    $lang = lf_get_post_language($post->ID);
    if (!isset($by_language[$lang])) {
        $by_language[$lang] = 0;
    }
    $by_language[$lang]++;
}

// $by_language = ['ru' => 45, 'en' => 38, 'de' => 12]
Example 3: Conditional logic based on post language
php
// single.php - Show a translation notice if the post is not in the visitor's preferred language
$post_lang = lf_get_post_language(get_the_ID());
$current_lang = lf_get_current_language();

if ($post_lang !== $current_lang) {
    $translations = lf_get_post_translations(get_the_ID());
    if (isset($translations[$current_lang])) {
        $translated_url = get_permalink($translations[$current_lang]);
        echo '<div class="translation-notice">';
        echo '<a href="' . esc_url($translated_url) . '">';
        _e('This page is available in your language', 'theme');
        echo '</a>';
        echo '</div>';
    }
}

lf_get_post_translations($post_id)

Returns all translations linked to a post, including the post itself.

php
/**
 * Get all translations for a post.
 *
 * Uses an in-memory cache: when you fetch translations for one post
 * in a group, all posts in that group are cached for the rest of
 * the request.
 *
 * @param  int   $post_id WordPress post ID
 * @return array Associative array: language_code => post_id
 */
$translations = lf_get_post_translations(42);
// Returns: ['ru' => 42, 'en' => 99, 'de' => 155]
ParameterTypeDescription
$post_idintWordPress post ID
Return TypeDescription
arrayAssociative array mapping language codes to post IDs. Always includes the source post. Returns empty array if no translation data exists.
Example 1: Show “Available in” links on a single post
php
// single.php
$translations = lf_get_post_translations(get_the_ID());
$languages    = lf_get_languages();
$current      = lf_get_current_language();

if (count($translations) > 1) {
    echo '<div class="also-available">';
    echo '<span>' . esc_html__('Also available in:', 'theme') . ' </span>';
    $links = [];
    foreach ($translations as $lang_code => $trans_id) {
        if ($lang_code === $current) continue;
        $name = $languages[$lang_code]['native_name'] ?? $lang_code;
        $links[] = '<a href="' . esc_url(get_permalink($trans_id)) . '">' . esc_html($name) . '</a>';
    }
    echo implode(', ', $links);
    echo '</div>';
}
Example 2: Build a translation completeness indicator
php
// Show which languages are missing translations for this post
$translations = lf_get_post_translations(get_the_ID());
$all_languages = lf_get_languages();
$missing = array_diff_key($all_languages, $translations);

if (!empty($missing)) {
    echo '<div class="missing-translations">';
    echo '<strong>Missing translations:</strong> ';
    $names = [];
    foreach ($missing as $code => $lang) {
        $names[] = esc_html($lang['name']);
    }
    echo implode(', ', $names);
    echo '</div>';
}
Example 3: Preload translations for a custom post loop
php
// Efficient pattern: preload translations before a loop
$query = new WP_Query(['post_type' => 'post', 'posts_per_page' => 20]);
$post_ids = wp_list_pluck($query->posts, 'ID');

// Warm the cache: first call per translation group triggers 1 query
foreach ($post_ids as $pid) {
    lf_get_post_translations($pid);
}

// Now display posts with translation info - all cache hits
while ($query->have_posts()) {
    $query->the_post();
    $trans = lf_get_post_translations(get_the_ID()); // 0 queries
    $trans_count = count($trans);
    echo '<p>' . get_the_title() . ' (' . $trans_count . ' languages)</p>';
}
wp_reset_postdata();

lf_get_translation($post_id, $language)

Returns the post ID of a specific translation.

php
/**
 * Get a single translation of a post.
 *
 * @param  int    $post_id  WordPress post ID
 * @param  string $language Target language code
 * @return int|null          Translated post ID, or null if not found
 */
$en_id = lf_get_translation(42, 'en');
// Returns: 99
ParameterTypeDescription
$post_idintWordPress post ID
$languagestringTarget language code (e.g., 'en', 'de')
Return TypeDescription
intnullTranslated post ID, or null if no translation exists for that language
Example 1: Link to the English version of the current post
php
$en_version = lf_get_translation(get_the_ID(), 'en');

if ($en_version) {
    echo '<a href="' . esc_url(get_permalink($en_version)) . '">';
    echo '<img src="' . esc_url(plugins_url('langforge/assets/flags/gb.svg')) . '" alt="English" width="20"> ';
    echo 'Read in English';
    echo '</a>';
} else {
    echo '<span class="no-translation">English version not available</span>';
}
Example 2: Build a hreflang-aware canonical URL
php
add_action('wp_head', function () {
    if (!is_singular()) return;

    $languages = lf_get_languages();
    $post_id = get_the_ID();

    foreach ($languages as $code => $lang) {
        $trans_id = lf_get_translation($post_id, $code);
        if ($trans_id) {
            $url = get_permalink($trans_id);
            $hreflang = str_replace('_', '-', $lang['locale']);
            echo '<link rel="alternate" hreflang="' . esc_attr($hreflang) . '" href="' . esc_url($url) . '">' . "n";
        }
    }
});
Example 3: Cross-language related posts widget
php
// Show the same post in other languages as "Read in other languages" widget
function theme_cross_language_widget($post_id) {
    $languages = lf_get_languages();
    $current = lf_get_current_language();
    $has_translations = false;

    echo '<div class="widget cross-language-widget">';
    echo '<h3>' . esc_html__('Read in other languages', 'theme') . '</h3>';
    echo '<ul>';

    foreach ($languages as $code => $lang) {
        if ($code === $current) continue;
        $trans_id = lf_get_translation($post_id, $code);
        if ($trans_id) {
            $has_translations = true;
            $title = get_the_title($trans_id);
            echo '<li>';
            echo '<a href="' . esc_url(get_permalink($trans_id)) . '">';
            echo esc_html($lang['native_name']) . ': ' . esc_html($title);
            echo '</a>';
            echo '</li>';
        }
    }

    echo '</ul>';
    echo '</div>';

    return $has_translations;
}

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