diff --git src/wp-includes/class-wp-locale-switcher.php src/wp-includes/class-wp-locale-switcher.php
new file mode 100644
index 0000000..d36db2b
--- /dev/null
+++ src/wp-includes/class-wp-locale-switcher.php
@@ -0,0 +1,218 @@
+<?php
+/**
+ * Locale switcher object.
+ *
+ * @package    WordPress
+ * @subpackage i18n
+ * @since      4.7.0
+ */
+
+/**
+ * Class for switching locales.
+ *
+ * @since 4.7.0
+ */
+class WP_Locale_Switcher {
+	/**
+	 * Locale stack.
+	 *
+	 * @since 4.7.0
+	 * @var string[]
+	 */
+	private $locales = array();
+
+	/**
+	 * Original locale.
+	 *
+	 * @since 4.7.0
+	 * @var string
+	 */
+	private $original_locale;
+
+	/**
+	 * Translation objects.
+	 *
+	 * @since 4.7.0
+	 * @var NOOP_Translations[][]
+	 */
+	private $translations = array();
+
+	/**
+	 * Holds all available languages.
+	 * @var array An array of language codes (file names without the .mo extension)
+	 */
+	private $available_languages = array();
+
+	/**
+	 * Constructor.
+	 *
+	 * Stores the original locale.
+	 *
+	 * @since 4.7.0
+	 */
+	public function __construct() {
+		$this->original_locale = get_locale();
+		$this->available_languages = get_available_languages();
+
+		add_filter( 'locale', array( $this, 'filter_locale' ) );
+	}
+
+	/**
+	 * Switches the translations according to the given locale.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @global Mo[]      $l10n      An array of available translations.
+	 * @global WP_Locale $wp_locale The WordPress date and time locale object.
+	 *
+	 * @param string $locale The locale.
+	 * @return bool True on success, false on failure.
+	 */
+	public function switch_to_locale( $locale ) {
+		global $l10n;
+
+		$current_locale = get_locale();
+
+		if ( $current_locale === $locale ) {
+			return false;
+		}
+
+		if ( ! in_array( $locale, $this->available_languages ) ) {
+			return false;
+		}
+
+		$GLOBALS['wp_locale'] = new WP_Locale();
+
+		$this->locales[] = $locale;
+
+		if ( null === $l10n ) {
+			$l10n = array();
+		}
+
+		if ( empty( $l10n ) ) {
+			load_default_textdomain();
+		}
+
+		if ( ! $this->has_translations_for_locale( $current_locale ) ) {
+			foreach ( array_keys( $l10n ) as $textdomain ) {
+				$this->translations[ $current_locale ][ $textdomain ] = get_translations_for_domain( $textdomain );
+			}
+		}
+
+		if ( $this->has_translations_for_locale( $locale ) ) {
+			foreach ( array_keys( $l10n ) as $textdomain ) {
+				if ( isset( $this->translations[ $locale ][ $textdomain ] ) ) {
+					$l10n[ $textdomain ] = $this->translations[ $locale ][ $textdomain ];
+				}
+			}
+		} else {
+			/* @var MO $mo */
+			foreach ( $l10n as $textdomain => $mo ) {
+				if ( 'default' === $textdomain ) {
+					load_default_textdomain();
+
+					continue;
+				}
+
+				unload_textdomain( $textdomain );
+
+				if ( $mofile = $mo->get_filename() ) {
+					load_textdomain( $textdomain, $mofile );
+				}
+
+				$this->translations[ $locale ][ $textdomain ] = get_translations_for_domain( $textdomain );
+			}
+		}
+
+		/**
+		 * Fires when the locale is switched.
+		 *
+		 * @since 4.7.0
+		 *
+		 * @param string $locale The new locale.
+		 */
+		do_action( 'switch_locale', $locale );
+
+		return true;
+	}
+
+	/**
+	 * Restores the translations according to the previous locale.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @global Mo[]      $l10n      An array of available translations.
+	 * @global WP_Locale $wp_locale The WordPress date and time locale object.
+	 *
+	 * @return string|false Locale on success, false on failure.
+	 */
+	public function restore_locale() {
+		global $l10n;
+
+		$previous_locale = end( $this->locales );
+
+		if ( ! array_pop( $this->locales ) ) {
+			// The stack is empty, bail.
+			return false;
+		}
+
+		if ( null === $l10n ) {
+			$l10n = array();
+		}
+
+		$locale = end( $this->locales );
+
+		if ( ! $locale ) {
+			// There's nothing left in the stack: go back to the original locale.
+			$locale = $this->original_locale;
+		}
+
+		foreach ( array_keys( $l10n ) as $textdomain ) {
+			if ( isset( $this->translations[ $locale ][ $textdomain ] ) ) {
+				$l10n[ $textdomain ] = $this->translations[ $locale ][ $textdomain ];
+			}
+		}
+
+		$GLOBALS['wp_locale'] = new WP_Locale();
+
+		/**
+		 * Fires when the locale is restored to the previous one.
+		 *
+		 * @since 4.7.0
+		 *
+		 * @param string $locale The new locale.
+		 * @param string $previous_locale The previous locale.
+		 */
+		do_action( 'restore_locale', $locale, $previous_locale );
+
+		return $locale;
+	}
+
+	/**
+	 * Filters the WordPress install's locale.
+	 *
+	 * @param string $locale The WordPress install's locale.
+	 * @return string The locale currently being switched to.
+	 */
+	public function filter_locale( $locale ) {
+		$switched_locale = end( $this->locales );
+
+		if ( $switched_locale ) {
+			return $switched_locale;
+		}
+
+		return $locale;
+	}
+
+	/**
+	 * Checks if there are cached translations for the given locale.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @param string $locale The locale.
+	 * @return bool True if there are cached translations for the given locale, false otherwise.
+	 */
+	private function has_translations_for_locale( $locale ) {
+		return ! empty( $this->translations[ $locale ] );
+	}
+}
diff --git src/wp-includes/l10n.php src/wp-includes/l10n.php
index aaa7611..d253fa6 100644
--- src/wp-includes/l10n.php
+++ src/wp-includes/l10n.php
@@ -1148,4 +1148,37 @@ function is_rtl() {
 		return false;
 	}
 	return $wp_locale->is_rtl();
-}
\ No newline at end of file
+}
+
+/**
+ * Switches the translations according to the given locale.
+ *
+ * @since 4.7.0
+ *
+ * @global WP_Locale_Switcher $wp_locale_switcher
+ *
+ * @param string $locale The locale.
+ * @return bool True on success, false on failure.
+ */
+function switch_to_locale( $locale ) {
+	/* @var WP_Locale_Switcher $wp_locale_switcher */
+	global $wp_locale_switcher;
+
+	return $wp_locale_switcher->switch_to_locale( $locale );
+}
+
+/**
+ * Restores the translations according to the previous locale.
+ *
+ * @since 4.7.0
+ *
+ * @global WP_Locale_Switcher $wp_locale_switcher
+ *
+ * @return string|false Locale on success, false on error.
+ */
+function restore_locale() {
+	/* @var WP_Locale_Switcher $wp_locale_switcher */
+	global $wp_locale_switcher;
+
+	return $wp_locale_switcher->restore_locale();
+}
diff --git src/wp-includes/load.php src/wp-includes/load.php
index ae32c7a..6084c00 100644
--- src/wp-includes/load.php
+++ src/wp-includes/load.php
@@ -868,6 +868,7 @@ function wp_load_translations_early() {
 	require_once ABSPATH . WPINC . '/pomo/mo.php';
 	require_once ABSPATH . WPINC . '/l10n.php';
 	require_once ABSPATH . WPINC . '/class-wp-locale.php';
+	require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php';
 
 	// General libraries
 	require_once ABSPATH . WPINC . '/plugin.php';
diff --git src/wp-includes/pomo/mo.php src/wp-includes/pomo/mo.php
index 6bc44d6..6188a7a 100644
--- src/wp-includes/pomo/mo.php
+++ src/wp-includes/pomo/mo.php
@@ -16,15 +16,39 @@ class MO extends Gettext_Translations {
 	var $_nplurals = 2;
 
 	/**
+	 * Loaded MO file.
+	 *
+	 * @since 4.7.0
+	 * @var string
+	 */
+	private $filename = '';
+
+	/**
+	 * Returns the loaded MO file.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @return string The loaded MO file.
+	 */
+	public function get_filename() {
+		return $this->filename;
+	}
+
+	/**
 	 * Fills up with the entries from MO file $filename
 	 *
 	 * @param string $filename MO file to load
 	 */
 	function import_from_file($filename) {
-		$reader = new POMO_FileReader($filename);
-		if (!$reader->is_resource())
+		$reader = new POMO_FileReader( $filename );
+
+		if ( ! $reader->is_resource() ) {
 			return false;
-		return $this->import_from_reader($reader);
+		}
+
+		$this->filename = (string) $filename;
+
+		return $this->import_from_reader( $reader );
 	}
 
 	/**
@@ -299,4 +323,4 @@ class MO extends Gettext_Translations {
 		return $this->_nplurals;
 	}
 }
-endif;
\ No newline at end of file
+endif;
diff --git src/wp-settings.php src/wp-settings.php
index 80f556c..ccf0396 100644
--- src/wp-settings.php
+++ src/wp-settings.php
@@ -131,6 +131,7 @@ if ( SHORTINIT )
 // Load the L10n library.
 require_once( ABSPATH . WPINC . '/l10n.php' );
 require_once( ABSPATH . WPINC . '/class-wp-locale.php' );
+require_once( ABSPATH . WPINC . '/class-wp-locale-switcher.php' );
 
 // Run the installer if WordPress is not installed.
 wp_not_installed();
@@ -384,6 +385,15 @@ unset( $locale_file );
  */
 $GLOBALS['wp_locale'] = new WP_Locale();
 
+/**
+ * WordPress Locale Switcher object for switching locales.
+ *
+ * @since 4.7.0
+ *
+ * @global WP_Locale_Switcher $wp_locale_switcher
+ */
+$GLOBALS['wp_locale_switcher'] = new WP_Locale_Switcher();
+
 // Load the functions for the active theme, for both parent and child theme if applicable.
 if ( ! wp_installing() || 'wp-activate.php' === $pagenow ) {
 	if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) )
diff --git tests/phpunit/tests/l10n/localeSwitcher.php tests/phpunit/tests/l10n/localeSwitcher.php
new file mode 100644
index 0000000..30fc24d
--- /dev/null
+++ tests/phpunit/tests/l10n/localeSwitcher.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @group l10n
+ * @group i18n
+ */
+class Tests_Locale_Switcher extends WP_UnitTestCase {
+	function test_switch_to_non_existent_locale_returns_false() {
+		$this->assertFalse( switch_to_locale( 'de_DE' ) );
+	}
+
+	function test_switch_to_non_existent_locale_does_not_change_locale() {
+		switch_to_locale( 'de_DE' );
+
+		$this->assertSame( 'en_US', get_locale() );
+	}
+
+	function test_switch_to_locale_returns_true() {
+		$expected = switch_to_locale( 'en_GB' );
+
+		// Cleanup.
+		restore_locale();
+
+		$this->assertTrue( $expected );
+	}
+
+	function test_switch_to_locale_changes_the_locale() {
+		switch_to_locale( 'en_GB' );
+
+		$locale = get_locale();
+
+		// Cleanup.
+		restore_locale();
+
+		$this->assertSame( 'en_GB', $locale );
+	}
+
+	function test_switch_to_locale_loads_translation() {
+		switch_to_locale( 'es_ES' );
+
+		$actual = __( 'Invalid parameter.' );
+
+		// Cleanup.
+		restore_locale();
+
+		$this->assertSame( 'Parámetro no válido. ', $actual );
+	}
+
+	function test_restore_locale_without_switching() {
+		$this->assertFalse( restore_locale() );
+	}
+
+	function test_restore_locale_changes_the_locale_back() {
+		switch_to_locale( 'en_GB' );
+
+		// Cleanup.
+		restore_locale();
+
+		$this->assertSame( 'en_US', get_locale() );
+	}
+
+	function test_switch_to_locale_multiple_times() {
+		switch_to_locale( 'en_GB' );
+		switch_to_locale( 'es_ES' );
+		$locale = get_locale();
+
+		// Cleanup.
+		restore_locale();
+		restore_locale();
+
+		$this->assertSame( 'es_ES', $locale );
+	}
+
+	function test_restore_locale_after_switching_multiple_times() {
+		switch_to_locale( 'en_GB' );
+		switch_to_locale( 'es_ES' );
+		restore_locale();
+
+		$locale = get_locale();
+
+		// Cleanup.
+		restore_locale();
+
+		$this->assertSame( 'en_GB', $locale );
+	}
+
+	function test_restore_locale_restores_translation() {
+		switch_to_locale( 'es_ES' );
+		restore_locale();
+
+		$actual = __( 'Invalid parameter.' );
+
+		$this->assertSame( 'Invalid parameter.', $actual );
+	}
+}
