Plugin: Polylang
There is also a free, easy to use, and very light-weight plugin called Polylang. Migration from WPML to Polylang should be painless with dedicated plugin WPML to Polylang by PolyLang creators.
Polylang Pro is required for ACF Pro compatibility, as stated in official document. They also recommend to use third-party plugin to translate ACF options: ACF Options For Polylang
Not sure if Pro is really required as some users are stating that “ACF works great with Polylang and everything works out of the box as expected. No dirty hacks are needed, except for “options” page.”
For CF7, if you don´t want to create a form for each language, you can use one single CF7 form for all languages using plugin Multilingual Contact Form 7 with Polylang
For “String Translation” Polylang officially recommends utilizing any PO/MO tools: How to translate the themes and plugins hardcoded strings?. More precisely, they now provide a resource that explains Loco Translate as the ideal complement to Polylang. BEA – Fix Loco Translate
In addition, there is a solution that I personally employ, which is a WP plugin: Theme and plugin translation for Polylang (TTfP) that accomplishes precisely what I require and works marvelously.
Using Polylang without paying for Pro
If you need proper WooCommerce, I guess you must buy that module, but for everything else, free is sufficient.
Main differences Pro vs Free:
- Important: Translations can share the same slug
- Important: Translate slugs in URLS (custom post types, taxonomies and more…)
- Good to have: Duplicate posts across languages
- Good to have: Additional integration with ACF Pro, meaning ACF Options fields
Every difference is solved with free plugins:
Translations can share the same slug in the URL
When we say “same slug” we mean that /wizard
, /nl/wizard
and /de/wizard
are the same.
This is the main reason to buy Pro, as explained here
It is properly solved with plugin grappler/polylang-slug, which is not actively developed. An alternative plugin that should also work is lufton/polylang-share-slug, which has not been updated for quite some time. The official Polylang Pro also references the polylang-slug
project in its source code.
Bad news it that on this plugin that works, in repository states: “This plugin is not being actively developed”
Duplicate posts across languages
Not sure this is essential functionality, but it is useful. It means that when we create a new translation, the whole post content, title and attachments are copied.
Based on reviews, this one is quite active and tested: Polylang Duplicate Content, but as usual, we have a viable alternative: aucor/polylang-copy-content
Also not sure about the following problem, that probably arises when cloning post using some specialized plugins: mindtwo/post-duplicator-polylang
Rewriting slugs aka translate slugs in post types
Based on this article on Translating URLS slugs from 2015, I believe this option was free before but now it is not.
There are too many plugins to enable rewriting slugs, but I’ve discovered that this one is only maintained and works: webnucleo/wp-polylang-translate-rewrite-slugs
The one on the plugin repository is real exploding bomb with bad code: WP Slug Post Type Custom Language (Polylang) | carlosramosweb/wp-slug-post-type-custom-language.
There is also this code snippet that might work as well: stouch/wp-plugin-polylang-localized-taxonomy-slug and I think this for similar purpose extracted from Pro: rizkiaprita/polylang-pro
REST API Support
Is probably solved with maru3l/wp-rest-polylang
Additional integration with ACF Pro
Is perfectly resolved with “Options” plugin: ACF Options For Polylang | BeAPI/acf-options-for-polylang
Amazing additions to the plugin
Essential
-
Theme and plugin translation for Polylang (TTfP) or Loco Translate as I thing we can achieve the same with them both
-
Simple Polylang cookie removal that just removes cookie Polylang is using: J0ANMM/wp-polylang-cookies-custom-plugin
Very Good
- Polylang – Country Detection
- WPML to Polylang
- Contact Form 7 Polylang Module or Multilingual Contact Form 7 with Polylang or https://github.com/aurovrata/cf7-polylang
Interesting
-
ACF: https://github.com/mcguffin/polylang-sync not sure what is this: https://github.com/the-best-is-best/tbib-polylang-acf
-
Media: https://github.com/aucor/polylang-translate-existing-media
-
PO and MO files: https://github.com/andriilive/polylang-export-importable-mo-po
-
Make Polylang’s post language select field disabled when the post has translations aucor/polylang-smart-language-select-disabler Basically the translations are unlinked and there is no warning for this.
How to remove the Polylang plugin
Quite nice and possible.
Polylang and WP-CLI
Polylang stores language information as a taxonomy ‘language’ for posts and ‘term_language’ for terms.
In WP-CLI we can use https://github.com/diggy/polylang-cli, but without it, we can use:
To list languages:
wp term list language
List English pages
wp post list --post_type=page --lang=en
or:
wp post list --post_type=page --lang=nl --fields=ID,post_title
Using SQL to modify Polylang data
Source: Search and replace query with multilanguage site (polylang)
List all English pages
|
|
Do a basic search-replace on one language, for example nl
for Dutch
|
|
In above query, I’m actually replacing one Gutenberg Reusable Block with another for specific language.
Translation of Reusable Blocks
The problem exists both on WPML and on Polylang and most of the other translation plugins for WordPress.
It sometimes worked, but just by luck
Currently, reusable blocks can’t be translated, as they are stored on pages by their ID.
Manifestation and temporary solution
In any language some page is displayed, the reusable block is presented in the original language used when that block was inserted into that page.
I’ve used a temporary fix that is not bulletproof, but it worked for some time. The idea is to check during page rendering if a reusable block present on the page has translation available and if it has it, to use that translation instead of the original reusable block.
Read more about this idea on Polylang support thread: https://wordpress.org/support/topic/reusable-block-translations/
Proper permanent solution
The only proper solution is to fully ignore “language” info on reusable blocks as that is obviously not working. Then on every page translation insert the block that you need in that exact language, without expecting automatic language switching on reusable blocks.
To ease this process, it is best to include language abbreviations in block titles (EN, DE, etc) so that when using them on pages, to distinguish them easily.
Polylang Language Cookie
I’m assuming that
URL modifications > Hide URL language information for default language
option is set and active
Polylang uses a cookie to remember the language selected by the user when he comes back to visit again the website. This cookie is also used to get the language information when not available in another way. Examples are AJAX requests (quite important) or the login page (less important).
About Polylang Cookie and EU cookie law
Polylang plugin is setting a cookie for language preference using the ˙set-cookie` header from PHP.
Disabling cookie using PLL_COOKIE
Polylang works just fine without the cookie, if you have turned on “URL modifications > The language is set from the directory name in pretty permalinks”. In this case, it is safe to disable the cookie by using define('PLL_COOKIE', false);
There are more Polylang options that could be set in wp-config.php
It is possible to modify cookie expiration using pll_cookie_expiration
hook. For example, if you prefer a cookie expiring at the end of the session, add this: add_filter( 'pll_cookie_expiration', function() { return 0; } );
;
more info here
Polylang Language Auto-detection
Nginx Cache and Polylang have a problem, a huge one. Let’s try to explain a problem.
When the Polylang setting Detect browser language: When the front page is visited, set the language according to the browser preference
is checked, then the first visitor that comes along will get redirected to his/her language correctly, but … that redirect response will be cached by Nginx! Now subsequent visitors with different browser languages will get served the same cached response, and they will be redirected to the wrong language.
That’s why we have a problem with static caching. On the server side, it can be solved by updating the proxy_cache_key
directive to include pll_language
cookie as mentioned in this support thread
Raidboxes.io uses a Nginx web server to cache pages. There is a known issue that Polylang language detection has with caching on the server. It is described more in the following support comment - Nginx fastcgi_cache and Polylang homepage redirects and another article
… and another article from WP Rocket Knowledge Base
Possibilities in solving the homepage cache problem
- One solution could be NOT to cache the homepage, but as our server is quite slow, we must avoid this. There is also no way to bust cache only the homepage on Raidboxes.io. For regular PHP-based caching plugins, Polylang is exactly using this cache-busting technique, as seen in the code here polylang/cache-compat.php](https://github.com/polylang/polylang/blob/master/integrations/cache/cache-compat.php)
Polylang can’t turn off the cache on the homepage, as the cache resides later in the response chain, on Nginx server and not on the PHP plugin level.
-
Turn off language detection and turn off cookies, so user will never redirect. This is a viable solution, but in our case with 90% of users from non-default language, we shouldn’t use this one
-
Write custom auto-detection and redirection code, based not on server PHP but on client-side JavaScript. This is the best way to go.
Final approach
- Don’t use
Detect browser language
option as it won’t work. It detects language using PHP$_SERVER['HTTP_ACCEPT_LANGUAGE']
and as such has a problem with server caching - Leave
PLL_COOKIE
as it doesn’t influence anything else, and we won’t use it anyway - Use custom JavaScript code for language detection and store selection inside a custom cookie
Ideas on JavaScript implementation
Interesting JavaScript implementations found: inside this support thread and this one
Redirection is done only on the home page and only on the default language, URL without language suffix.
Verify functionality
- Test language detection — in new incognito mode (so that there are no cookies set), navigate to cnc24.com, and you’ll be redirected to your browser language, probably German
- Test last used language — in normal mode, switch using language switcher to a different language. After that, open a new tab and navigate to cnc24.com. You should be redirected to that selected language.
ACF Options in Polylang
BeAPI/acf-options-for-polylang: A WordPress plugin for adding ACF options page support for Polylang.
Options page + polylang - ACF Support Usage of get_fields(‘options’) · Issue #62 · BeAPI/acf-options-for-polylang
The plugin is designed to get the Polylang “All languages” value if the current lang one is empty. You can easily disable that to avoid confusion.
I purchased the Polylang Block Language plugin, but I have a problem with it that is becoming increasingly annoying.
Hello Jakub,
I am contacting you because I am a paid user of your plugin “Polylang block language”. Everything is working as expected, but I am not satisfied with one detail that I assume is not difficult to implement.
Namely, the plugin inserts a lot of “extra code” into the HTML code produced by the editor.
For example:
- Some text
- Pro: Manage navigation blocks translations in the site editor (requires WP 6.3)
- Pro: Manage pages translations in the site editor (requires WP 6.3)
- Pro: Manage patterns translations in the site editor
-
Polylang Duplicate Content Addon je inače opcija koja postoji u Pro verziji
It would be desirable for the “pllVisibility” to not pollute the HTML code at all if it has no value. Currently, I am using the plugin on only a few pages on the entire website. However, due to this “bug”, “pllVisibility” is written in almost every block on every page.
Thank you in advance.
Best regards, Vladan
It might be worth considering replacing it with a plugin like Wicked Block Conditions or a similar one that supports conditions based on the result of a custom PHP function. Other than that, Wicked Block Conditions is a completely free plugin with no restrictions whatsoever.
Permalink Manager Lite već u free verziji ima opciju to Translate permalinks and in Polylang plugins installed on your website, Permalink Manager allows you to translate the slug and specify different permalink format/structure for each language.
Text Domain Inspector is interesting plugin that simplifies the process of finding and discovering text domains for translatable strings. After activating the plugin via the Inspect Text Domains
button in the Admin bar, translatable strings are marked with red dots and hovering over these dots reveals element text domain.
Add Polylang support for Customizer
Ideja koja bi mi rešila problem sa polylang langage auto detekcijom, valjda:
Country Caching For WP Super Cache nije baš mantained ali radi, a ima i za ostale cshing pozginove.
Inače, kada ideš preko CloudFlare, imaš i country information koja je stalno ažurna i savršena, Configuring IP geolocation · Cloudflare Support docs, a to onda mogu bilo gde da koristim pa i u PolyLang mom JS skriptu, na primer.
Polylang i The SEO Framework kao i pominjanje Browser language redirect, i zašto to isključiti. Translation plugin compatibility • The SEO Framework · KB
3.5 (2023-10-09)
Some plugins for Polylang:
First and foremost, Polylang automatically incorporates hreflang HTML tag attributes on your multilingual site, eliminating the need for manual intervention - refer to Hreflang tag attributes and Polylang for comprehensive information. Therefore, plugins like Hreflang for Polylang are unnecessary - I noticed that plugin SVN repository is completely empty.