Polylang 3.4 will soon be released and it comes with some technical changes. This new version is more focused on developers and we will discuss these changes here.
In this release we wanted to:
- Improve compatibility with php 8.2.
- Improve reliability of some core components,
- Prepare for more changes to come,
- Ease extensibility with third party plugins.
In fact, the changes in this release are the first step towards more improvements to come in the plugin’s architecture, but that’s a subject to discuss another day 😏.
PLL_Language
This is the class holding the data related to a language, and is the starting point of our improvements. Until now we had an object with properties set as soon as the instance is created, some were set later, and some other were generated dynamically on-the-fly. This was a bit difficult to work with properties that were maybe available, or maybe not. So we changed a few things to get a more “reliable” tool.
So what does it mean for you?
Some public properties related to language terms are deprecated
term_taxonomy_id
, count
, tl_term_id
, tl_term_taxonomy_id
, and tl_count
. Note that term_id
hasn’t changed.
Those properties are still available publicly but will trigger a deprecation warning when accessed directly. To retrieve these values, a new getter is available:
PLL_Language::get_tax_prop( $taxonomy, $field )
Where $taxonomy
is a taxonomy name like 'language'
and 'term_language'
, and $field
is the name of the field to retrieve: 'term_id'
, 'term_taxonomy_id'
, or 'count'
(those are the only 3 possible values).
Which gives us:
$language->term_taxonomy_id |
$language->get_tax_prop( 'language', 'term_taxonomy_id' ) |
$language->count |
$language->get_tax_prop( 'language', 'count' ) |
$language->tl_term_id |
$language->get_tax_prop( 'term_language', 'term_id' ) |
$language->tl_term_taxonomy_id |
$language->get_tax_prop( 'term_language', 'term_taxonomy_id' ) |
$language->tl_count |
$language->get_tax_prop( 'term_language', 'count' ) |
There is also another getter to retrieve values for all language taxonomies:
PLL_Language::get_tax_props( $field )
Example:
$ids = $language->get_tax_props( 'term_id' ); /** * [ * 'language' => 8, * 'term_language' => 10, * ] */
The $field
argument can be omitted to retrieve all the fields.
Some public properties related to URLs are deprecated
home_url
and search_url
.
Like the previous ones, those properties are still available publicly but will trigger a deprecation warning when accessed directly. To retrieve these values, 2 new getters are available:
PLL_Language::get_home_url() PLL_Language::get_search_url()
Some public properties are removed
$mo_id
: it was used to store the ID of the post containing the strings translations (they are stored elsewhere now).
Some public methods are removed
The following methods are removed without deprecation warnings:
PLL_Language::set_flag() PLL_Language::set_home_url() PLL_Language::set_url_scheme()
They were used internally to set properties that are now set during the class instantiation.
New public properties
$is_default
: handy to know if a language is the default one.
$active
: tells whether or not the language is active. The default value is true
. Note that deactivating languages is still a feature of Polylang Pro, this property is not used in Polylang.
$fallbacks
: list of fallback language locales. The default value is an empty array. Note that this also a feature of Polylang Pro, this property is not used in Polylang.
API functions
But let’s not forget that API functions are available:
pll_current_language() pll_default_language() pll_get_post_language() pll_get_term_language()
These functions have a $field = 'slug'
parameter and work like before. They can retrieve a field value without triggering a deprecation warning. However 'tl_term_id'
, 'tl_term_taxonomy_id'
, and 'tl_count'
should not be used. Instead, the parameter accepts a new notation: '{language_taxonomy_name}:{property_name}'
.
Example:
$tl_tt_id = pll_current_language( 'term_language:term_taxonomy_id' );
The languages list
A lot of things happened here. To put it simply, the list is considered incomplete if we try to retrieve it (with pll_languages_list()
) before the hook pll_pre_init
. If this function is called before this hook, Polylang will trigger a “doing it wrong” warning.
On pll_pre_init
, the languages are considered ready and the list is cached when called the first time.
PLL_Model
Some hooks are deprecated
With all the changes, the filters pll_after_languages_cache
and pll_languages_list
are not needed anymore, and are deprecated.
Note: if you used pll_after_languages_cache
to filter URLs, you may hook site_url
instead.
Get a language by its term_taxonomy_id
Not the big feature, but a small improvement that can be handy sometimes: PLL_Model::get_language()
can use a term_taxonomy_id
to retrieve a language.
However, there is a trick. This method can also use a term_id
, so to prevent a confusion between these two (they can be different), the value of the term_taxonomy_id
must be prefixed with tt:
. Example:
$lang = PLL()->model->get_language( 7 ); // term_id $lang = PLL()->model->get_language( 'tt:8' ); // term_taxonomy_id
Translate custom database tables is now easier
You didn’t know this was already possible? Well, it was, but a bit of a chaotic road because nothing was really prepared for it.
Since its version 0.1, Polylang is focused on translating posts and terms. Everything was built on this idea and these two types of content became the only ones to be translated (kind-of).
While working on PLL_Language
and PLL_Model
, we also had to work on PLL_Translated_Post
, PLL_Translated_Term
, and their parent classes. We had to work on their common behaviors and differences, and ended up working on generic ways to orchestrate all this.
So, how do we do now?
First, you need to create a class that will extend either PLL_Translatable_Object
or PLL_Translated_Object
. These classes give you tools to easily get and set a language to an item, manage translations, etc.
PLL_Translatable_Object
is meant for items that need a language assigned to, but don’t necessary need translations (meaning, a relation with other items in another language).PLL_Translated_Object
is probably what you’re looking for. It is meant for items that need a language and translations (PLL_Translated_Post
andPLL_Translated_Term
extend this class).
Another thing you may need here is the interface PLL_Translatable_Object_With_Types_Interface
and the trait PLL_Translatable_Object_With_Types_Trait
. You must use them if you want to manage types of your items. Example: post types for PLL_Translated_Post
, and taxonomies for PLL_Translated_Term
. By using them you can tell Polylang that some of your item types are translatable, and some are not.
Now that your class is ready, what to do with it? The answer is: register it in Polylang.
Let’s say your class is FooTranslatedItems
:
add_action( 'pll_model_init', 'foo_register_in_polylang' ); /** * Registers the database table in Polylang. * * @return void */ function foo_register_into_polylang( $model ) { $translatedItems = new FooTranslatedItems( $model ); $model->translatable_objects->register( $translatedItems ); );
And that’s it.
We created a new hook pll_model_init
for this purpose and it is triggered right before pll_pre_init
, so, right before the languages are considered complete.
Why registering a class?
By registering your class in Polylang you tell Polylang that your custom table exists and its content is translatable. Now Polylang will:
- Automatically create the terms for your language taxonomy if they don’t exist yet.
- Include your items when looking for untranslated objects (you know the admin notice in Polylang’ settings saying that some of the content is not translated yet) and allow the users to assign a language in bulk to all these items. This also works in Polylang’s wizard.
- Update the translations when a language slug has been modified in the settings or delete them when a language is removed.
Oh, and you will find your language term_id
, term_taxonomy_id
, and count
in PLL_Language::get_tax_prop()
.
Still confused?
OK, this may still be a bit confusing without seeing code, so we created a small example plugin for you to explore.
Your main focus should be on:
polylang-translated-table-example.php
: it will show you how to register your class.src/TranslatedEvents.php
: it will show you how to extend and usePLL_Translated_Object
.
Polylang won’t do everything automatically simply by creating this class and registering it, it is a process that has many aspects that can’t be done on our side, but it gives you a good starting point to make your custom table translatable in Polylang.
Conclusion
Polylang is currently putting some efforts into code improvements and we expect to continue in the following major versions. Some parts must be cut down at some point, but of course we try to keep backward compatibility as much as possible.
You can test the beta version of Polylang 3.4 as of today. The beta version of Polylang Pro can be downloaded from your account. You can also download the beta version of Polylang for WooCommerce 1.8 there. It is necessary to avoid deprecation warnings with Polylang 3.4 . Bug reports are welcome on GitHub.
Picture illustrating the article by Lorenzo Cafaro and licensed under the Pixabay license.