diff --git src/wp-includes/class.wp-dependencies.php src/wp-includes/class.wp-dependencies.php
index c1bac65..e6b6288 100644
--- src/wp-includes/class.wp-dependencies.php
+++ src/wp-includes/class.wp-dependencies.php
@@ -201,6 +201,19 @@ class WP_Dependencies {
 	}
 
 	/**
+	 * Adds dependencies
+	 * @param string $handle Script name
+	 * @param array|string $deps Either an array of handles to become dependancies, or a single string dependancy
+	 * @rerurn bool success
+	 */
+	function add_deps( $handle, $deps ) {
+		if ( !isset( $this->registered[$handle] ) ) {
+			return false;
+		}
+		return $this->registered[$handle]->add_deps( $deps );
+	}
+
+	/**
 	 * Register an item.
 	 *
 	 * Registers the item if no item of that name already exists.
@@ -506,4 +519,14 @@ class _WP_Dependency {
 		return true;
 	}
 
+	function add_deps( $deps ) {
+		if ( is_string( $deps ) ) {
+			$deps = array( $deps );
+		}
+		if ( !is_array( $deps ) ) {
+			return false;
+		}
+		$this->deps = array_merge( $this->deps, $deps );
+		return true;
+	}
 } // _WP_Dependencies
diff --git src/wp-includes/class.wp-scripts.php src/wp-includes/class.wp-scripts.php
index 89a9ec9..2083e58 100644
--- src/wp-includes/class.wp-scripts.php
+++ src/wp-includes/class.wp-scripts.php
@@ -104,6 +104,10 @@ class WP_Scripts extends WP_Dependencies {
 		$src = $this->registered[$handle]->src;
 
 		if ( $this->do_concat ) {
+			if ( 'inline' == $src ) {
+				$this->print_code .= $this->print_extra_script( $handle, false );
+				return true;
+			}
 			/**
 			 * Filter the script loader source.
 			 *
@@ -125,6 +129,11 @@ class WP_Scripts extends WP_Dependencies {
 		}
 
 		$this->print_extra_script( $handle );
+
+		if ( 'inline' == $src ) {
+			return true;
+		}
+
 		if ( !preg_match('|^(https?:)?//|', $src) && ! ( $this->content_url && 0 === strpos($src, $this->content_url) ) ) {
 			$src = $this->base_url . $src;
 		}
@@ -166,8 +175,11 @@ class WP_Scripts extends WP_Dependencies {
 
 			$l10n[$key] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8');
 		}
+		$literals = WP_JS_Literal::find( $l10n );
 
-		$script = "var $object_name = " . json_encode($l10n) . ';';
+		$this->add_deps_from_literals( $handle, $literals );
+
+		$script = "var $object_name = " . WP_JS_Literal::json_encode( $l10n, $literals ) . ';';
 
 		if ( !empty($after) )
 			$script .= "\n$after;";
@@ -180,6 +192,12 @@ class WP_Scripts extends WP_Dependencies {
 		return $this->add_data( $handle, 'data', $script );
 	}
 
+	private function add_deps_from_literals( $handle, $literals ) {
+		foreach( $literals as $literal ) {
+			$this->add_deps( $handle, $literal->get_deps() );
+		}
+	}
+
 	public function set_group( $handle, $recursion, $group = false ) {
 
 		if ( $this->registered[$handle]->args === 1 )
@@ -245,3 +263,66 @@ class WP_Scripts extends WP_Dependencies {
 		$this->ext_handles = '';
 	}
 }
+
+/**
+ * Represents a literal JS text, which should not be JSON-encoded
+ *
+ * Used when localizing a script to tell the script loader not to encode
+ * this specific values and to load any additional dependancies this piece
+ * of code might have.
+ */
+class WP_JS_Literal {
+	private $text;
+	private $deps;
+
+	public function __construct( $js_text, $deps = array() ) {
+		$this->text = $js_text;
+		if ( is_string( $deps ) ) {
+			$this->deps = array( $deps );
+		} elseif ( is_array( $deps ) ) {
+			$this->deps = $deps;
+		} else {
+			$deps = array();
+		}
+	}
+
+	public function get_text() {
+		return $this->text;
+	}
+
+	public function get_deps() {
+		return $this->deps;
+	}
+
+	static public function json_encode( $value, $literals = null ) {
+		if ( !$literals ) {
+			$literals = self::find( $value );
+		}
+		$encoded = json_encode( $value );
+		return self::replace_literals_with_their_texts( $literals, $encoded );
+	}
+
+	private static function replace_literals_with_their_texts( $literals, $json_encoded ) {
+		$replaces_from = array();
+		$replaces_to = array();
+		foreach( $literals as $literal ) {
+			$replaces_from[] = json_encode( $literal );
+			$replaces_to[] = $literal->get_text();
+		}
+		return str_replace( $replaces_from, $replaces_to, $json_encoded );
+	}
+
+	public static function find( $value ) {
+		if ( !is_array( $value ) && !is_object( $value ) ) {
+			return array();
+		}
+		if ( is_a( $value, 'WP_JS_Literal' ) ) {
+			return array( $value );
+		}
+		$literals = array();
+		foreach( $value as &$item ) {
+			$literals += self::find( $item );
+		}
+		return $literals;
+	}
+}
diff --git src/wp-includes/functions.wp-scripts.php src/wp-includes/functions.wp-scripts.php
index 4e3bda7..d194991 100644
--- src/wp-includes/functions.wp-scripts.php
+++ src/wp-includes/functions.wp-scripts.php
@@ -256,3 +256,8 @@ function wp_script_is( $handle, $list = 'enqueued' ) {
 
 	return (bool) $wp_scripts->query( $handle, $list );
 }
+
+function wp_js_make_literal( $js_text, $deps = array() ) {
+	$literal = new WP_JS_Literal( $js_text, $deps );
+	return $literal;
+}
diff --git src/wp-includes/l10n.php src/wp-includes/l10n.php
index ed5b224..92adbc9 100644
--- src/wp-includes/l10n.php
+++ src/wp-includes/l10n.php
@@ -289,6 +289,58 @@ function esc_html_x( $text, $context, $domain = 'default' ) {
 	return esc_html( translate_with_gettext_context( $text, $context, $domain ) );
 }
 
+function _n_js( $singular, $plural, $domain = 'default' ) {
+	return translate_plural_for_js( $singular, $plural, null, $domain );
+}
+
+function _nx_js( $singular, $plural, $context, $domain = 'default' ) {
+	return translate_plural_for_js( $singular, $plural, $context, $domain );
+}
+
+function translate_plural_for_js( $singular, $plural, $context, $domain ) {
+	$translations = get_translations_for_domain( $domain );
+	$entry = new Translation_Entry( array( 'singular' => $singular, 'plural' => $plural, 'context' => $context ) );
+	if ( $translated = $translations->translate_entry( $entry ) ) {
+		$js_translations = json_encode( $translated->translations );
+		$js_domain = esc_js( $domain );
+		return wp_js_make_literal( "wp.i18n.make_plural($js_translations, '$js_domain')", 'i18n-make-plural' );
+	} else {
+		$js_originals = json_encode( array( $singular, $plural ) );
+		return wp_js_make_literal( "wp.i18n.make_plural($js_originals)", 'i18n-make-plural' );
+	}
+}
+
+function wp_i18n_js_make_plural_defintion() {
+	$json_encoded_plural_info = wp_i18n_get_json_encoded_domains_plural_info();
+	return <<<JS
+window.wp = window.wp || {};
+window.wp.i18n = window.wp.i18n || {};
+wp.i18n.domains_plural_info = $json_encoded_plural_info;
+wp.i18n.english_plural_info = {nplurals: 2, choose: function(n) { return n != 1;}};
+wp.i18n.make_plural = function(translations, domain) {
+	var domain_plural_info = wp.i18n.domains_plural_info[domain] || wp.i18n.english_plural_info;
+	return function(n) {
+		var i = domain_plural_info['choose'](n);
+		if (typeof i === 'boolean') i = i ? 1 : 0;
+		return i >=0 && i < domain_plural_info['nplurals']? translations[i] : null;
+	}
+}
+JS;
+}
+
+function wp_i18n_get_json_encoded_domains_plural_info() {
+	global $l10n;
+	$domains_plural_info = array();
+	foreach( $l10n as $domain => $translations ) {
+		list( $nplurals, $expression ) = $translations->nplurals_and_expression();
+		$domains_plural_info[$domain] = array(
+			'nplurals' => $nplurals,
+			'choose' => wp_js_make_literal( "function(n) { return $expression; }" ),
+		);
+	}
+	return WP_JS_Literal::json_encode( $domains_plural_info );
+}
+
 /**
  * Retrieve the plural or single form based on the supplied amount.
  *
diff --git src/wp-includes/pomo/translations.php src/wp-includes/pomo/translations.php
index 5ad316c..16edc7f 100644
--- src/wp-includes/pomo/translations.php
+++ src/wp-includes/pomo/translations.php
@@ -142,7 +142,7 @@ class Gettext_Translations extends Translations {
 	 */
 	function gettext_select_plural_form($count) {
 		if (!isset($this->_gettext_select_plural_form) || is_null($this->_gettext_select_plural_form)) {
-			list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms'));
+			list( $nplurals, $expression ) = $this->nplurals_and_expression();
 			$this->_nplurals = $nplurals;
 			$this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression);
 		}
@@ -159,6 +159,11 @@ class Gettext_Translations extends Translations {
 		}
 	}
 
+	function nplurals_and_expression() {
+		$header = $this->get_header( 'Plural-Forms' );
+		return $this->nplurals_and_expression_from_header( $header );
+	}
+
 	/**
 	 * Makes a function, which will return the right translation index, according to the
 	 * plural forms header
@@ -229,9 +234,12 @@ endif;
 
 if ( !class_exists( 'NOOP_Translations' ) ):
 /**
- * Provides the same interface as Translations, but doesn't do anything
+ * Provides the same interface as Gettext_Translations, but doesn't do anything
+ *
+ * Used for domains without any translations to make sure we neither have special cases,
+ * nor look for translations on every translate call.
  */
-class NOOP_Translations {
+class NOOP_Translations extends Gettext_Translations {
 	var $entries = array();
 	var $headers = array();
 
diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php
index 154393f..54d6782 100644
--- src/wp-includes/script-loader.php
+++ src/wp-includes/script-loader.php
@@ -77,9 +77,12 @@ function wp_default_scripts( &$scripts ) {
 		'secure' => (string) ( 'https' === parse_url( site_url(), PHP_URL_SCHEME ) ),
 	) );
 
+	$scripts->add( 'i18n-make-plural', 'inline' );
+	$scripts->add_data( 'i18n-make-plural', 'data', wp_i18n_js_make_plural_defintion() );
+
 	$scripts->add( 'common', "/wp-admin/js/common$suffix.js", array('jquery', 'hoverIntent', 'utils'), false, 1 );
 	did_action( 'init' ) && $scripts->localize( 'common', 'commonL10n', array(
-		'warnDelete' => __("You are about to permanently delete the selected items.\n  'Cancel' to stop, 'OK' to delete.")
+		'warnDelete' => __("You are about to permanently delete the selected items.\n  'Cancel' to stop, 'OK' to delete."),
 	) );
 
 	$scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", array(), '1.6.1', 1 );
diff --git tests/phpunit/tests/dependencies.php tests/phpunit/tests/dependencies.php
index 5f9f579..d231805 100644
--- tests/phpunit/tests/dependencies.php
+++ tests/phpunit/tests/dependencies.php
@@ -136,4 +136,29 @@ class Tests_Dependencies extends WP_UnitTestCase {
 		$this->assertFalse( $dep->query( 'one' ) );
 
 	}
+
+	function test_add_deps_should_add_one_string_dep() {
+		$dep = new WP_Dependencies;
+		$dep->add( 'baba', '', array( 'dep0' ) );
+		$dep->add_deps( 'baba', 'new-dep' );
+		$this->assertEquals( array( 'dep0', 'new-dep' ), $dep->query( 'baba' )->deps );
+	}
+
+	function test_add_deps_should_merge_deps() {
+		$dep = new WP_Dependencies;
+		$dep->add( 'baba', '', array( 'dep0' ) );
+		$dep->add_deps( 'baba', array( 'new-dep', 'another-dep' ) );
+		$this->assertEquals( array( 'dep0', 'new-dep', 'another-dep' ), $dep->query( 'baba' )->deps );
+	}
+
+	function test_add_deps_should_return_false_on_non_string_non_array_deps() {
+		$dep = new WP_Dependencies;
+		$dep->add( 'baba', '', array( 'dep0' ) );
+		$this->assertFalse( $dep->add_deps( 'baba', 5 ) );
+	}
+
+	function test_add_deps_should_return_false_on_non_registered_handle() {
+		$dep = new WP_Dependencies;
+		$this->assertFalse( $dep->add_deps( 'baba', 'dep0' ) );
+	}
 }
