Working with multilingual content can be demanding, especially when using different domains for the languages, since it may require you to be logged in for every domain.

The problem(s)

There can be multiple problems why it makes sense to make sure that you’re logged in for every language you’re managing, but also why it’s impossible:

  1. A server-side page cache caches existing content for guests.
  2. A caching plugin caches existing content for guests.
  3. There is different content for logged-in users and guests.
  4. A login is not possible for every domain due to certain restrictions (e.g. having a single sign-on that only works on a single domain).

Since Polylang allows you to use different (sub-)domains for each language, you can run into one or many of these issues. That was also the case for me, as it was a combination of a server-side cache for guests and not being able to login on each domain.

My solution

I noticed that you can visit a translated page from any domain in Polylang by adding a URL parameter with the language of any translation. This way, I can access the German version of the start page via https://www.example.com/?lang=de and the French one via https://www.example.com/?lang=fr.

I then use this method to add this URL parameter to any permalink URL in the admin (since in the frontend, I want to keep the links as they are), but only if the system is set to use different domains.

/**
 * Replace permalink with the current domain and add language parameter.
 * 
 * @param	string			$link Link to replace
 * @param	int|\WP_Post	$post Post ID or post object
 * @return	string Updated link
 */
public static function replace_permalink( string $link, int|\WP_Post $post ): string {
	if ( \is_int( $post ) ) {
		$post = \get_post( $post );
	}
	
	if ( ! $post instanceof \WP_Post ) {
		return $link;
	}
	
	$language = \pll_get_post_language( $post->ID, 'slug' );
	
	if ( empty( $language ) ) {
		return $link;
	}
	
	$current_domain = \wp_parse_url( \home_url(), \PHP_URL_HOST );
	$link_domain = \wp_parse_url( $link, \PHP_URL_HOST );
	
	if ( \is_string( $link_domain ) && \is_string( $current_domain ) && $link_domain !== $current_domain ) {
		$link = \str_replace( $link_domain, $current_domain, $link );
	}
	
	return \add_query_arg(
		[
			'lang' => $language,
		],
		$link
	);
}

$polylang_options = (array) \get_option( 'polylang' );

// 3 equals the setting for domains
if (
	\is_admin()
	&& isset( $polylang_options['force_lang'] )
	// 3 equals the setting for domains
	&& $polylang_options['force_lang'] === 3
) {
	\add_filter( 'attachment_link', 'replace_permalink', 10, 2 );
	\add_filter( 'page_link', 'replace_permalink', 10, 2 );
	\add_filter( 'post_link', 'replace_permalink', 10, 2 );
	\add_filter( 'post_type_link', 'replace_permalink', 10, 2 );
}
Code language: PHP (php)

There is one drawback, however: Only the actual post content is displayed in the language given via URL parameter. Things like navigation menus stay in the language of the domain you’ve used to access the page. In the example above, giving that the primary language is English, the menu will still be the English menu, even if the content is German or French.

Reposts

Leave a Reply

Your email address will not be published. Required fields are marked *

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Learn more about webmentions)