1

My theme has a lot of templates. Most of them contain messages in the usual way:

echo __('This is the message','mytextdomain')

This has several disadvantages. For instance, if I want to change the Read More message I have to browse all files to see if it is there. There's a larger risk of typos and it is more difficult to check for consistency in the messages. So, is there a way to concentrate messages in one place?

Also I wonder about performance. For every page load WP loads the complete textdomain, only to find a translation that is always the same. Especially on the front end this doesn't sound efficient. So, is there a way to have proper localization without repeating the process all the time?

1
  • For anyone ending up here searching for info on how to organize the textdomain: also read this
    – cjbj
    Oct 6, 2016 at 7:40

2 Answers 2

2

In my opinion you are focusing on a wrong issue in this case.

For instance, if I want to change the Read More message I have to browse all files to see if it is there.

This doesn't indicate localization problem. This indicates templating problem.

What if you want to change markup of Read More of whatever else? Do you have to do this in multiple places as well? Then it's more about how templates are structured and duplication in them.

Not that WordPress is particularly good at that, but still worth a consideration.

Also I wonder about performance. For every page load WP loads the complete textdomain, only to find a translation that is always the same. Especially on the front end this doesn't sound efficient.

You make a typical mistake of wondering instead of measuring.

There are certainly performance implications to localization in WordPress. However core already does plenty of it to load localization for itself.

If your theme doesn't approach or exceed WP core in size of necessary translations then you are probably fine. If you want to be sure — profile performance and get sure. :) Wondering just wastes your time on hypotheticals that might not need to be addressed.

2
  • Thank you for your thoughts. Templating Problem Point taken. You could prevent duplicates by breaking things up and glueing them together with get_template_part. But that does not help keeping track of the overall state of messages. Performance It always starts with wondering. Then I did the measuring. For the backend my approach is senseless. On the frontend there is a difference, though not too much. Personally the most important reason to follow this approach for me is I can change the messages on the options page and update the framework without losing customized messages.
    – cjbj
    May 19, 2016 at 18:30
  • Well, I measured and performance is an issue. Loading WooCommerce language files takes over 30ms in our case, all language files from all plugins take over 50ms. This is in production, PHP 7.4, cache, SSDs, a lot of RAM, fairly fast CPUs, and whatnot.
    – matt
    Jun 7, 2021 at 17:23
-1

There is an easy way to get around this problem. Store all frontend messages as options of your theme. Let's define an option 'messages':

add_option('messages',array());

Now we must populate this option. Let's define the defaults:

$theme_messages_defaults = array (
    'read-more'         => __('Read more','tekko'),
    'next-page'         => __('Next page','tekko'),
    ... and so on ...
    )

Now, we have to transfer the defaults to the option. We want to do this only at first install, when the translation files have been updated or when the user switches languages. When this test passes run this function:

function run_only_at_install_or_new_version {
    global $theme_messages_defaults;
    var $messages = array();
    foreach ($theme_messages_defaults as $message_key => $message_val) {
        $messages[$message_key] = $theme_messages_defaults[$message_val];
    }
    update_option('messages',$messages);
}

Given that the option is an array, we need a slightly different get_option function:

function mytheme_get_message_option ($message_key) {
    $messages = get_option('messages');
    $message = $messages[$message_key];
    return $message;
}

In your templates replace all your echo statements like this:

mytheme_get_message_option('read-more');

Don't forget you won't need the textdomain on the frontend anymore, so add a condition in your function file:

if (is_admin()) load_theme_textdomain ('mytheme', 'path/to/languages');

Now you have all your messages in one place and are preventing unnecessary translation actions. Actually you have even more possibilities. You can add the messages to your option pages and have your clients change the texts without having to change templates. Hey, if you use mods in stead of options, you can even add them to the theme customizer. Beware that you would have to add an extra condition to run_only_at_install_or_new_version to prevent overriding client messages when the theme is updated.

Note: The above is adapted from a more complex setup I use myself, so there may be some typos. If you're at this stage debugging it shouldn't be a problem.

10
  • I don't see why anyone should bother with this, but this just doesn't scale and doesn't work with multiple languages. And as always avoiding established wp conventions means that the code is harder to understand for anyone else. May 19, 2016 at 10:53
  • @Mark. Let me assure you that it has been tested with multiple languages. It does not circumvent wp conventions, just moves the place in the Theme where the localization occurs.
    – cjbj
    May 19, 2016 at 10:58
  • If it works it means that you havn't tested it good enough. try different langs on admin and frontend. Anyway, that is the solvable problem, the fact that it is not scaling solution with performance hit against every page load can not be solved in any way. May 19, 2016 at 11:03
  • As far as I can see I'm replacing loading a full textdomain with reading a variable. What would be the performance hit?
    – cjbj
    May 19, 2016 at 11:16
  • 1
    The way wordpress handles translations is wrong. The problem is that there is one place which holds all of the translation strings and bloats the memory (this is why core now has 3 different translation files for different contexts - too many out of memory errors due to the list of cities for setting the base time). The right solution is to have different domain per different page, or at least different context, but for small translation sets it just do not worth the effort. Your solution just shifts the core problem from one place to another. May 19, 2016 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.