Using plural-only translation of register_post_status() in plugin

tl;dr: My plugin wants to translate strings from core or other plugins that use _n_noop(). How?

This question related to this plugin and is sort of a follow up to this question.

Read More

My plugin adds “{status} (n)” (e.g. “Drafts (10)”) to the admin menus for any post type. It supports any post status added with register_post_status() because it grabs all statuses with the get_post_stati() function (not the irritatingly similar get_post_statuses()).

When someone registers a post status with register_post_status(), one includes a label_count value in the $args that is perfect for what I need. I’d always like to display the plural label count in the menu and use sprintf() to drop in the count value.

Here’s a truncated excerpt of the current plugin code (that first sprintf() is the thing I’m looking to change):

<?php
// an array of all the statuses
$ps_statuses = get_post_stati( array( 'show_in_admin_status_list' => true ), 'objects' );

// a filter for the list of statuses for anything people want to do that's plugin specific
$ps_statuses = apply_filters( 'psmi_statuses', $ps_statuses );

// Get status counts of all post types
$ps_status_counts = wp_count_posts( $ps_type_id );

foreach( $ps_statuses as $status ) {

    $ps_status_id = $status->name;
    $ps_status_count = $ps_status_counts -> $ps_status_id;

    // If a status has any posts, show it
    if( $ps_status_count > 0 ) {
        // Get the plural post status label
        $ps_status_label = $status->label_count['plural'];
        $submenu[$menu][] = array(
            sprintf(
                $ps_status_label,
                $ps_status_count
            ),
            'read',
            sprintf(
                '%1$sedit.php?post_status=%2$s&post_type=%3$s',
                get_admin_url(),
                $ps_status_id,
                $ps_type_id
            )

        );
    }
}

This works fine, but it’s untranslatable.

I can see that when WordPress registers the post stati in core (in /wp-includes/post.php), it uses the _n_noop() function to allow for plural translations:

register_post_status( 'draft', array(
    'label'       => _x( 'Draft', 'post' ),
    'protected'   => true,
    '_builtin'    => true, /* internal use only. */
    'label_count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>' ),
) );

However, I haven’t been able to figure out how to get the translated string working. I think I need to use translate_nooped_plural(), but I haven’t been able to get that to work (and really, I just want to use the plural string even if there’s only one post in a status). Secondly, I’m really lost what text domain I should use because the statuses could be coming from core, a custom call or register_post_status(), or a plugin like edit flow.

Related posts

Leave a Reply

1 comment

  1. // Get the plural post status label
    $ps_status_label = $status->label_count;
    
    $submenu[$menu][] = array(
    
      sprintf(
        translate_nooped_plural(
          $ps_status_label,
          $ps_status_count
        ),
        $ps_status_count
      ),
    

    This should work as expected for the core translations. Now you need the textdomain, so lets search for the string you wish to translate

    foreach ( $GLOBALS['l10n'] as $domain => $data ) {
        if ( in_array( $ps_status_label[0], array_keys( $data->entries ) ) )
            break;
    
        $domain = '';
    }
    
    $domain = ( ! empty( $domain ) ) ? $domain : 'default';
    

    And now you can alter the first code snippet to

    // Get the plural post status label
    $ps_status_label = $status->label_count;
    
    $submenu[$menu][] = array(
    
      sprintf(
        translate_nooped_plural(
          $ps_status_label,
          $ps_status_count,
          $domain
        ),
        $ps_status_count
      ),
    

    You only need the plural form of the post status, just rise the count value in translate_nooped_plural()

    sprintf(
      translate_nooped_plural(
        $ps_status_label,
        10,
        $domain
      ),
      $ps_status_count
    ),
    

    This will always return the plural form because the count value is greater than 1. Be sure to use a value graeter than 3, because in some languages there are differences between the cases for one, two or more.

    Just to clearify:

    translate_nooped_plural(
      [array(
        [string for singular]
        [string for plural]
      ),
      [count] (1 = select singular string, greater than 1 select the plural string)
      [domain]
    )