Index: wp-includes/l10n.php
===================================================================
--- wp-includes/l10n.php	(revision 17037)
+++ wp-includes/l10n.php	(working copy)
@@ -272,10 +272,11 @@
  * @since 2.5
  * @param string $single Single form to be i18ned
  * @param string $plural Plural form to be i18ned
- * @return array array($single, $plural)
+ * @param string $domain Gettext domain. Optional. If not present, the domain passed to {@link translate_nooped_plural()} will be used.
+ * @return array array('single' => $single, 'plural' => $plural, ...)
  */
-function _n_noop( $singular, $plural ) {
-	return array( 0 => $singular, 1 => $plural, 'singular' => $singular, 'plural' => $plural, 'context' => null );
+function _n_noop( $singular, $plural, $domain = null ) {
+	return array( 0 => $singular, 1 => $plural, 'singular' => $singular, 'plural' => $plural, 'context' => null, 'domain' => $domain );
 }
 
 /**
@@ -283,8 +284,8 @@
  *
  * @see _n_noop()
  */
-function _nx_noop( $singular, $plural, $context ) {
-	return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context );
+function _nx_noop( $singular, $plural, $context, $domain = null ) {
+	return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context, 'domain' => $domain );
 }
 
 /**
@@ -293,9 +294,10 @@
  * @since 3.1
  * @param array $nooped_plural array with singular, plural and context keys, usually the result of _n_noop() or _nx_noop()
  * @param int $count number of objects
- * @param string $domain Optional. The domain identifier the text should be retrieved in
+ * @param string $domain Optional. The domain identifier the text should be retrieved in. Used only in case $nooped_plural doesn't contain a domain
  */
 function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) {
+	$domain = is_null( $nooped_plural['domain'] )? $domain : $nooped_plural['domain'];
 	if ( $nooped_plural['context'] )
 		return _nx( $nooped_plural['singular'], $nooped_plural['plural'], $count, $nooped_plural['context'], $domain );
 	else
Index: wp-includes/comment-template.php
===================================================================
--- wp-includes/comment-template.php	(revision 17037)
+++ wp-includes/comment-template.php	(working copy)
@@ -560,33 +560,106 @@
 }
 
 /**
- * Display the language string for the number of comments the current post has.
- *
- * @since 0.71
- * @uses apply_filters() Calls the 'comments_number' hook on the output and number of comments respectively.
- *
- * @param string $zero Text for no comments
- * @param string $one Text for one comment
- * @param string $more Text for more than one comment
- * @param string $deprecated Not used.
+ * Return the text for the number of comments the current post has. The arguments are the same as those of {@link comments_number_text()}
+ * 
+ * @see comments_number_text()
  */
-function comments_number( $zero = false, $one = false, $more = false, $deprecated = '' ) {
-	if ( !empty( $deprecated ) )
-		_deprecated_argument( __FUNCTION__, '1.3' );
+function get_comments_number_text( $no_comments = null, $one_comment = null, $many_comments = null, $domain = 'default'  ) {
+	return _get_comments_number_text_helper( $no_comments, $one_comment, $many_comments, null, $domain );
+}
 
+function get_comments_number_text_x( $no_comments = null, $one_comment = null, $many_comments = null, $context = null, $domain = 'default' ) {
+	return _get_comments_number_text_helper( $no_comments, $one_comment, $many_comments, $context, $domain );
+}
+
+/**
+ * @access private
+ */
+function _get_comments_number_text_helper( $no_comments = null, $one_comment = null, $many_comments = null, $context, $domain = 'default' ) {
 	$number = get_comments_number();
+	if ( 0 == $number ) {
+		$text = is_null( $no_comments )? __( 'No Comments' ) : translate( $no_comments );
+	} else {
+		$format = _get_comments_number_translated_format( $number, $one_comment, $many_comments, $context, $domain);
+		$text = sprintf( $format, number_format_i18n( $number) );
+	}
+	return apply_filters( 'get_comments_number_text', $text, $number );
+	
+}
 
-	if ( $number > 1 )
-		$output = str_replace('%', number_format_i18n($number), ( false === $more ) ? __('% Comments') : $more);
-	elseif ( $number == 0 )
-		$output = ( false === $zero ) ? __('No Comments') : $zero;
-	else // must be one
-		$output = ( false === $one ) ? __('1 Comment') : $one;
+/**
+ * @access private
+ */
+function _get_comments_number_translated_format( $number, $one_comment, $many_comments, $context, $domain ) {
+	if ( is_null( $one_comment ) || is_null( $many_comments) )
+		return $context? _nx( '1 Comment', '%s Comments', $number, $context, $domain ) : _n( '1 Comment', '%s Comments', $number, $context, $domain );
+	else
+		return $context? _nx( $one_comment, $many_comments, $number, $context, $domain ) : _n( $one_comment, $many_comments, $number, $domain );
+}
 
-	echo apply_filters('comments_number', $output, $number);
+function comments_number_text( $no_comments = null, $one_comment = null, $many_comments = null, $domain = 'default' ) {
+	$number = get_comments_number();
+	$after_old_filter = apply_filters( 'comments_number', get_comments_number_text( $no_comments, $one_comment, $many_comments, $domain ), $number );
+	echo apply_filters( 'comments_number_text', $after_old_filter, $number );
 }
 
+function comments_number_text_x( $no_comments = null, $one_comment = null, $many_comments = null, $context, $domain = 'default' ) {
+	$number = get_comments_number();
+	$after_old_filter = apply_filters( 'comments_number', get_comments_number_text_x( $no_comments, $one_comment, $many_comments, $context, $domain ), $number );
+	echo apply_filters( 'comments_number_text', $after_old_filter, $number );
+}
+
+
 /**
+ * Return an HTML link to the current post's comments. The arguments are the same as those of {@link comments_number_link()}
+ * 
+ */
+function get_comments_number_link( $no_comments = null, $one_comment = null, $many_comments = null, $domain = 'default', $disabled = null, $attrs = array() ) {
+	global $wpcommentspopupfile, $wpcommentsjavascript;
+	$number = get_comments_number();
+	
+	$disabled = is_null( $disabled )? __( 'Comments Off' ) : translate( $disabled );
+
+	if ( 0 == $number && !comments_open() && !pings_open() ) {
+		return "<span ".apply_filters( 'get_comments_number_link_attrs', $attrs ).">$disabled</span>";
+	}
+
+	if ( post_password_required() ) {
+		return __( 'Enter your password to view comments.' );
+	}
+	
+	if ( post_password_required() ) {
+		echo __('Enter your password to view comments.');
+		return;
+	}
+
+	$attrs['href'] = $number? get_comments_link() : get_permalink() . '#respond';
+	if ( isset( $wpcommentsjavascript ) && $wpcommentsjavascript ) {
+		$home = $wpcommentspopupfile? get_option( 'siteurl' ) : home_url();
+		$attrs['href'] = $home . '/' . $wpcommentspopupfile . '?comments_popup=' . get_the_ID();
+		$attrs['onclick'] = 'wpopen(this.href); return false;';
+	}
+	$attrs['title'] = sprintf( __('Comment on %s'), get_the_title() );
+	$attrs = apply_filters( 'get_comments_number_link_attrs', $attrs );
+	
+	$text = get_comments_number_text( $no_comments, $one_comment, $many_comments, $domain );
+	$html_attrs = wp_html_attributes( $attrs );
+	return "<a $html_attrs>$text</a>";
+}
+
+/**
+ * Display an HTML link to the current post's comments
+ * 
+ * @param string $zero text if there are no comments. Optional. Default is 'No Comments'
+ * @param string $nooped_plural the result of {@link _n_noop()} or {@link _nx_noop()}, which determines what the text will be depending on different comment numbers
+ * @param string $disabled text if comments are disabled. Options. Default is 'Comments Off'
+ * @param array $attrs associative array of html attributes and their values (raw, not escaped)
+ */
+function comments_number_link( $no_comments = null, $one_comment = null, $many_comments = null, $domain = 'default', $disabled = null, $attrs = array() ) {
+	echo get_comments_number_link( $no_comments, $one_comment, $many_comments, $domain, $disabled, $attrs );
+}
+
+/**
  * Retrieve the text of the current comment.
  *
  * @since 1.5.0
@@ -949,74 +1022,6 @@
 }
 
 /**
- * Displays the link to the comments popup window for the current post ID.
- *
- * Is not meant to be displayed on single posts and pages. Should be used on the
- * lists of posts
- *
- * @since 0.71
- * @uses $wpcommentspopupfile
- * @uses $wpcommentsjavascript
- * @uses $post
- *
- * @param string $zero The string to display when no comments
- * @param string $one The string to display when only one comment is available
- * @param string $more The string to display when there are more than one comment
- * @param string $css_class The CSS class to use for comments
- * @param string $none The string to display when comments have been turned off
- * @return null Returns null on single posts and pages.
- */
-function comments_popup_link( $zero = false, $one = false, $more = false, $css_class = '', $none = false ) {
-	global $wpcommentspopupfile, $wpcommentsjavascript;
-
-	$id = get_the_ID();
-
-	if ( false === $zero ) $zero = __( 'No Comments' );
-	if ( false === $one ) $one = __( '1 Comment' );
-	if ( false === $more ) $more = __( '% Comments' );
-	if ( false === $none ) $none = __( 'Comments Off' );
-
-	$number = get_comments_number( $id );
-
-	if ( 0 == $number && !comments_open() && !pings_open() ) {
-		echo '<span' . ((!empty($css_class)) ? ' class="' . esc_attr( $css_class ) . '"' : '') . '>' . $none . '</span>';
-		return;
-	}
-
-	if ( post_password_required() ) {
-		echo __('Enter your password to view comments.');
-		return;
-	}
-
-	echo '<a href="';
-	if ( $wpcommentsjavascript ) {
-		if ( empty( $wpcommentspopupfile ) )
-			$home = home_url();
-		else
-			$home = get_option('siteurl');
-		echo $home . '/' . $wpcommentspopupfile . '?comments_popup=' . $id;
-		echo '" onclick="wpopen(this.href); return false"';
-	} else { // if comments_popup_script() is not in the template, display simple comment link
-		if ( 0 == $number )
-			echo get_permalink() . '#respond';
-		else
-			comments_link();
-		echo '"';
-	}
-
-	if ( !empty( $css_class ) ) {
-		echo ' class="'.$css_class.'" ';
-	}
-	$title = the_title_attribute( array('echo' => 0 ) );
-
-	echo apply_filters( 'comments_popup_link_attributes', '' );
-
-	echo ' title="' . esc_attr( sprintf( __('Comment on %s'), $title ) ) . '">';
-	comments_number( $zero, $one, $more );
-	echo '</a>';
-}
-
-/**
  * Retrieve HTML content for reply to comment link.
  *
  * The default arguments that can be override are 'add_below', 'respond_id',
Index: wp-includes/formatting.php
===================================================================
--- wp-includes/formatting.php	(revision 17037)
+++ wp-includes/formatting.php	(working copy)
@@ -2898,4 +2898,22 @@
 
 }
 
-?>
+/**
+ * Builds an HTML attributes string out of an associattive array
+ * 
+ * You don't have to escape the attribute values.
+ * 
+ * Example:
+ * <code>wp_html_attributes( array( 'class' => 'post', 'id' => 'post-11' ) )</code> will return <code>'class="post" id="post-11"'</code>
+ * 
+ * @param $attr array associative array in the form attribute-name => attribute-value
+ * @return string the attributes suitable for insertion into an HTML tag
+ */
+function wp_html_attributes( $attrs ) {
+	$attrs = wp_parse_args( $attrs );
+	$strings = array();
+	foreach( $attrs as $key => $value ) {
+		$strings[] = $key.'="'.esc_attr( $value ).'"';
+	}
+	return implode( ' ', $strings );
+}
\ No newline at end of file
Index: wp-includes/deprecated.php
===================================================================
--- wp-includes/deprecated.php	(revision 17037)
+++ wp-includes/deprecated.php	(working copy)
@@ -2577,3 +2577,101 @@
 	return true;
 }
 
+/**
+ * Display the language string for the number of comments the current post has.
+ *
+ * @since 0.71
+ * @uses apply_filters() Calls the 'comments_number' hook on the output and number of comments respectively.
+ *
+ * @param string $zero Text for no comments
+ * @param string $one Text for one comment
+ * @param string $more Text for more than one comment
+ * @param string $deprecated Not used.
+ */
+function comments_number( $zero = false, $one = false, $more = false, $deprecated = '' ) {
+	_deprecated_function( __FUNCTION__, '3.1', 'comments_number_text()'  );
+	
+	if ( !empty( $deprecated ) )
+		_deprecated_argument( __FUNCTION__, '1.3' );
+
+	$number = get_comments_number();
+
+	if ( $number > 1 )
+		$output = str_replace('%', number_format_i18n($number), ( false === $more ) ? __('% Comments') : $more);
+	elseif ( $number == 0 )
+		$output = ( false === $zero ) ? __('No Comments') : $zero;
+	else // must be one
+		$output = ( false === $one ) ? __('1 Comment') : $one;
+
+	echo apply_filters('comments_number', $output, $number);
+}
+
+/**
+ * Displays the link to the comments popup window for the current post ID.
+ *
+ * Is not meant to be displayed on single posts and pages. Should be used on the
+ * lists of posts
+ *
+ * @since 0.71
+ * @uses $wpcommentspopupfile
+ * @uses $wpcommentsjavascript
+ * @uses $post
+ *
+ * @param string $zero The string to display when no comments
+ * @param string $one The string to display when only one comment is available
+ * @param string $more The string to display when there are more than one comment
+ * @param string $css_class The CSS class to use for comments
+ * @param string $none The string to display when comments have been turned off
+ * @return null Returns null on single posts and pages.
+ */
+function comments_popup_link( $zero = false, $one = false, $more = false, $css_class = '', $none = false ) {
+	global $wpcommentspopupfile, $wpcommentsjavascript;
+	
+	_deprecated_function( __FUNCTION__, '3.1', 'comments_number_link()'  );
+
+	$id = get_the_ID();
+
+	if ( false === $zero ) $zero = __( 'No Comments' );
+	if ( false === $one ) $one = __( '1 Comment' );
+	if ( false === $more ) $more = __( '% Comments' );
+	if ( false === $none ) $none = __( 'Comments Off' );
+
+	$number = get_comments_number( $id );
+
+	if ( 0 == $number && !comments_open() && !pings_open() ) {
+		echo '<span' . ((!empty($css_class)) ? ' class="' . esc_attr( $css_class ) . '"' : '') . '>' . $none . '</span>';
+		return;
+	}
+
+	if ( post_password_required() ) {
+		echo __('Enter your password to view comments.');
+		return;
+	}
+
+	echo '<a href="';
+	if ( $wpcommentsjavascript ) {
+		if ( empty( $wpcommentspopupfile ) )
+			$home = home_url();
+		else
+			$home = get_option('siteurl');
+		echo $home . '/' . $wpcommentspopupfile . '?comments_popup=' . $id;
+		echo '" onclick="wpopen(this.href); return false"';
+	} else { // if comments_popup_script() is not in the template, display simple comment link
+		if ( 0 == $number )
+			echo get_permalink() . '#respond';
+		else
+			comments_link();
+		echo '"';
+	}
+
+	if ( !empty( $css_class ) ) {
+		echo ' class="'.$css_class.'" ';
+	}
+	$title = the_title_attribute( array('echo' => 0 ) );
+
+	echo apply_filters( 'comments_popup_link_attributes', '' );
+
+	echo ' title="' . esc_attr( sprintf( __('Comment on %s'), $title ) ) . '">';
+	comments_number( $zero, $one, $more );
+	echo '</a>';
+}
\ No newline at end of file
Index: wp-content/themes/twentyten/loop.php
===================================================================
--- wp-content/themes/twentyten/loop.php	(revision 17037)
+++ wp-content/themes/twentyten/loop.php	(working copy)
@@ -53,11 +53,8 @@
 	 *
 	 * Without further ado, the loop:
 	 */ ?>
-<?php while ( have_posts() ) : the_post();
+<?php while ( have_posts() ) : the_post(); ?>
 
-$comment_number_template = _n( '1 Comment', '% Comments', get_comments_number(), 'twentyten' );
-?>
-
 <?php /* How to display posts of the Gallery format. The gallery category is the old way. */ ?>
 
 	<?php if ( 'gallery' == get_post_format( $post->ID ) || in_category( _x( 'gallery', 'gallery category slug', 'twentyten' ) ) ) : ?>
@@ -99,7 +96,7 @@
 				<a href="<?php echo get_term_link( _x( 'gallery', 'gallery category slug', 'twentyten' ), 'category' ); ?>" title="<?php esc_attr_e( 'View posts in the Gallery category', 'twentyten' ); ?>"><?php _e( 'More Galleries', 'twentyten' ); ?></a>
 				<span class="meta-sep">|</span>
 			<?php endif; ?>
-				<span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'twentyten' ), $comment_number_template, $comment_number_template ); ?></span>
+				<span class="comments-link"><?php comments_number_link( 'Leave a comment', '1 Comment', '%s Comments', 'twentyten' ); ?></span>
 				<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="meta-sep">|</span> <span class="edit-link">', '</span>' ); ?>
 			</div><!-- .entry-utility -->
 		</div><!-- #post-## -->
@@ -122,7 +119,7 @@
 			<div class="entry-utility">
 				<?php twentyten_posted_on(); ?>
 				<span class="meta-sep">|</span>
-				<span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'twentyten' ), $comment_number_template, $comment_number_template ); ?></span>
+				<span class="comments-link"><?php comments_number_link( 'Leave a comment', '1 Comment', '%s Comments', 'twentyten' ); ?></span>
 				<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="meta-sep">|</span> <span class="edit-link">', '</span>' ); ?>
 			</div><!-- .entry-utility -->
 		</div><!-- #post-## -->
@@ -164,7 +161,7 @@
 					</span>
 					<span class="meta-sep">|</span>
 				<?php endif; ?>
-				<span class="comments-link"><?php comments_popup_link( __( 'Leave a comment', 'twentyten' ), $comment_number_template, $comment_number_template ); ?></span>
+				<span class="comments-link"><?php comments_number_link( 'Leave a comment', '1 Comment', '%s Comments', 'twentyten' ); ?></span>
 				<?php edit_post_link( __( 'Edit', 'twentyten' ), '<span class="meta-sep">|</span> <span class="edit-link">', '</span>' ); ?>
 			</div><!-- .entry-utility -->
 		</div><!-- #post-## -->
