• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Setting Up and Registering Standard WordPress Comment Templates in Multi-Language Site Networks

Setting Up and Registering Standard WordPress Comment Templates in Multi-Language Site Networks

Understanding WordPress Comment Template Hierarchy

When WordPress renders comments on a post or page, it follows a specific template hierarchy. For single-site installations, the primary template file is typically comments.php. However, in a multisite environment, especially when dealing with internationalization, the default behavior might not be sufficient. We need to ensure that the correct comment template is loaded based on the active language of the site.

The core WordPress function responsible for loading templates is locate_template(), which is used internally by get_template_part() and other template loading functions. For comments, the process is slightly different. WordPress checks for specific files in the theme directory and its subdirectories. The standard lookup order for comment templates involves:

  • comments.php in the root of the active theme.
  • comments.php in the root of the parent theme (if a child theme is active).

This default behavior doesn’t inherently support language-specific templates. To achieve this, we need to hook into WordPress’s template loading process and provide our own logic.

Registering Language-Specific Comment Templates

The most robust way to manage language-specific comment templates is by leveraging WordPress’s internationalization features and custom template loading. We can create a function that filters the template path WordPress uses for comments. This filter is not directly exposed as a standard WordPress hook for comments.php itself, but we can achieve a similar effect by overriding the comments_template() function.

The comments_template() function is responsible for including the comment template file. We can filter the path it returns before it’s included. A common approach involves checking the current language context, often managed by plugins like WPML or Polylang.

Example: Using Polylang for Language Detection

Assuming you are using Polylang to manage your multilingual site, you can detect the current language using pll_current_language(). We’ll create a function that hooks into the comments_template filter (though this filter doesn’t exist directly, we’ll simulate its effect by modifying the behavior of comments_template()).

Let’s create a function within your theme’s functions.php file or a custom plugin. This function will check for language-specific comment template files in a designated subdirectory, for example, /languages/comments/.

Theme Structure for Language-Specific Templates

Your theme directory might look like this:

  • your-theme/
    • functions.php
    • style.css
    • index.php
    • page.php
    • single.php
    • comments.php (fallback/default)
    • languages/
      • comments/
        • comments-en.php
        • comments-fr.php
        • comments-es.php

Implementing the Template Loader

Here’s the PHP code to implement this logic. This code should be placed in your theme’s functions.php file or a custom plugin.

/**
 * Load language-specific comment template.
 *
 * This function attempts to load a language-specific comment template
 * before falling back to the default 'comments.php'.
 *
 * @param string $template The path to the comment template.
 * @return string The path to the comment template to be included.
 */
function my_theme_load_language_comment_template( $template ) {
    // Check if Polylang is active and get the current language slug.
    if ( function_exists( 'pll_current_language' ) ) {
        $current_lang = pll_current_language( 'slug' );

        // Define the path to the language-specific comment template.
        // We'll look for templates in a 'languages/comments/' subdirectory.
        $lang_template_path = trailingslashit( get_template_directory() ) . 'languages/comments/comments-' . $current_lang . '.php';

        // If the language-specific template exists, use it.
        if ( file_exists( $lang_template_path ) ) {
            return $lang_template_path;
        }
    }

    // Fallback to the default 'comments.php' if no language-specific template is found
    // or if Polylang is not active.
    // The original $template variable passed to the filter is usually the default path.
    // We ensure it's a valid path within the theme.
    $default_template_path = get_template_directory() . '/comments.php';
    if ( file_exists( $default_template_path ) ) {
        return $default_template_path;
    }

    // As a last resort, return the original $template, which might be a parent theme's path.
    return $template;
}
add_filter( 'comments_template', 'my_theme_load_language_comment_template' );

Explanation:

  • The function my_theme_load_language_comment_template is hooked into the comments_template filter. Note that this filter is not a standard WordPress filter for comments_template() itself, but rather a common pattern for overriding template loading. WordPress’s comments_template() function directly includes files, so we need to ensure our logic runs *before* the inclusion. A more direct approach might involve overriding the comments_template() function call within your theme’s template files (e.g., single.php, page.php) if the filter doesn’t behave as expected. However, the filter approach is cleaner if it works.
  • It checks if Polylang is active using function_exists( 'pll_current_language' ).
  • It retrieves the current language slug (e.g., ‘en’, ‘fr’, ‘es’) using pll_current_language( 'slug' ).
  • It constructs the expected path for the language-specific comment template: /wp-content/themes/your-theme/languages/comments/comments-[lang_slug].php.
  • If this file exists, its path is returned, and WordPress will include it.
  • If the language-specific template does not exist, or if Polylang is not active, it falls back to the default comments.php file in the theme’s root directory.

Creating the Language-Specific Comment Templates

Now, let’s create the actual template files. These files will contain the HTML structure and PHP logic for displaying comments and the comment form, tailored for each language.

Example: comments-en.php

<?php
/**
 * English comment template.
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Check if comments are open or if there are comments.
if ( post_password_required() ) {
    return;
}
?>

<div id="comments" class="comments-area">

    <?php if ( have_comments() ) : ?>
        <h2 class="comments-title">
            <?php
            $comment_count = get_comments_number();
            if ( 1 === $comment_count ) {
                esc_html_e( 'One thought on “%s”', 'your-text-domain' );
            } else {
                printf( esc_html__( '%1$s thoughts on “%2$s”', 'your-text-domain' ), number_format_i18n( $comment_count ), get_the_title() );
            }
            ?>
        </h2>

        <ol class="comment-list">
            <?php
                wp_list_comments( array(
                    'style'       => 'ol',
                    'short_ping'  => true,
                    'avatar_size' => 60,
                ) );
            ?>
        </ol><!-- .comment-list -->

        <?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : ?>
            <nav id="comment-nav-below" class="comment-navigation">
                <h1 class="screen-reader-text"><?php esc_html_e( 'Comment navigation', 'your-text-domain' ); ?></h1>
                <div class="nav-previous"><?php previous_comments_link( esc_html__( '&#8592; Older Comments', 'your-text-domain' ) ); ?></div>
                <div class="nav-next"><?php next_comments_link( esc_html__( 'Newer Comments &#8594;', 'your-text-domain' ) ); ?></div>
            </nav><!-- #comment-nav-below -->
        <?php endif; ?>

    <?php endif; ?>

    <?php
    // If comments are closed and there are no comments, let's leave the placeholder.
    if ( ! comments_open() && get_comments_number() ) :
        ?>
        <p class="no-comments"><?php esc_html_e( 'Comments are closed.', 'your-text-domain' ); ?></p>
    <?php
    endif;

    comment_form( array(
        'title_reply' => esc_html__( 'Leave a Reply', 'your-text-domain' ),
        'title_reply_to' => esc_html__( 'Leave a Reply to %s', 'your-text-domain' ),
        'cancel_reply_link' => esc_html__( 'Cancel reply', 'your-text-domain' ),
        'label_submit' => esc_html__( 'Post Comment', 'your-text-domain' ),
    ) );
    ?>

</div><!-- #comments .comments-area -->

Example: comments-fr.php

<?php
/**
 * French comment template.
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Check if comments are open or if there are comments.
if ( post_password_required() ) {
    return;
}
?>

<div id="comments" class="comments-area">

    <?php if ( have_comments() ) : ?>
        <h2 class="comments-title">
            <?php
            $comment_count = get_comments_number();
            if ( 1 === $comment_count ) {
                esc_html_e( 'Une réflexion sur “%s”', 'your-text-domain' );
            } else {
                printf( esc_html__( '%1$s réflexions sur “%2$s”', 'your-text-domain' ), number_format_i18n( $comment_count ), get_the_title() );
            }
            ?>
        </h2>

        <ol class="comment-list">
            <?php
                wp_list_comments( array(
                    'style'       => 'ol',
                    'short_ping'  => true,
                    'avatar_size' => 60,
                ) );
            ?>
        </ol><!-- .comment-list -->

        <?php if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) : ?>
            <nav id="comment-nav-below" class="comment-navigation">
                <h1 class="screen-reader-text"><?php esc_html_e( 'Navigation des commentaires', 'your-text-domain' ); ?></h1>
                <div class="nav-previous"><?php previous_comments_link( esc_html__( '&#8592; Commentaires plus anciens', 'your-text-domain' ) ); ?></div>
                <div class="nav-next"><?php next_comments_link( esc_html__( 'Commentaires plus récents &#8594;', 'your-text-domain' ) ); ?></div>
            </nav><!-- #comment-nav-below -->
        <?php endif; ?>

    <?php endif; ?>

    <?php
    // If comments are closed and there are no comments, let's leave the placeholder.
    if ( ! comments_open() && get_comments_number() ) :
        ?>
        <p class="no-comments"><?php esc_html_e( 'Les commentaires sont fermés.', 'your-text-domain' ); ?></p>
    <?php
    endif;

    comment_form( array(
        'title_reply' => esc_html__( 'Laisser un commentaire', 'your-text-domain' ),
        'title_reply_to' => esc_html__( 'Répondre à %s', 'your-text-domain' ),
        'cancel_reply_link' => esc_html__( 'Annuler la réponse', 'your-text-domain' ),
        'label_submit' => esc_html__( 'Poster le commentaire', 'your-text-domain' ),
    ) );
    ?>

</div><!-- #comments .comments-area -->

Key Considerations for Template Files:

  • Text Domain: Ensure you replace 'your-text-domain' with your theme’s actual text domain for proper internationalization. This allows strings to be translated using standard WordPress translation tools.
  • comments_template() Function: The comment_form() function is used to display the comment form. You can customize its arguments to change labels, add fields, etc.
  • wp_list_comments() Function: This function handles the display of existing comments. Its arguments control the output format, pingbacks, avatars, etc.
  • Conditional Logic: The code includes checks for post_password_required() and comments_open() to ensure correct behavior.
  • HTML Structure: The HTML structure should be consistent with your theme’s overall design and accessibility standards.

Advanced Diagnostics and Troubleshooting

If your language-specific comment templates are not loading, here are some advanced diagnostic steps:

1. Verify Polylang (or other Translation Plugin) Configuration

Procedure:

  • Navigate to your WordPress admin dashboard.
  • Go to Languages > Settings.
  • Ensure that the language slugs used in your template filenames (e.g., ‘en’, ‘fr’) match the slugs configured in Polylang.
  • Check the language switcher on the front-end to confirm that the correct language is being detected for the current page.

2. Debug Template Loading

Procedure:

  • Temporarily add debugging statements to your my_theme_load_language_comment_template function.
function my_theme_load_language_comment_template( $template ) {
    error_log( 'Original template path: ' . $template ); // Log the initial path

    if ( function_exists( 'pll_current_language' ) ) {
        $current_lang = pll_current_language( 'slug' );
        error_log( 'Current language slug: ' . $current_lang );

        $lang_template_path = trailingslashit( get_template_directory() ) . 'languages/comments/comments-' . $current_lang . '.php';
        error_log( 'Attempting to load: ' . $lang_template_path );

        if ( file_exists( $lang_template_path ) ) {
            error_log( 'Language-specific template FOUND.' );
            return $lang_template_path;
        } else {
            error_log( 'Language-specific template NOT FOUND.' );
        }
    }

    $default_template_path = get_template_directory() . '/comments.php';
    error_log( 'Falling back to default template: ' . $default_template_path );
    if ( file_exists( $default_template_path ) ) {
        return $default_template_path;
    }

    error_log( 'Returning original template path: ' . $template );
    return $template;
}
add_filter( 'comments_template', 'my_theme_load_language_comment_template' );

Analysis: Check your server’s PHP error log (often found in /var/log/apache2/error.log, /var/log/nginx/error.log, or accessible via your hosting control panel) for output from these error_log() calls. This will tell you exactly which paths WordPress is considering and whether the files are found.

3. Check File Permissions and Paths

Procedure:

  • Ensure that the languages/comments/ directory and the specific language comment template files (e.g., comments-en.php) have read permissions for the web server user (e.g., www-data, apache).
  • Double-check the spelling of directory and file names. Case sensitivity matters on some servers.
  • Verify that get_template_directory() is returning the correct path to your theme. You can log its output: error_log( 'Theme directory: ' . get_template_directory() );

4. Multisite Considerations

In a WordPress multisite setup, themes can be network-activated or site-specific. The get_template_directory() function will always return the path to the currently active theme for the specific site. If you are using a parent/child theme structure, ensure that the language-specific templates are placed within the child theme’s directory. If the child theme is active, get_template_directory() will point to the child theme. If you need to load templates from a parent theme, you would use get_stylesheet_directory() for the child theme and get_template_directory() for the parent theme.

5. Alternative: Overriding comments_template() Directly

If the filter approach proves unreliable or if you need more granular control, you can directly modify the call to comments_template() within your theme’s template files (e.g., single.php, page.php).

// In single.php or page.php, replace the standard call:
// comments_template();

// With this custom logic:
$comment_template = '';
if ( function_exists( 'pll_current_language' ) ) {
    $current_lang = pll_current_language( 'slug' );
    $lang_template_path = trailingslashit( get_template_directory() ) . 'languages/comments/comments-' . $current_lang . '.php';
    if ( file_exists( $lang_template_path ) ) {
        $comment_template = $lang_template_path;
    }
}

// Fallback to default if no language-specific template found
if ( empty( $comment_template ) ) {
    $default_template_path = get_template_directory() . '/comments.php';
    if ( file_exists( $default_template_path ) ) {
        $comment_template = $default_template_path;
    } else {
        // As a last resort, let WordPress find it (might be parent theme)
        $comment_template = locate_template( array( 'comments.php' ) );
    }
}

// Include the determined template
if ( ! empty( $comment_template ) ) {
    comments_template( $comment_template );
} else {
    // Fallback if even default isn't found (highly unlikely)
    comments_template();
}

This direct override provides explicit control over which template file is loaded, bypassing the need for a filter and offering clearer debugging paths.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Top 100 Automated PDF & Document Generation Tool Ideas for Developers that Will Dominate the Software Industry in 2026
  • Top 5 Automated PDF & Document Generation Tool Ideas for Developers in Highly Competitive Technical Niches
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers without Relying on Paid Advertising Budgets
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Double User Engagement and Session Duration
  • Building a Reactive Frontend Framework inside Theme Security Auditing: Mitigating XSS, CSRF, and SQLi Vulnerabilities under Heavy Concurrent Load Conditions

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (581)
  • DevOps (7)
  • DevOps & Cloud Scaling (956)
  • Django (1)
  • Migration & Architecture (187)
  • MySQL (1)
  • Performance & Optimization (780)
  • PHP (5)
  • Plugins & Themes (241)
  • Security & Compliance (543)
  • SEO & Growth (488)
  • Server (23)
  • Ubuntu (9)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (346)

Recent Posts

  • Top 100 Automated PDF & Document Generation Tool Ideas for Developers that Will Dominate the Software Industry in 2026
  • Top 5 Automated PDF & Document Generation Tool Ideas for Developers in Highly Competitive Technical Niches
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers without Relying on Paid Advertising Budgets
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Double User Engagement and Session Duration
  • Building a Reactive Frontend Framework inside Theme Security Auditing: Mitigating XSS, CSRF, and SQLi Vulnerabilities under Heavy Concurrent Load Conditions
  • Deep Dive: Memory Leak Prevention in Virtual CSS Variables and Dynamic Style Interpolation Using Custom Action and Filter Hooks

Top Categories

  • DevOps & Cloud Scaling (956)
  • Performance & Optimization (780)
  • Debugging & Troubleshooting (581)
  • Security & Compliance (543)
  • SEO & Growth (488)
  • Business & Monetization (390)

Our Products

  • School Management & Student Administration System
  • Integrated Hospital & Clinic Management System
  • Real Estate Directory & Agent Portal
  • Restaurant POS & Table Booking System
  • Retail Inventory POS & Billing System
  • Pharmacy Inventory & Clinic Billing System

Our Services

  • Vibe Engineering & AI Code Auditing Services
  • Prompt Engineering & "Vibe Coding" Workflow Consulting
  • AI-Augmented "Vibe Coding" & Rapid MVP Development
  • Figma to Shopify Liquid Theme Customization
  • Figma to WooCommerce Frontend Development
  • Figma to Magento 2 Theme Development

Copyright © 2026 · Vinay Vengala