How to change the WordPress post updated messages of the edit screen

WordPress posts edit interface has got a good information messages system for all user actions. It doesn’t matter what is the done action, WordPress talks to us: draft saved, post updated, published… Actually, it’s a perfect information system if regulary you only publish posts or sometimes a new page, ie, if you have just got a blog but, when your website has other kinds of information (films, cats, recipies, products…) WordPress keeps saying “post updated” and in fact, you are editing an actor’s profile, or a recipe, or whatever, but not a post… Would not it be awesome that WordPress says “Actor profile updated”, or “Recipe improved” or any message more like the natural language? So, if you don’t want that WordPress talks like a machine, you need use post_updated_messages.

Some examples of WordPress post updated messages on the edit screen

I’m sure that if your website talks about recipes, or actor profiles (whatever that is not a post), you are used to use the WP function register_post_type but probably you don’t know that there is another option that works together with register_post_type that allows us also to change the information messages related with these new kinds of information. Yes, as I said the filter post_updated_messages.

Using the filter post_updated_messages

This filter, that’s called inside the WP edit-form-advanced.php module, is the solution for this problem. It’s a filter that receives one parameter: an array of all information messages written for all WordPress Post Types, ie, the filter receives an array of arrays. See the basic structure.

$msg = array (

    'post' => array (
         0 => '', // Unused. Messages start at index 1.
	 1 => __( 'Post updated.' ) . $view_post_link_html,
	 2 => __( 'Custom field updated.' ),
	 3 => __( 'Custom field deleted.' ),
	 4 => __( 'Post updated.' ),
	/* translators: %s: date and time of the revision */
	 5 => isset( $_GET['revision']) ? sprintf( __( 'Post restored to revision from %s.' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
	 6 => __( 'Post published.' ) . $view_post_link_html,
	 7 => __( 'Post saved.' ),
	 8 => __( 'Post submitted.' ) . $preview_post_link_html,
	 9 => sprintf( __( 'Post scheduled for: %s.' ), '<strong>' . $scheduled_date . '</strong>' ) . $scheduled_post_link_html,
	10 => __( 'Post draft updated.' ) . $preview_post_link_html,

    'page' => array (
         // the same for pages changing the word 'post' for 'page'

     // Here, the arrays of messages for other post types  
     // 'recipe'   => array ( ... ), 
     // 'actor_profile'    => array ( ... ),
     // 'cat'      => array ( ... ),
     // 'country'  => array ( ... ),

Well, the first think that you have to know it’s that, inside your filter function, the array of messages for your Post Type has to be declared in the same order [from 0 to 10] because WordPress uses numeric codes for indentifying the different actions: 1 for updated, 6 for published, 10 for draft saved. So, you must not change the order.

The second thing is that this new array of your information messages has to be identified with the real Post Type name as you can see in the colored part of the former example. It doesn’t matter the label strings that you use on the screen for the Post Type, if it’s been declared throught an instruction like register_post_type ( 'actor_profile', $args );, your array of information messages has to be named as 'actor_profile' => array( ... ).

First example

So in a first approach, for Actors we could write a function like this:

function actors_post_updated_messages ( $msg ) {
    $msg[ 'actor_profile' ] = array (
         0 => '', // Unused. Messages start at index 1.
	 1 => "Actor's profile updated.",
           // or simply "Actor updated.",
           // natural language "The actor's profile has been updated successfully.",
           // or what you need "Actor updated, so remember to check also <strong>the films list</strong>."

	 2 => 'Custom field updated.',  // Probably better do not touch
	 3 => 'Custom field deleted.',  // Probably better do not touch

	 4 => "Actor's profile updated.",
	 5 => "Actor's profile restored to revision",
	 6 => "Actor's profile published.",
            // you can use the kind of messages that better fits with your needs
	    // 6 => "Good boy, one more... so, 4,999,999 are to reach IMDB.",
	    // 6 => "This actor is already on the website.",
	    // 6 => "Congratulations, a new Actor's profile has been published.",
	 7 => "Actor's profile saved.",
	 8 => "Actor's profile submitted.",
	 9 => "Actor's profile scheduled.",
	10 => "Actor's profile draft updated.",
    return $msg;
add_filter( 'post_updated_messages', 'actors_post_updated_messages', 10, 1 );

In this first simplified example, we have seen the basic structure of the filter function, how to name the array actor_profile of messages, how to keep the exact order of the items in the array, and we even avoid the WP translation system supressing the WP function __(). The objective of this first example was simply to show that you can decide (write) the kind of messages that you want for each kind of Post Type in your Website.

Perhaps this basic example is enought for your needs but, if you take a deeper look to the first array –the original WordPress array of messages– you have noticed that, appart from translation functions, there were some additional elements: $_GET['revision'], $scheduled_date, etc. and believe me, these variables are good for something so, if you need an improved system of messages, let’s go with the next example.

Second example

In this example, we’ll introduce all the variable elements of the original WordPress array so, we need to add some code to our simplified former function.

function actors_post_updated_messages ( $msg ) {

    global $post;

    $view_post_link_html = sprintf( ' <a href="%1$s">%2$s</a>',
	esc_url( get_permalink ( $post->ID ) ),
	__( "View actor's profile", 'txtdomain' ) // we can even change the link messages

    $preview_post_link_html = sprintf( ' <a target="_blank" href="%1$s">%2$s</a>',
	esc_url( get_preview_post_link( $post->ID ) ),
	__( "Preview actor's profile", 'txtdomain' )

    $scheduled_post_link_html = sprintf( ' <a target="_blank" href="%1$s">%2$s</a>',
	esc_url( get_permalink ( $post->ID ) ),
	__( "Preview actor's profile", 'txtdomain' )

    $scheduled_date = date_i18n( __( 'M j, Y @ H:i' ), strtotime( $post->post_date ) );

    $msg[ 'actor_profile' ] = array (

	 0 => '', // Unused. Messages start at index 1.

         // here, we also add the ID 
	 1 => sprintf( __( "#Actor <strong>%s</strong> has been updated successfully.", 'txtdomain' ), $post->ID ) . $view_post_link_html,

	 2 => __( 'Custom field updated.' ),
	 3 => __( 'Custom field deleted.' ),

         // here, we use the actor's name (probably the title) if it's not empty.
	 4 => ( ! empty( $post->post_title )  
                    ? sprintf( __( "The profile of <strong>%s</strong> updated.", 'txtdomain' ), $post->post_title )
                    : __( "Actor's profile updated.", 'txtdomain' ) 

	 5 => isset($_GET['revision']) ? sprintf( __( "Actor's profile restored to revision from %s.", 'txtdomain' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
	 6 => __( "Actor's profile published.", 'txtdomain' ) . $view_post_link_html,
	 7 => __( "Actor's profile saved.", 'txtdomain' ),
	 8 => __( "Actor's profile submitted.", 'txtdomain' ) . $preview_post_link_html,
	 9 => ( ! empty( $post->post_title ) 
                      ? sprintf( __( "The profile of <strong>%s</strong> has been scheduled for publishing on <strong>%s</strong>.", 'txtdomain' ), $post->post_title, $scheduled_date )
                      : sprintf( __( "Actor's profile without <strong>NAME</strong> scheduled for: %s", 'txtdomain' ), $scheduled_date )
               ) . $scheduled_post_link_html,
	10 => __( "Actor's profile draft <strong>updated</strong> successfully.", 'txtdomain' ) . $preview_post_link_html,


    return $msg;

add_filter( 'post_updated_messages', 'actors_post_updated_messages', 10, 1 );

In this second example, firstly we have created the four initial variables of the WordPress original array (links, scheduled, etc.) but in addition, we also used to rebuild completely the information system,

  • of course, we’ve changed the messages but, in addition
  • we’ve introduced our own translation domain 'txtdomain',
  • we’ve added some HTML to messages,
  • and we’ve introduced new variables —$post->ID, $post->post_title— in messages as in the items 1st, 4th, 9th of the array,
  • we’ve created an ALERT message in the 9th item. The case where we have scheduled –and we’ll probably forget– for publishing an actor’s profile without name,
  • etc.

Actually, we can transform completely the messages shown by WordPress and so to improve their fit with the context for getting a more fluent and intelligent interfaces… Well, perhaps this kind of issues is not important for you but if not, now you already know how to walk towards a more Natural Language Interfaces on WordPress.

Have a nice WordPressing!

Leave a Comment

   Mandatory field
You can use these HTML tags inside the commment.
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>