In the docs for the translate function __( $text, $domain )
, it states that you must put the string directly in place of $text, that you cannot do something clever such as __( $my_text, 'text-domain' );
.
However, I am writing a method which takes in a string and needs to pass it to __(
… )
somehow. Is there a way, e.g. via printf
or sprintf
that I can work around this?
Something like…
function print_description( $text ) {
echo '<p>' . __( printf( '%s', $text ), 'text-domain' ) . '</p>';
}
You can do it with
printf()
.E.g.
To translate a string in WordPress, as in most CMSs that use PHP, you have to wrap the string in a GetText translation function (i.e. __ (), _e (), _n (), _x () … etc).
The string has also to be included in a PO file (GetText Portable Object files, the industry standard for multilingual websites in PHP – https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html). This file includes pairs of strings, one of them is the string in the original language and the other is its translation in the target language.
In order to build these PO files for every language (i.e. my-text-domain-es_ES.po for Spanish, my-text-domain-fr_FR.po for French … etc.) in which we need to translate the plugin or theme, the translator will use a POT file (PO template) that contains all the strings to translate in the original language and will add a translated string for every one of them. PO files are compiled to binary MO files, that can be processed much faster.
At run-time, the strings to translate are fetched through the MO files and replaced by its translation.
The POT files are usually generated using special tools that parse the source code files and extract the translatable strings.
If we write code like this:
When the code is parsed by the special tools, the value of the string to be translated ($text) is not yet defined and therefore is not present in the code. As a result, the automatic search tools will not include this string in the POT file and therefore will not be included in PO nor MO files.
At run time, when the value of the string $text presumably will be already defined, there will be no correspondence for this value in the translation files and the translation will not be possible.
However, if the set of possible values for that variable is limited and we know them, we have two options to overcome this problem:
Option 1: Manually edit the POT file to add the entries with the possible values of $text. This option is simple and easy to implement. Any code editor and minimal knowledge of the POT format will be enough. But it has one drawback. Every time we use the automatic search tools to update the translations after modifying our code, the modifications that we have made would be lost and we would have to include them manually again.
Option 2: include in our code all the possible values of $text wraped by translation functions. Let’s see an example. Suppose that $text can take the values: apple, orange, banana, peach and pear. We would need to write the following code:
This option is also easy to implement and has the advantage that it will not be lost when we use the automatic search tools to update the translations.
If we have, in our theme or plugin, several variables that we want to be translated and they have a limited set of known possible values, we could include all of them in a separated file that has to be in the root folder or a subfolder (i.e. ‘includes’ or ‘assets’ folder) of the theme or plugin as is shown below:
This is a clean and maintainable approach that keeps the definition of these strings in a separate file that can be modified without affecting other code files.
No
The tools that help in generating a translation can not parse your code and decide what are the strings that need translation when the strings passed to the translation routines are totally dynamic.
in your example the proper way to code this function is
and call it
No, because one cannot translate text when you don’t actually know what that text is.
Translation works via, essentially, a big array. You take your code, find all the strings in it, then build a big list of strings. A translator translates them into another language. Then the various translations functions do a big array lookup and return the translated string.
If you use a variable to hold the text string, then there’s no way to know what it is in advance and put it in the initial list of strings to be translated.
Variables cannot be used in translation functions, because that doesn’t actually make any sense. You cannot translate a variable.
For some reason, for me it does works to pass variables to _e():
Obviously, you must create your textdomain before, ideally in yourtheme/functions.php:
If I translate the word ‘ciao’ on the .po file, it will be correctly translated in frontend. Use Poedit or the like to compile the .mo. Both .po and .mo must placed in /wp-content/yourtheme/languages (accordingly to the code above).
Not sure the reason why it works, but it does, it will output ‘ciao’ in italian and ‘hello’ in english.
As I mention here http://www.westofwonder.com/2013/12/whats-with-all-the-double-underscores-everywhere/ (please pardon the theme, I’ve made improvements, just haven’t pushed them yet), one possible solution to this is to create a function for the text:
Ugly in and of itself, but for a long or frequently used translation string, the trade-off may be worth it for code readability.
(Is this allowed? To link to my blog in direct answer to a question? If not, I apologize and won’t do it again. )