Creating a Multilingual Page with ACF

<h3 class="entry-title">Creating a Multilingual Page with ACF</h3>
Posted on



 

In a previous post, I outlined how to register short-codes for  the ACF repeaterfield.  The following code example is built upon that.

 

Multilingual Fields created with ACF Repeater.

 

/**
 *  Hook into filter for custom 'Translations' ACF Repeater Field and register to create a custom shortcode 
 *  that can be used in the WYSIWYG editor of the same page
 *  
 *  https://www.advancedcustomfields.com/resources/acf-format_value/
 * 
 */
function prepare_translation_shortcodes( $field ) {
	// echo '<pre>' . var_export($field, true) . '</pre>';

        // Row Index in Admin Dashboard starts at 1
	$translation_index = 1;
	foreach( $field as $f) {
		$name = 'translation_' . $translation_index; 
		$translation_index = $translation_index + 1; 
		add_shortcode($name, function() use ( $name, $f ) {
			$keys = array_keys($f);
			$EN = $f[$keys{0}] ;
			$ES = $f[$keys{1}] ;  
			return '<div class="row translated-cols">' .
				'<div  id="en" lang="en" class="col hideable">' . $EN . '</div>' .
				'<div  id="es" lang="es" class="col hideable">' . $ES . '</div>' .
				'</div>';
		});
	}
    return $field;
}
add_filter('acf/format_value/name=translations', 'prepare_translation_shortcodes'
window.onload = function () {
   
   document.querySelectorAll('a[lang="en"]').forEach(function(el){
        el.addEventListener("click", showhide.bind(this, 'en'), false);
    })

    document.querySelectorAll('a[lang="es"]').forEach(function(el){
        el.addEventListener("click", showhide.bind(this, 'es'), false);
    })

    var showhide =  function showhide(id) {
        if (document.getElementById) {
            var divid = document.getElementById(id);
            var divs = document.getElementsByClassName("hideable");
            for (var i = 0; i < divs.length; i = i + 1) {
                $(divs[i]).fadeOut("slow");
            }
            $(divid).fadeIn("slow");
        }
        return false;
    }
    $('.hideable').hide();
    showhide('en');
}
<article id="post-<?php the_ID(); ?>" ?>
    <header class="entry-header">
		<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
	</header><!-- .entry-header -->

    <section>
        <span>
            <a lang="en" href="javascript:void(0);" >
                <span class="flag-icon flag-icon-us"></span>English
            </a>    
            <a lang="es" href="javascript:void(0);" >
                <span class="flag-icon flag-icon-ec"></span>Español</a>
        </span>
    </section>
    
    <div class="entry-content">
        <?php do_shortcode(the_content());?>
    </div><!-- .entry-content -->

</article><!-- #post-<?php the_ID(); ?> -->

 

Thoughts

I'm unsure to weather or not it is considered bad practice to have translated content on thee same page. However, it does allow for easy entry into from the Admin Dashboard. Furthermore,  I was able to mark the language of the content on the parent div  by adding something the lang attribute, along the lines of `<div lang='es> ... </div<>` so at the minimum there is an indication to Google's bots. Only time will tell.

 

Result

 

The final result in action.

 

Other Considerations

  • Multilingual SEO - HREFLANG
    • This has something to do with serving specific content to users based on their browser language and/or location.
    • Seems hard to test if set up correctly
  • Don't hard code the language values and extend the amount of language sections that can be created
  • Allow customization of Flags for language links

Dependencies

  • jQuery (for the animation effect)
  • Either the function get_field() or get_field_objects()  needs to be invoked in order for the short codes to be registered.