As you may have heard, Advanced Custom Fields 5.7 is now available in beta. This new version is packed with long-awaited features that will both improve your workflow and ACF’s performance. Today, we wanted to introduce you to an improvement that aims to do a little bit of both.
First, some background information. Version 5.7 sports a completely-rewritten JavaScript architecture that brings with it vastly improved ways to interact with fields. One of the biggest advantages with this new framework is a major expansion of ACF’s conditional logic capabilities.
These JavaScript improvements have opened up new opportunities for ACF, but also some rather unique challenges. One of the most important was how to best provide translations (handled in PHP) in our JavaScript environment.
The good news is that we have found a solution that will bring both efficiency and ease to the entire process – and we want to share it with you!
Before we get into the nitty-gritty of how ACF 5.7 improves localization and internationalization, let’s take a brief look at what these processes are:
The process of internationalization (abbreviated as i18n) prepares a WordPress plugin or theme to be translated into different languages. WP makes this super easy with PHP functions such as __()
used to both return translated text and generate .pot files.
Localization (abbreviated as l10n) is the process of actually translating a theme or plugin into a different language. When working with Javascript, this involves printing PHP translations into a Javascript Object via inline scripts.
These two processes work in tandem, yet they each serve a specific function. Localization (l10n) passes PHP data to JavaScript, while internationalization (i18n) uses l10n to pass PHP translate strings to JavaScript.
The problem we faced in ACF 5.7 was that our existing l10n processes did not encourage a fast and efficient working environment.
Previously, translations were passed from PHP to JS through an inline script object that looked something like this:
acf.l10n = {
uploadedTo: "Uploaded to this post"
// ...
};
From there, we would use this data like so:
var html = '<span class="acf-uploadedTo">' + acf.l10n.uploadedTo + '</span>';
This is all pretty basic stuff, and while this approach worked, there were some serious drawbacks:
acf.l10n.uploadedTo
didn’t exist, there was no fallback or default string.As we further developed the new conditional logic goodness in ACF 5.7, it became clear that the issues above needed to change. So, we went to work 💪😀
Starting in ACF v5.7, we have implemented a fully-revamped way to localize our plugin. Let’s take a look under the hood to see how it all works. We’ll take it issue-by-issue:
Solving the timing issue was quite simple. Instead of printing the acf.l10n
data down in the footer, we made use of the WP recommended wp_localize_script() function to pass translation data from PHP to JS.
This function also creates an inline script. However, it is printed right before the main ACF JS file is included and passes the PHP data to a global JS variable called acfL10n
.
Not knowing the exact string caused a lot of frustration when writing in Javascript. We’re happy to say that this process has been greatly improved!
Along with the new variable name, we also changed the way this variable looks. Which is something like this:
var acfL10n = {
"Uploaded to this post": "Uploaded to this post"
// ...
};
😳 The avid viewer may notice that the above object looks quite redundant as both the key and value are the same. Don’t fear, we have this covered later on!
And, to help make it easy to register strings for translation, we created the function acf_localize_text( $strings )
. It can be used like so:
acf_localize_text(array(
"Uploaded to this post" => __("Uploaded to this post", 'acf'),
// ...
));
Adding reliability to our translations is a great by-product from the above changes. With our new system in place to register localized text, we can now interact with the data through a function like so:
var html = '<span class="acf-uploadedTo">' + acf.__("Uploaded to this post") + '</span>';
This allows the JS to read just like PHP, while also providing a fallback if the translation doesn’t exist.
Remember how our acfL10n
object had the same key and value? Super wasteful, right!
The solution to this is simple. All we do is loop over the registered strings and compare the array key to the array value. If they are the same, then we can safely assume that no translation exists for this string and it therefore doesn’t need to be printed to ‘acfL10n’.
Only translated strings (ones that have changed via the PHP __()
function) will be registered. This means that when using ACF in an English language, the ‘acfL10n’ is completely empty. This a major efficiency win 🔥
Providing context for translations is extremely important. We had a look at how WP’s _x()
function worked and implemented a similar approach. Simply put, we now also have a JS acf._x()
function too!
We also added another function called, acf_localize_data( $data )
, to do a similar job. This helps to separate the data away from translations.
Both i18n and l10n are areas where we want to continually improve. It’s an important part of making ACF more user-friendly on a worldwide basis.
We’re also very excited to share all of the new features that have been developed for ACF 5.7. If you’re interested in beta testing, we’d love your feedback!