For my first CPT, it seemed great that I could hook a function to post_updated_messages and customize the post messages. When I tried the same for 4 CPTs, only the last filter added was having any effect. Here’s my new DRY method.
function set_custom_messages( $messages ) {
global $post, $post_ID;
$post_type = get_post_type( $post_ID );
$obj = get_post_type_object( $post_type );
$singular = $obj->labels->singular_name;
$messages[$post_type] = array(
0 => '', // Unused. Messages start at index 1.
1 => sprintf( __( $singular . ' updated. <a href="%s">View '.strtolower( $singular) . '</a>' ), esc_url( get_permalink( $post_ID ) ) ),
2 => __('Custom field updated . ' ),
3 => __('Custom field deleted . ' ),
4 => __( $singular . ' updated . ' ),
5 => isset( $_GET['revision']) ? sprintf( __( $singular . ' restored to revision from %s' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
6 => sprintf( __( $singular . ' published. <a href="%s">View '.strtolower( $singular) . '</a>' ), esc_url( get_permalink( $post_ID ) ) ),
7 => __('Page saved . ' ),
8 => sprintf( __( $singular . ' submitted. <a target="_blank" href="%s">Preview '.strtolower( $singular) . '</a>' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
9 => sprintf( __( $singular . ' scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview '.strtolower( $singular) . '</a>' ), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post_ID ) ) ),
10 => sprintf( __( $singular . ' draft updated. <a target="_blank" href="%s">Preview '.strtolower( $singular) . '</a>' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post_ID ) ) ) ),
);
return $messages;
}