Quick Register Custom Post Type In WordPress

When register custom post type in WordPress, the most boring work is writing labels for menus and notifications. If your theme has several custom post types, that work will be repeated again and again. In this case, we can avoid duplication by creating a function that handle all the labels and other parameters automatically, and call it with minimum arguments when needed.

This is how I do that:

function rw_register_post_type( $post_type = '', $args = array() )
    if ( empty( $post_type ) )

    $singular = empty( $args['singular'] ) ? $post_type : $args['singular'];
    $singular = str_replace( '_', ' ', $singular );
    $singular = ucwords( $singular );

    $plural = empty( $args['plural'] ) ? "{$singular}s" : $args['plural'];
    $plural = ucwords( $plural );
    $plural_lower = strtolower( $plural );

    $args['labels'] = empty( $args['labels'] ) ? array() : $args['labels'];
    $args['labels'] = wp_parse_args( $args['labels'], array(
        'name'               => $plural,
        'singular_name'      => $singular,
        'add_new'            => __( 'Add New', 'your_textdomain' ),
        'add_new_item'       => sprintf( __( 'Add New %s', 'your_textdomain' ), $singular ),
        'edit_item'          => sprintf( __( 'Edit %s', 'your_textdomain' ), $singular ),
        'new_item'           => sprintf( __( 'New %s', 'your_textdomain' ), $singular ),
        'view_item'          => sprintf( __( 'View %s', 'your_textdomain' ), $singular ),
        'search_items'       => sprintf( __( 'Search %s', 'your_textdomain' ), $plural ),
        'not_found'          => sprintf( __( 'No %s found', 'your_textdomain' ), $plural_lower ),
        'not_found_in_trash' => sprintf( __( 'No %s found in Trash', 'your_textdomain' ), $plural_lower ),
        'parent_item_colon'  => null,
        'all_items'          => sprintf( __( 'All %s', 'your_textdomain' ), $plural ),
        'menu_name'          => $plural,
    ) );

    $args = wp_parse_args( $args, array(
        'public' => true,
    ) );

    register_post_type( $post_type, $args );

How to use

Simple example: NO arguments

rw_register_post_type( 'book' );
rw_register_post_type( 'movie' );

This will register custom post type book and create singular label Book as well as plural label Books and apply to menu items and notifications.

Different types of plural label

rw_register_post_type( 'company', array(
    'plural' => 'companies',
) );
rw_register_post_type( 'box', array(
    'plural' => 'boxes',
) );

The plural argument is used when you need to specified plural label, in case it’s not auto generated by adding s to singular label.

Handle other arguments

rw_register_post_type( 'company', array(
    'hierarchy' => 'true',
    'public' => false,
) );

This function can handle all default WordPress arguments used by register_post_type function. All arguments are optional. By default it uses only public => true.

Hope this is helpful for you, any feedback is welcomed.


  1. Love the way register post type made easy. Custom Post Type is not only usefull but also “tricky”, and somehow a little bore (writing like-code lines).
    Thanks a lot Tran :)

  2. Some languages use up to four different plural forms. Since you don’t even provide a context parameter – what should translators do when you register two post types with the same text domain?

      • See http://mylanguages.org/polish_plural.php for multiple language forms.

        But the problems with your approach start much earlier.
        Given your examples ‘book’ and ‘movie’: In German I had to translate ‘New %s’ as:

        • Neues Buch (for a book)
        • Neuer Film (for a movie)

        Impossible when I get just one string for both.

        • Ehm … that should be *multiple plural forms*. :)

        • I understand. I know Russian, and it has the same problem. Looks like this “quick” method is not as “quick” solution for all cases.

Leave a Reply