WordPress plugin internationalization: variables not translated?

I have a wordpress plugin with some settings stored in an array with a slug and a label for each setting.

My plugin is class based, and this is the code of my construct function

Read More
class My_Plugin {
  function __construct() {
    $this->_options = array(
        'optionA' => __( 'Text for first option', 'my-plugin' ),
        'optionB' => __( 'Text for second option', 'my-plugin' ),
        'optionC' => __( 'Text for third option', 'my-plugin' ),
    );
  }
}

I use a similar structure in few places, to store a list of values associated with a label with get text. For example, later on, this array could be used to create a form with user settings

foreach ($this->_options as $option_name => $option_label) {
    echo '<input type="text" name="' . $option_name .  '" value="' . $option_label . '"/>';
}

I use a similar structure elsewhere as well.
Now, the strange (?) thing I noticed is that when I translate the plugin using PoEdit, these strings are not translated.
Why does that happen? Is there anything I could do, aside from changing the structure and directly write each input field, or repetitive structure?

Related posts

Leave a Reply

1 comment

  1. You need to understand how gettext libraries (including the one in WordPress) work — once you do, the cause of issues like this is easy to reason about:

    __() is not some magic marker, but a plain old function. It takes a string as its input, searches the currently loaded MO file for the domain, if there’s any, and returns a translation if it finds one. Otherwise it returns the input unmodified (i.e. falling back to English).

    So the question you need to ask yourself, with the knowledge of the rest of your code that you didn’t include here, is: Was the translation for the my-plugin domain loaded at the time when __() was called from the constructors?

    A reasonable guess is that no, it was not. You first constructed the My_Plugin object, thus calling __() when no translations were loaded and the gettext library wasn’t yet properly initialized. In such situation, the only thing the function can do is return the original English string. At some point later (chronologically, not necessarily in source code order) your gettext initialization hook was executed and called load_plugin_textdomain. From that point on, __() would behave as expected. That was too late for your constructor, though, because you already “translated” these strings.

    It’s perfectly fine to store translated values as you do (although it’s also a bit pointless, because it doesn’t give you any meaningful performance benefits). But you need to rigorously follow a simple rule: Load translations first, then use them.