Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 21356)
+++ wp-includes/post.php	(working copy)
@@ -27,6 +27,7 @@
 		'capability_type' => 'post',
 		'map_meta_cap' => true,
 		'hierarchical' => false,
+		'show_taxonomy_columns' => array( 'category', 'post_tag' ),
 		'rewrite' => false,
 		'query_var' => false,
 		'delete_with_user' => true,
@@ -977,7 +978,7 @@
 	$defaults = array(
 		'labels' => array(), 'description' => '', 'publicly_queryable' => null, 'exclude_from_search' => null,
 		'capability_type' => 'post', 'capabilities' => array(), 'map_meta_cap' => null,
-		'_builtin' => false, '_edit_link' => 'post.php?post=%d', 'hierarchical' => false,
+		'_builtin' => false, '_edit_link' => 'post.php?post=%d', 'hierarchical' => false, 'show_taxonomy_columns' => false,
 		'public' => false, 'rewrite' => true, 'has_archive' => false, 'query_var' => true,
 		'supports' => array(), 'register_meta_box_cb' => null,
 		'taxonomies' => array(), 'show_ui' => null, 'menu_position' => null, 'menu_icon' => null,
@@ -1285,6 +1286,9 @@
 	if ( !isset( $object->labels['all_items'] ) && isset( $object->labels['menu_name'] ) )
 		$object->labels['all_items'] = $object->labels['menu_name'];
 
+	if ( !isset( $object->labels['no_items'] ) && isset( $object->labels['menu_name'] ) )
+		$object->labels['no_items'] = 'No ' . $object->labels['menu_name'];
+
 	foreach ( $nohier_vs_hier_defaults as $key => $value )
 			$defaults[$key] = $object->hierarchical ? $value[1] : $value[0];
 
Index: wp-includes/taxonomy.php
===================================================================
--- wp-includes/taxonomy.php	(revision 21356)
+++ wp-includes/taxonomy.php	(working copy)
@@ -43,6 +43,9 @@
 
 	register_taxonomy( 'category', 'post', array(
 		'hierarchical' => true,
+		'labels' => array(
+			'no_items' => __( 'Uncategorized' ),
+		),
 		'query_var' => 'category_name',
 		'rewrite' => $rewrite['category'],
 		'public' => true,
@@ -416,6 +419,7 @@
 		'search_items' => array( __( 'Search Tags' ), __( 'Search Categories' ) ),
 		'popular_items' => array( __( 'Popular Tags' ), null ),
 		'all_items' => array( __( 'All Tags' ), __( 'All Categories' ) ),
+		'no_items' => array( __( 'No Tags' ), __( 'No Categories' ) ),
 		'parent_item' => array( null, __( 'Parent Category' ) ),
 		'parent_item_colon' => array( null, __( 'Parent Category:' ) ),
 		'edit_item' => array( __( 'Edit Tag' ), __( 'Edit Category' ) ),
Index: wp-admin/includes/class-wp-posts-list-table.php
===================================================================
--- wp-admin/includes/class-wp-posts-list-table.php	(revision 21358)
+++ wp-admin/includes/class-wp-posts-list-table.php	(working copy)
@@ -270,10 +270,10 @@
 			$posts_columns['author'] = __( 'Author' );
 
 		if ( empty( $post_type ) || is_object_in_taxonomy( $post_type, 'category' ) )
-			$posts_columns['categories'] = __( 'Categories' );
+			$posts_columns['category'] = __( 'Categories' );
 
 		if ( empty( $post_type ) || is_object_in_taxonomy( $post_type, 'post_tag' ) )
-			$posts_columns['tags'] = __( 'Tags' );
+			$posts_columns['post_tag'] = __( 'Tags' );
 
 		$post_status = !empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all';
 		if ( post_type_supports( $post_type, 'comments' ) && !in_array( $post_status, array( 'pending', 'draft', 'future' ) ) )
@@ -287,6 +287,31 @@
 			$posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type );
 		$posts_columns = apply_filters( "manage_{$post_type}_posts_columns", $posts_columns );
 
+		if ( empty( $post_type ) ) return $posts_columns;
+
+		$post_type_object = get_post_type_object( $post_type );
+		$registered_taxonomies = get_object_taxonomies( $post_type );
+
+		if ( $post_type_object->show_taxonomy_columns && is_array( $post_type_object->show_taxonomy_columns ) )
+				$taxonomies = $post_type_object->show_taxonomy_columns;
+		elseif ( $post_type_object->show_taxonomy_columns )
+			$taxonomies = $registered_taxonomies;
+		else
+			$taxonomies = array();
+
+		$this->taxonomy_columns = apply_filters( 'show_taxonomy_columns', $taxonomies, $post_type );
+
+		if ( empty( $this->taxonomy_columns ) ) return $posts_columns;
+
+		foreach ( $this->taxonomy_columns as $registered_taxonomy ) {
+
+			if ( !in_array( $registered_taxonomy, $registered_taxonomies ) ) continue;
+			if ( $registered_taxonomy == 'post_tag' || $registered_taxonomy == 'category' ) continue;
+
+			$taxonomy_object = get_taxonomy( $registered_taxonomy );
+			$posts_columns[$registered_taxonomy] = apply_filters( 'taxonomy_column_header', __( $taxonomy_object->label ), $post_type_object, $taxonomy_object );
+		}
+
 		return $posts_columns;
 	}
 
@@ -529,7 +554,6 @@
 				}
 				else {
 					$attributes = 'class="post-title page-title column-title"' . $style;
-					
 					$pad = str_repeat( '&#8212; ', $level );
 ?>
 			<td <?php echo $attributes ?>><strong><?php if ( $can_edit_post && $post->post_status != 'trash' ) { ?><a class="row-title" href="<?php echo $edit_link; ?>" title="<?php echo esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ); ?>"><?php echo $pad; echo $title ?></a><?php } else { echo $pad; echo $title; }; _post_states( $post ); ?></strong>
@@ -603,46 +627,15 @@
 				echo '</td>';
 			break;
 
-			case 'categories':
-			?>
-			<td <?php echo $attributes ?>><?php
-				$categories = get_the_category();
-				if ( !empty( $categories ) ) {
-					$out = array();
-					foreach ( $categories as $c ) {
-						$out[] = sprintf( '<a href="%s">%s</a>',
-							esc_url( add_query_arg( array( 'post_type' => $post->post_type, 'category_name' => $c->slug ), 'edit.php' ) ),
-							esc_html( sanitize_term_field( 'name', $c->name, $c->term_id, 'category', 'display' ) )
-						);
-					}
-					/* translators: used between list items, there is a space after the comma */
-					echo join( __( ', ' ), $out );
-				} else {
-					_e( 'Uncategorized' );
-				}
-			?></td>
-			<?php
-			break;
+			case ( is_array( $this->taxonomy_columns ) && in_array( $column_name, $this->taxonomy_columns ) ) :
 
-			case 'tags':
-			?>
-			<td <?php echo $attributes ?>><?php
-				$tags = get_the_tags( $post->ID );
-				if ( !empty( $tags ) ) {
-					$out = array();
-					foreach ( $tags as $c ) {
-						$out[] = sprintf( '<a href="%s">%s</a>',
-							esc_url( add_query_arg( array( 'post_type' => $post->post_type, 'tag' => $c->slug ), 'edit.php' ) ),
-							esc_html( sanitize_term_field( 'name', $c->name, $c->term_id, 'tag', 'display' ) )
-						);
-					}
-					/* translators: used between list items, there is a space after the comma */
-					echo join( __( ', ' ), $out );
-				} else {
-					_e( 'No Tags' );
-				}
-			?></td>
-			<?php
+			$defaults = array(
+				'taxonomy' => $column_name,
+				'attributes' => $attributes,
+			);
+			$args = apply_filters( 'taxonomy_column_args', $defaults, $post_type_object, $column_name  );
+
+			$this->taxonomy_column( $args );
 			break;
 
 			case 'comments':
@@ -679,8 +672,8 @@
 			?></td>
 			<?php
 			break;
+			}
 		}
-	}
 	?>
 		</tr>
 	<?php
@@ -688,6 +681,45 @@
 	}
 
 	/**
+	 * Creates internal taxonomy columns as well as registered taxonomies
+	 *
+	 * @since 3.5.0
+	 */
+	function taxonomy_column( $atts = array() ) {
+		global $post;
+
+		$defaults = array(
+			'taxonomy' => 'category',
+			'attributes' => '',
+			'empty' => '',
+		);
+		$args = wp_parse_args( (array) $atts, $defaults );
+		extract( $args, EXTR_SKIP );
+
+		$attributes = !empty( $attributes ) ? $attributes : 'class="column-'. $taxonomy .'"';
+		$taxonomy_object = get_taxonomy( $taxonomy );
+
+		?>
+		<td <?php echo $attributes ?>><?php
+			$terms = get_the_terms( $post->ID, $taxonomy );
+			if ( !empty( $terms ) ) {
+				$out = array();
+				foreach ( $terms as $t ) {
+					$out[] = sprintf( '<a href="%s">%s</a>',
+						esc_url( add_query_arg( array( 'post_type' => $post->post_type, $taxonomy_object->query_var => $t->slug ), 'edit.php' ) ),
+						esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) )
+					);
+				}
+				/* translators: used between list items, there is a space after the comma */
+				echo join( __( ', ' ), $out );
+			} else {
+				echo $taxonomy_object->labels->no_items;
+			}
+		?></td>
+		<?php
+	}
+
+	/**
 	 * Outputs the hidden row displayed when inline editing
 	 *
 	 * @since 3.1.0
Index: wp-admin/css/wp-admin.dev.css
===================================================================
--- wp-admin/css/wp-admin.dev.css	(revision 21357)
+++ wp-admin/css/wp-admin.dev.css	(working copy)
@@ -2350,8 +2350,8 @@
 
 .fixed .column-response,
 .fixed .column-author,
-.fixed .column-categories,
-.fixed .column-tags,
+.fixed .column-category,
+.fixed .column-post_tag,
 .fixed .column-rel,
 .fixed .column-role {
 	width: 15%;
