Mangling strings for fun and profit

As a WordPress lead developer, every time I see someone recommending editing a core WordPress file, a little bit of me dies.

You should always avoid editing the core files and put your modifications into a plugin so as to ensure you have a smooth upgrade experience to a future WordPress version.

Therefore inspired by the following forum post here is how to change one of the translatable strings in WordPress without hacking a core file using the filters available in the translation functions:

<?php
/*
 Plugin Name: PJW Translation Mangler
 Plugin URI: http://blog.ftwr.co.uk/#
 Description: Example of how to mangle translated strings.
 Author: Peter Westwood
 Version: 0.01
 Author URI: http://blog.ftwr.co.uk/
 */

class PJW_Translation_Mangler {
 /**
 * Filter the translation string before it is displayed.
 *
 * @param $translation The current translation
 * @param $text The text being translated
 * @param $context The context for the translation
 * @param $domain The domain for the translation
 * @return string The translated / filtered text.
 */
 function filter_gettext($translation, $text, $domain) {
  $translations = &get_translations_for_domain( $domain );
  if ( $text == 'View all posts filed under %s' ) {
   return $translations->translate( 'See all articles filed under %s' );
  }
  return $translation;
 }
}
add_filter('gettext', array('PJW_Translation_Mangler', 'filter_gettext'), 10, 4);
?>

The filter used in this example gettext is one of a set of filters in the translation functions in wp-includes/l10n.php which also include gettext_with_context, ngettext, and ngettext_with_context.

15 thoughts on “Mangling strings for fun and profit

    1. Force of habit, more than anything.

      I like to do it that way so as to keep everything namespaced and not take top level function names.

      I only use top level function names, in plugins, as wrappers when providing template tags.

  1. Hadn’t thought of using that gettext filter. There’s a filter in wp-super-cache that allows you to filter the contents of the page that is about to be cached. I wrote a small function that deletes the moderation message for comments as a small exercise because the string isn’t filterable, or so I thought!

    This way is much neater. Thanks!

  2. Really great tip 🙂

    Is it possible to use this function to re-name admin menu items when activating a theme?

    For example, if I wanted to change “Posts” to “News”?

    Or the “Appearance” tab back to “Themes” maybe?

    I’d love to be able to do total admin menu overhauls using theme functions rather than plugins.

      1. Currently I do something like:


        global $menu, $submenu, $wp_taxonomies;

        // Unset Post & Page menus so we can change them
        unset($menu[5]);
        unset($menu[10]);
        unset($menu[20]);

        // Change menu order to reflect new positions
        //New Pages
        $menu[5] = array(__('Pages'), 'edit_pages', 'edit-pages.php', '', 'wp-menu-open menu-top', 'menu-pages', 'div');
        $submenu['edit-pages.php'][5] = array(__('Edit'), 'edit_pages', 'edit-pages.php');
        $submenu['edit-pages.php'][10] = array(_c('Add New|page'), 'edit_pages', 'page-new.php');

        //New Posts (News)
        $menu[10] = array(__('News'), 'edit_posts', 'edit.php', '', 'menu-top', 'menu-posts', 'div');
        $submenu['edit.php'][5] = array(__('Edit'), 'edit_posts', 'edit.php');
        .... etc

        Which allows me to move menu items (Media between Pages and Posts always annoys me) and rename them, in this case Posts to News.

        Is this possible using the translation function?

  3. Pingback: Around the WordPress Community: WPMU Merger, Widgets, Custom Fields, Shortcodes | WordCast - Blogging news, WordPress help, WordPress plugins, WordPress themes, WordPress news

  4. mercime

    Thank you very much Westi. I was referred to this solution by DJPaul at BuddyPress Forums when I wanted to find a simpler and easier to override text output from BP parent theme’s template function. From 45 lines of code to replace a single sentence in child theme’s functions.php to 10 lines of code in same functions.php – Awesome!

  5. Your code is somewhat inefficient. The get_translations_for_domain() call should be inside the if block 😛

    Also, I love the fact that you have more comments than code. 🙂

  6. Is there any way to do this one a per post type basis? For instance, I’d like to filter ‘Scheduled for: %1$s‘ to ‘Event Date: %1$s‘ only on my events custom post type.

    1. This should be possible. Hopefully at the time the string is output there is enough context in global variables for you to determine which page you are on and therefore mangle the string in the correct way.
      From what I recall there is a global which tells you which admin page you are currently on so that may be of use to you.

  7. Peter,

    You pointing me to this as a solution for changing the name of admin menu items. One big of the problems I see with using the gettext hook in almost all cases is that it is called hundreds of times per page load and if anything significant is done in it using it could slow down page load by a noticeable amount. For example, I just ran a test and it runs 577 times on the Dashboard page of the admin.

    The fact it’s run over 500 times is why I’d rather not use it for something so simple as changing the name of a menu option; it’s an expensive and blunt instrument for something that could easily use an inexpensive scalpel, assuming one were easily made available and didn’t require intricate knowledge of the admin menu array structures.

    In general, I’d rather look for a hook that is called only once or just a few executions.

    -Mike

    1. If you find the overhead is to high for this the easiest thing to do is to switch to doing it with a translation file instead. i.e. Create a special translation of WordPress for this particular use case.

  8. Pingback: String Replacement; or, how to not hack the core | BP-Tricks

Comments are closed.