diff --git a/src/wp-includes/class-wp-locale.php b/src/wp-includes/class-wp-locale.php
index 287914e880..a12b2ce26c 100644
--- a/src/wp-includes/class-wp-locale.php
+++ b/src/wp-includes/class-wp-locale.php
@@ -127,22 +127,22 @@ class WP_Locale {
 		$this->weekday[6] = /* translators: weekday */ __( 'Saturday' );
 
 		// The first letter of each day.
-		$this->weekday_initial[ __( 'Sunday' ) ]    = /* translators: one-letter abbreviation of the weekday */ _x( 'S', 'Sunday initial' );
-		$this->weekday_initial[ __( 'Monday' ) ]    = /* translators: one-letter abbreviation of the weekday */ _x( 'M', 'Monday initial' );
-		$this->weekday_initial[ __( 'Tuesday' ) ]   = /* translators: one-letter abbreviation of the weekday */ _x( 'T', 'Tuesday initial' );
-		$this->weekday_initial[ __( 'Wednesday' ) ] = /* translators: one-letter abbreviation of the weekday */ _x( 'W', 'Wednesday initial' );
-		$this->weekday_initial[ __( 'Thursday' ) ]  = /* translators: one-letter abbreviation of the weekday */ _x( 'T', 'Thursday initial' );
-		$this->weekday_initial[ __( 'Friday' ) ]    = /* translators: one-letter abbreviation of the weekday */ _x( 'F', 'Friday initial' );
-		$this->weekday_initial[ __( 'Saturday' ) ]  = /* translators: one-letter abbreviation of the weekday */ _x( 'S', 'Saturday initial' );
+		$this->weekday_initial[ (string) $this->weekday[0] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'S', 'Sunday initial' );
+		$this->weekday_initial[ (string) $this->weekday[1] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'M', 'Monday initial' );
+		$this->weekday_initial[ (string) $this->weekday[2] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'T', 'Tuesday initial' );
+		$this->weekday_initial[ (string) $this->weekday[3] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'W', 'Wednesday initial' );
+		$this->weekday_initial[ (string) $this->weekday[4] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'T', 'Thursday initial' );
+		$this->weekday_initial[ (string) $this->weekday[5] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'F', 'Friday initial' );
+		$this->weekday_initial[ (string) $this->weekday[6] ] = /* translators: one-letter abbreviation of the weekday */ _x( 'S', 'Saturday initial' );
 
 		// Abbreviations for each day.
-		$this->weekday_abbrev[ __( 'Sunday' ) ]    = /* translators: three-letter abbreviation of the weekday */ __( 'Sun' );
-		$this->weekday_abbrev[ __( 'Monday' ) ]    = /* translators: three-letter abbreviation of the weekday */ __( 'Mon' );
-		$this->weekday_abbrev[ __( 'Tuesday' ) ]   = /* translators: three-letter abbreviation of the weekday */ __( 'Tue' );
-		$this->weekday_abbrev[ __( 'Wednesday' ) ] = /* translators: three-letter abbreviation of the weekday */ __( 'Wed' );
-		$this->weekday_abbrev[ __( 'Thursday' ) ]  = /* translators: three-letter abbreviation of the weekday */ __( 'Thu' );
-		$this->weekday_abbrev[ __( 'Friday' ) ]    = /* translators: three-letter abbreviation of the weekday */ __( 'Fri' );
-		$this->weekday_abbrev[ __( 'Saturday' ) ]  = /* translators: three-letter abbreviation of the weekday */ __( 'Sat' );
+		$this->weekday_abbrev[ (string) $this->weekday[0] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Sun' );
+		$this->weekday_abbrev[ (string) $this->weekday[1] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Mon' );
+		$this->weekday_abbrev[ (string) $this->weekday[2] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Tue' );
+		$this->weekday_abbrev[ (string) $this->weekday[3] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Wed' );
+		$this->weekday_abbrev[ (string) $this->weekday[4] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Thu' );
+		$this->weekday_abbrev[ (string) $this->weekday[5] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Fri' );
+		$this->weekday_abbrev[ (string) $this->weekday[6] ] = /* translators: three-letter abbreviation of the weekday */ __( 'Sat' );
 
 		// The Months
 		$this->month['01'] = /* translators: month name */ __( 'January' );
@@ -173,18 +173,18 @@ class WP_Locale {
 		$this->month_genitive['12'] = /* translators: month name, genitive */ _x( 'December', 'genitive' );
 
 		// Abbreviations for each month.
-		$this->month_abbrev[ __( 'January' ) ]   = /* translators: three-letter abbreviation of the month */ _x( 'Jan', 'January abbreviation' );
-		$this->month_abbrev[ __( 'February' ) ]  = /* translators: three-letter abbreviation of the month */ _x( 'Feb', 'February abbreviation' );
-		$this->month_abbrev[ __( 'March' ) ]     = /* translators: three-letter abbreviation of the month */ _x( 'Mar', 'March abbreviation' );
-		$this->month_abbrev[ __( 'April' ) ]     = /* translators: three-letter abbreviation of the month */ _x( 'Apr', 'April abbreviation' );
-		$this->month_abbrev[ __( 'May' ) ]       = /* translators: three-letter abbreviation of the month */ _x( 'May', 'May abbreviation' );
-		$this->month_abbrev[ __( 'June' ) ]      = /* translators: three-letter abbreviation of the month */ _x( 'Jun', 'June abbreviation' );
-		$this->month_abbrev[ __( 'July' ) ]      = /* translators: three-letter abbreviation of the month */ _x( 'Jul', 'July abbreviation' );
-		$this->month_abbrev[ __( 'August' ) ]    = /* translators: three-letter abbreviation of the month */ _x( 'Aug', 'August abbreviation' );
-		$this->month_abbrev[ __( 'September' ) ] = /* translators: three-letter abbreviation of the month */ _x( 'Sep', 'September abbreviation' );
-		$this->month_abbrev[ __( 'October' ) ]   = /* translators: three-letter abbreviation of the month */ _x( 'Oct', 'October abbreviation' );
-		$this->month_abbrev[ __( 'November' ) ]  = /* translators: three-letter abbreviation of the month */ _x( 'Nov', 'November abbreviation' );
-		$this->month_abbrev[ __( 'December' ) ]  = /* translators: three-letter abbreviation of the month */ _x( 'Dec', 'December abbreviation' );
+		$this->month_abbrev[ (string) $this->month['01'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Jan', 'January abbreviation' );
+		$this->month_abbrev[ (string) $this->month['02'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Feb', 'February abbreviation' );
+		$this->month_abbrev[ (string) $this->month['03'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Mar', 'March abbreviation' );
+		$this->month_abbrev[ (string) $this->month['04'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Apr', 'April abbreviation' );
+		$this->month_abbrev[ (string) $this->month['05'] ] = /* translators: three-letter abbreviation of the month */ _x( 'May', 'May abbreviation' );
+		$this->month_abbrev[ (string) $this->month['06'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Jun', 'June abbreviation' );
+		$this->month_abbrev[ (string) $this->month['07'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Jul', 'July abbreviation' );
+		$this->month_abbrev[ (string) $this->month['08'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Aug', 'August abbreviation' );
+		$this->month_abbrev[ (string) $this->month['09'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Sep', 'September abbreviation' );
+		$this->month_abbrev[ (string) $this->month['10'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Oct', 'October abbreviation' );
+		$this->month_abbrev[ (string) $this->month['11'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Nov', 'November abbreviation' );
+		$this->month_abbrev[ (string) $this->month['12'] ] = /* translators: three-letter abbreviation of the month */ _x( 'Dec', 'December abbreviation' );
 
 		// The Meridiems
 		$this->meridiem['am'] = __( 'am' );
@@ -196,7 +196,7 @@ class WP_Locale {
 		// See https://secure.php.net/number_format
 
 		/* translators: $thousands_sep argument for https://secure.php.net/number_format, default is , */
-		$thousands_sep = __( 'number_format_thousands_sep' );
+		$thousands_sep = (string) __( 'number_format_thousands_sep' );
 
 		if ( version_compare( PHP_VERSION, '5.4', '>=' ) ) {
 			// Replace space with a non-breaking space to avoid wrapping.
@@ -209,7 +209,7 @@ class WP_Locale {
 		$this->number_format['thousands_sep'] = ( 'number_format_thousands_sep' === $thousands_sep ) ? ',' : $thousands_sep;
 
 		/* translators: $dec_point argument for https://secure.php.net/number_format, default is . */
-		$decimal_point = __( 'number_format_decimal_point' );
+		$decimal_point = (string) __( 'number_format_decimal_point' );
 
 		$this->number_format['decimal_point'] = ( 'number_format_decimal_point' === $decimal_point ) ? '.' : $decimal_point;
 
@@ -250,7 +250,7 @@ class WP_Locale {
 	 * @return string Full translated weekday.
 	 */
 	public function get_weekday( $weekday_number ) {
-		return $this->weekday[ $weekday_number ];
+		return $this->weekday[ (string) $weekday_number ];
 	}
 
 	/**
@@ -267,7 +267,7 @@ class WP_Locale {
 	 * @return string Translated weekday initial.
 	 */
 	public function get_weekday_initial( $weekday_name ) {
-		return $this->weekday_initial[ $weekday_name ];
+		return $this->weekday_initial[ (string) $weekday_name ];
 	}
 
 	/**
@@ -282,7 +282,7 @@ class WP_Locale {
 	 * @return string Translated weekday abbreviation.
 	 */
 	public function get_weekday_abbrev( $weekday_name ) {
-		return $this->weekday_abbrev[ $weekday_name ];
+		return $this->weekday_abbrev[ (string) $weekday_name ];
 	}
 
 	/**
@@ -317,7 +317,7 @@ class WP_Locale {
 	 * @return string Translated abbreviated month.
 	 */
 	public function get_month_abbrev( $month_name ) {
-		return $this->month_abbrev[ $month_name ];
+		return $this->month_abbrev[ (string) $month_name ];
 	}
 
 	/**
@@ -331,7 +331,7 @@ class WP_Locale {
 	 * @return string Translated version
 	 */
 	public function get_meridiem( $meridiem ) {
-		return $this->meridiem[ $meridiem ];
+		return $this->meridiem[ (string) $meridiem ];
 	}
 
 	/**
diff --git a/src/wp-includes/comment-template.php b/src/wp-includes/comment-template.php
index d0bdba5024..0bf35b905e 100644
--- a/src/wp-includes/comment-template.php
+++ b/src/wp-includes/comment-template.php
@@ -906,7 +906,7 @@ function get_comments_number_text( $zero = false, $one = false, $more = false )
 			/* translators: If comment number in your language requires declension,
 			 * translate this to 'on'. Do not translate into your own language.
 			 */
-			if ( 'on' === _x( 'off', 'Comment number declension: on or off' ) ) {
+			if ( 'on' === (string) _x( 'off', 'Comment number declension: on or off' ) ) {
 				$text = preg_replace( '#<span class="screen-reader-text">.+?</span>#', '', $more );
 				$text = preg_replace( '/&.+?;/', '', $text ); // Kill entities
 				$text = trim( strip_tags( $text ), '% ' );
diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
index f3070315f6..2640eaf44c 100644
--- a/src/wp-includes/functions.php
+++ b/src/wp-includes/functions.php
@@ -218,7 +218,7 @@ function wp_maybe_decline_date( $date ) {
 	/* translators: If months in your language require a genitive case,
 	 * translate this to 'on'. Do not translate into your own language.
 	 */
-	if ( 'on' === _x( 'off', 'decline months names: on or off' ) ) {
+	if ( 'on' === (string) _x( 'off', 'decline months names: on or off' ) ) {
 		// Match a format like 'j F Y' or 'j. F'
 		if ( @preg_match( '#^\d{1,2}\.? [^\d ]+#u', $date ) ) {
 			$months          = $wp_locale->month;
@@ -2915,7 +2915,7 @@ function wp_die( $message = '', $title = '', $args = array() ) {
 		$function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
 	}
 
-	call_user_func( $function, $message, $title, $args );
+	call_user_func( $function, $message instanceof WP_String_Proxy ? (string) $message : $message, $title, $args );
 }
 
 /**
diff --git a/src/wp-includes/l10n.php b/src/wp-includes/l10n.php
index 081f2cf7db..eaff94aee4 100644
--- a/src/wp-includes/l10n.php
+++ b/src/wp-includes/l10n.php
@@ -192,14 +192,15 @@ function translate_with_gettext_context( $text, $context, $domain = 'default' )
  * If there is no translation, or the text domain isn't loaded, the original text is returned.
  *
  * @since 2.1.0
+ * @since 5.0.0 Returns a lazily-translating proxy object.
  *
  * @param string $text   Text to translate.
  * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
  *                       Default 'default'.
- * @return string Translated text.
+ * @return WP_String_Proxy Proxy object representing a string.
  */
 function __( $text, $domain = 'default' ) {
-	return translate( $text, $domain );
+	return new WP_Translation_Proxy( $text, $domain );
 }
 
 /**
@@ -208,14 +209,17 @@ function __( $text, $domain = 'default' ) {
  * If there is no translation, or the text domain isn't loaded, the original text is returned.
  *
  * @since 2.8.0
+ * @since 5.0.0 Returns a lazily-translating proxy object.
  *
  * @param string $text   Text to translate.
  * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
  *                       Default 'default'.
- * @return string Translated text on success, original text on failure.
+ * @return WP_String_Proxy Proxy object representing a string.
  */
 function esc_attr__( $text, $domain = 'default' ) {
-	return esc_attr( translate( $text, $domain ) );
+	return new WP_Escape_Attribute_Proxy(
+		new WP_Translation_Proxy( $text, $domain )
+	);
 }
 
 /**
@@ -225,14 +229,17 @@ function esc_attr__( $text, $domain = 'default' ) {
  * is escaped and returned.
  *
  * @since 2.8.0
+ * @since 5.0.0 Returns a lazily-translating proxy object.
  *
  * @param string $text   Text to translate.
  * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
  *                       Default 'default'.
- * @return string Translated text
+ * @return WP_String_Proxy Proxy object representing a string.
  */
 function esc_html__( $text, $domain = 'default' ) {
-	return esc_html( translate( $text, $domain ) );
+	return new WP_Escape_HTML_Proxy(
+		new WP_Translation_Proxy( $text, $domain )
+	);
 }
 
 /**
@@ -284,15 +291,16 @@ function esc_html_e( $text, $domain = 'default' ) {
  * strings differently.
  *
  * @since 2.8.0
+ * @since 5.0.0 Returns a lazily-translating proxy object.
  *
  * @param string $text    Text to translate.
  * @param string $context Context information for the translators.
  * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
  *                        Default 'default'.
- * @return string Translated context string without pipe.
+ * @return WP_String_Proxy Proxy object representing a string.
  */
 function _x( $text, $context, $domain = 'default' ) {
-	return translate_with_gettext_context( $text, $context, $domain );
+	return new WP_Contextual_Translation_Proxy( $text, $context, $domain );
 }
 
 /**
@@ -314,30 +322,36 @@ function _ex( $text, $context, $domain = 'default' ) {
  * Translate string with gettext context, and escapes it for safe use in an attribute.
  *
  * @since 2.8.0
+ * @since 5.0.0 Returns a lazily-translating proxy object.
  *
  * @param string $text    Text to translate.
  * @param string $context Context information for the translators.
  * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
  *                        Default 'default'.
- * @return string Translated text
+ * @return WP_String_Proxy Proxy object representing a string.
  */
 function esc_attr_x( $text, $context, $domain = 'default' ) {
-	return esc_attr( translate_with_gettext_context( $text, $context, $domain ) );
+	return new WP_Escape_Attribute_Proxy(
+		new WP_Contextual_Translation_Proxy( $text, $context, $domain )
+	);
 }
 
 /**
  * Translate string with gettext context, and escapes it for safe use in HTML output.
  *
  * @since 2.9.0
+ * @since 5.0.0 Returns a lazily-translating proxy object.
  *
  * @param string $text    Text to translate.
  * @param string $context Context information for the translators.
  * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
  *                        Default 'default'.
- * @return string Translated text.
+ * @return WP_String_Proxy Proxy object representing a string.
  */
 function esc_html_x( $text, $context, $domain = 'default' ) {
-	return esc_html( translate_with_gettext_context( $text, $context, $domain ) );
+	return new WP_Escape_HTML_Proxy(
+		new WP_Contextual_Translation_Proxy( $text, $context, $domain )
+	);
 }
 
 /**
diff --git a/src/wp-includes/l10n/class-wp-contextual-translation-proxy.php b/src/wp-includes/l10n/class-wp-contextual-translation-proxy.php
new file mode 100644
index 0000000000..02707c9289
--- /dev/null
+++ b/src/wp-includes/l10n/class-wp-contextual-translation-proxy.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * L10n: WP_Contextual_Translation_Proxy class.
+ *
+ * @package    WordPress
+ * @subpackage L10n
+ * @since      5.0.0
+ */
+final class WP_Contextual_Translation_Proxy extends WP_String_Proxy {
+
+	private $text;
+	private $context;
+	private $domain;
+
+	/**
+	 * Instantiate a WP_Translation_Proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param string $text    Text to translate.
+	 * @param string $context Context of the test to translate.
+	 * @param string $domain  Optional. Text domain to use for the translation.
+	 */
+	public function __construct( $text, $context, $domain = 'default' ) {
+		$this->text    = $text;
+		$this->context = $context;
+		$this->domain  = $domain;
+	}
+
+	/**
+	 * Get the result of evaluating the string proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	protected function get_result() {
+		return translate_with_gettext_context(
+			$this->text,
+			$this->context,
+			$this->domain
+		);
+	}
+}
diff --git a/src/wp-includes/l10n/class-wp-escape-attribute-proxy.php b/src/wp-includes/l10n/class-wp-escape-attribute-proxy.php
new file mode 100644
index 0000000000..1f1a895212
--- /dev/null
+++ b/src/wp-includes/l10n/class-wp-escape-attribute-proxy.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * L10n: WP_Escape_Attribute_Proxy class.
+ *
+ * @package    WordPress
+ * @subpackage L10n
+ * @since      5.0.0
+ */
+final class WP_Escape_Attribute_Proxy extends WP_String_Proxy {
+
+	private $value;
+
+	/**
+	 * Instantiate a WP_Translation_Proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param mixed $value Value to be escaped. Needs to be castable to a
+	 *                     string.
+	 */
+	public function __construct( $value ) {
+		$this->value = $value;
+	}
+
+	/**
+	 * Get the result of evaluating the string proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	protected function get_result() {
+		return esc_attr( (string) $this->value );
+	}
+}
diff --git a/src/wp-includes/l10n/class-wp-escape-html-proxy.php b/src/wp-includes/l10n/class-wp-escape-html-proxy.php
new file mode 100644
index 0000000000..b77e94708b
--- /dev/null
+++ b/src/wp-includes/l10n/class-wp-escape-html-proxy.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * L10n: WP_Escape_HTML_Proxy class.
+ *
+ * @package    WordPress
+ * @subpackage L10n
+ * @since      5.0.0
+ */
+final class WP_Escape_HTML_Proxy extends WP_String_Proxy {
+
+	private $value;
+
+	/**
+	 * Instantiate a WP_Translation_Proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param mixed $value Value to be escaped. Needs to be castable to a
+	 *                     string.
+	 */
+	public function __construct( $value ) {
+		$this->value = $value;
+	}
+
+	/**
+	 * Get the result of evaluating the string proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	protected function get_result() {
+		return esc_html( (string) $this->value );
+	}
+}
diff --git a/src/wp-includes/l10n/class-wp-string-proxy.php b/src/wp-includes/l10n/class-wp-string-proxy.php
new file mode 100644
index 0000000000..a8094aa2a1
--- /dev/null
+++ b/src/wp-includes/l10n/class-wp-string-proxy.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * L10n: WP_String_Proxy class.
+ *
+ * Implements `JsonSerializable` interface so that it gets converted to a
+ * translated string on `json_encode()`.
+ *
+ * Implements the `ArrayAccess` interface so that you can directly access
+ * individual characters in the translated string
+ *
+ * Uses magic `__get()` to make sure the result is only generated once.
+ *
+ * @package    WordPress
+ * @subpackage L10n
+ * @since      5.0.0
+ */
+abstract class WP_String_Proxy implements JsonSerializable, ArrayAccess {
+
+	/** @var string|null */
+	private $result;
+
+	/**
+	 * Return the string representation of the proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	public function __toString() {
+		return $this->result();
+	}
+
+	/**
+	 * Return the JSON representation of the proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	public function jsonSerialize() {
+		return $this->result();
+	}
+
+	/**
+	 * Lazily evaluate the result the first time it is being requested.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	private function result() {
+		if ( null === $this->result ) {
+			$this->result = $this->get_result();
+		}
+
+		return $this->result;
+	}
+
+	/**
+	 * Check whether an offset into the array exists.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param mixed $offset Offset to check for.
+	 *
+	 * @return bool
+	 */
+	public function offsetExists( $offset ) {
+		return mb_strlen( $this->result() ) > $offset;
+	}
+
+	/**
+	 * Retrieve a specific offset into the array.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param mixed $offset The offset to retrieve.
+	 *
+	 * @return mixed
+	 */
+	public function offsetGet( $offset ) {
+		$this->result();
+
+		return $this->result[ $offset ];
+	}
+
+	/**
+	 * Set a specific offset in the array.
+	 *
+	 * @since 5.0.
+	 *
+	 * @param mixed $offset The offset to assign the value to.
+	 * @param mixed $value  The value to set the offset to.
+	 */
+	public function offsetSet( $offset, $value ) {
+		$this->result();
+		$this->result[ $offset ] = $value;
+	}
+
+	/**
+	 * Unset a specific offset in the array.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param mixed $offset The offset to unset.
+	 */
+	public function offsetUnset( $offset ) {
+		trigger_error( 'Cannot unset string offset', E_USER_ERROR );
+	}
+
+	/**
+	 * Get the result of evaluating the string proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	abstract protected function get_result();
+}
\ No newline at end of file
diff --git a/src/wp-includes/l10n/class-wp-translation-proxy.php b/src/wp-includes/l10n/class-wp-translation-proxy.php
new file mode 100644
index 0000000000..28b73e63f3
--- /dev/null
+++ b/src/wp-includes/l10n/class-wp-translation-proxy.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * L10n: WP_Translation_Proxy class.
+ *
+ * @package    WordPress
+ * @subpackage L10n
+ * @since      5.0.0
+ */
+final class WP_Translation_Proxy extends WP_String_Proxy {
+
+	private $text;
+	private $domain;
+
+	/**
+	 * Instantiate a WP_Translation_Proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param string $text   Text to translate.
+	 * @param string $domain Optional. Text domain to use for the translation.
+	 */
+	public function __construct( $text, $domain = 'default' ) {
+		$this->text   = $text;
+		$this->domain = $domain;
+	}
+
+	/**
+	 * Get the result of evaluating the string proxy object.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @return string
+	 */
+	protected function get_result() {
+		return translate( $this->text, $this->domain );
+	}
+}
diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php
index 79e445021b..4d85a99a0e 100644
--- a/src/wp-includes/load.php
+++ b/src/wp-includes/load.php
@@ -956,6 +956,11 @@ function wp_load_translations_early() {
 	require_once ABSPATH . WPINC . '/l10n.php';
 	require_once ABSPATH . WPINC . '/class-wp-locale.php';
 	require_once ABSPATH . WPINC . '/class-wp-locale-switcher.php';
+	require_once ABSPATH . WPINC . '/l10n/class-wp-string-proxy.php';
+	require_once ABSPATH . WPINC . '/l10n/class-wp-translation-proxy.php';
+	require_once ABSPATH . WPINC . '/l10n/class-wp-contextual-translation-proxy.php';
+	require_once ABSPATH . WPINC . '/l10n/class-wp-escape-attribute-proxy.php';
+	require_once ABSPATH . WPINC . '/l10n/class-wp-escape-html-proxy.php';
 
 	// General libraries
 	require_once ABSPATH . WPINC . '/plugin.php';
diff --git a/src/wp-includes/wp-db.php b/src/wp-includes/wp-db.php
index ae08158f64..f9e31d37cd 100644
--- a/src/wp-includes/wp-db.php
+++ b/src/wp-includes/wp-db.php
@@ -1313,7 +1313,7 @@ class wpdb {
 		}
 
 		foreach ( $args as $arg ) {
-			if ( ! is_scalar( $arg ) && ! is_null( $arg ) ) {
+			if ( ! is_scalar( $arg ) && ! is_null( $arg ) && ! $arg instanceof WP_String_Proxy) {
 				wp_load_translations_early();
 				_doing_it_wrong( 'wpdb::prepare', sprintf( __( 'Unsupported value type (%s).' ), gettype( $arg ) ), '4.8.2' );
 			}
diff --git a/src/wp-settings.php b/src/wp-settings.php
index eb632238f0..5b0794cf91 100644
--- a/src/wp-settings.php
+++ b/src/wp-settings.php
@@ -137,6 +137,11 @@ if ( SHORTINIT ) {
 
 // Load the L10n library.
 require_once( ABSPATH . WPINC . '/l10n.php' );
+require_once( ABSPATH . WPINC . '/l10n/class-wp-string-proxy.php' );
+require_once( ABSPATH . WPINC . '/l10n/class-wp-translation-proxy.php' );
+require_once( ABSPATH . WPINC . '/l10n/class-wp-contextual-translation-proxy.php' );
+require_once( ABSPATH . WPINC . '/l10n/class-wp-escape-attribute-proxy.php' );
+require_once( ABSPATH . WPINC . '/l10n/class-wp-escape-html-proxy.php' );
 require_once( ABSPATH . WPINC . '/class-wp-locale.php' );
 require_once( ABSPATH . WPINC . '/class-wp-locale-switcher.php' );
 
diff --git a/tests/phpunit/data/plugins/internationalized-plugin.php b/tests/phpunit/data/plugins/internationalized-plugin.php
index 4b56846ad3..2362cf6180 100644
--- a/tests/phpunit/data/plugins/internationalized-plugin.php
+++ b/tests/phpunit/data/plugins/internationalized-plugin.php
@@ -8,5 +8,5 @@ Text Domain: internationalized-plugin
 */
 
 function i18n_plugin_test() {
-	return __( 'This is a dummy plugin', 'internationalized-plugin' );
+	return (string) __( 'This is a dummy plugin', 'internationalized-plugin' );
 }
diff --git a/tests/phpunit/includes/testcase.php b/tests/phpunit/includes/testcase.php
index db3f0b9fb6..26fa83f75f 100644
--- a/tests/phpunit/includes/testcase.php
+++ b/tests/phpunit/includes/testcase.php
@@ -582,6 +582,112 @@ class WP_UnitTestCase extends PHPUnit_Framework_TestCase {
 	}
 
 	/**
+	 * Assert that two elements are equal.
+	 *
+	 * Override to handle special cases for equality checks.
+	 *
+	 * @since 5.0.0 Added WP_String_Proxy object <=> string equality.
+	 *
+	 * @param mixed  $expected
+	 * @param mixed  $actual
+	 * @param string $message
+	 * @param int    $delta
+	 * @param int    $maxDepth
+	 * @param bool   $canonicalize
+	 * @param bool   $ignoreCase
+	 */
+	public static function assertEquals( $expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false ) {
+		if ( is_array( $actual ) ) {
+			array_walk( $actual, 'WP_UnitTestCase::resolve_proxies', $expected );
+		}
+
+		$actual   = self::resolve_proxy( $actual );
+		$expected = self::resolve_proxy( $expected );
+
+		parent::assertEquals( $expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase );
+	}
+
+	/**
+	 * Resolve proxies in arrays to be tested.
+	 *
+	 * @since 5.0.0
+	 *
+	 * @param mixed  $value Reference to the array value to be checked.
+	 * @param string $key   Index key of the array value to be checked.
+	 */
+	protected static function resolve_proxies( &$value, $key ) {
+		if ( is_array( $value ) ) {
+			array_walk( $value, 'WP_UnitTestCase::resolve_proxies' );
+		}
+
+		$value = self::resolve_proxy( $value );
+	}
+
+	/**
+	 * Resolve an individual proxy.
+	 *
+	 * @since 0.1.0
+	 *
+	 * @param $value
+	 *
+	 * @return string
+	 */
+	protected static function resolve_proxy( $value ) {
+		if ( $value instanceof WP_String_Proxy ) {
+			return (string) $value;
+		}
+
+		return $value;
+	}
+
+	/**
+	 * Asserts that two variables have the same type and value.
+	 * Used on objects, it asserts that two variables reference
+	 * the same object.
+	 *
+	 * Override to handle special cases for equality checks.
+	 *
+	 * @since 5.0.0 Added WP_String_Proxy object <=> string equality.
+	 *
+	 * @param mixed  $expected
+	 * @param mixed  $actual
+	 * @param string $message
+	 */
+	public static function assertSame( $expected, $actual, $message = '' ) {
+		if ( is_array( $actual ) ) {
+			array_walk( $actual, 'WP_UnitTestCase::resolve_proxies' );
+		}
+
+		if ( is_array( $expected ) ) {
+			array_walk( $expected, 'WP_UnitTestCase::resolve_proxies' );
+		}
+
+		$actual   = self::resolve_proxy( $actual );
+		$expected = self::resolve_proxy( $expected );
+
+		parent::assertSame( $expected, $actual, $message );
+	}
+
+	/**
+	 * Asserts that a variable is of a given type.
+	 *
+	 * Override to handle special cases for equality checks.
+	 *
+	 * @since 5.0.0 Added WP_String_Proxy object <=> string equality.
+	 *
+	 * @param string $expected
+	 * @param mixed  $actual
+	 * @param string $message
+	 */
+	public static function assertInternalType( $expected, $actual, $message = '' ) {
+		if ( 'string' === $expected ) {
+			$actual = self::resolve_proxy( $actual );
+		}
+
+		parent::assertInternalType( $expected, $actual, $message );
+	}
+
+    /**
 	 * Sets the global state to as if a given URL has been requested.
 	 *
 	 * This sets:
diff --git a/tests/phpunit/tests/customize/nav-menus.php b/tests/phpunit/tests/customize/nav-menus.php
index e7387773ac..951d766fd9 100644
--- a/tests/phpunit/tests/customize/nav-menus.php
+++ b/tests/phpunit/tests/customize/nav-menus.php
@@ -390,7 +390,7 @@ class Test_WP_Customize_Nav_Menus extends WP_UnitTestCase {
 		$results = $menus->search_available_items_query(
 			array(
 				'pagenum' => 1,
-				's'       => $title,
+				's'       => (string) $title,
 			)
 		);
 		$this->assertCount( 1, $results );
diff --git a/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php b/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php
index 7fb85a5427..49c40d480c 100644
--- a/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php
+++ b/tests/phpunit/tests/l10n/loadTextdomainJustInTime.php
@@ -75,11 +75,11 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 		$expected_output             = i18n_plugin_test();
 		$is_textdomain_loaded_after  = is_textdomain_loaded( 'internationalized-plugin' );
 
-		remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
-
 		$this->assertFalse( $is_textdomain_loaded_before );
 		$this->assertSame( 'Das ist ein Dummy Plugin', $expected_output );
 		$this->assertTrue( $is_textdomain_loaded_after );
+
+		remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
 	}
 
 	/**
@@ -94,13 +94,14 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 
 		$is_textdomain_loaded_before = is_textdomain_loaded( 'internationalized-theme' );
 		$expected_output             = i18n_theme_test();
-		$is_textdomain_loaded_after  = is_textdomain_loaded( 'internationalized-theme' );
-
-		remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
 
 		$this->assertFalse( $is_textdomain_loaded_before );
 		$this->assertSame( 'Das ist ein Dummy Theme', $expected_output );
+
+		$is_textdomain_loaded_after  = is_textdomain_loaded( 'internationalized-theme' );
 		$this->assertTrue( $is_textdomain_loaded_after );
+
+		remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
 	}
 
 	/**
@@ -110,10 +111,11 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 		add_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
 		add_filter( 'override_load_textdomain', '__return_true' );
 		$translations = get_translations_for_domain( 'internationalized-plugin' );
-		remove_filter( 'override_load_textdomain', '__return_true' );
-		remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
 
 		$this->assertTrue( $translations instanceof NOOP_Translations );
+
+		remove_filter( 'override_load_textdomain', '__return_true' );
+		remove_filter( 'locale', array( $this, 'filter_set_locale_to_german' ) );
 	}
 
 	/**
@@ -163,9 +165,10 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 
 		switch_to_locale( 'de_DE' );
 		$expected = i18n_plugin_test();
-		restore_previous_locale();
 
 		$this->assertSame( 'Das ist ein Dummy Plugin', $expected );
+
+		restore_previous_locale();
 	}
 
 	/**
@@ -180,10 +183,10 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 		switch_to_locale( 'es_ES' );
 		$expected_es_ES = i18n_plugin_test();
 
-		restore_current_locale();
-
 		$this->assertSame( 'Das ist ein Dummy Plugin', $expected_de_DE );
 		$this->assertSame( 'This is a dummy plugin', $expected_es_ES );
+
+		restore_current_locale();
 	}
 
 	/**
@@ -196,11 +199,12 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 
 		switch_to_locale( 'de_DE' );
 		$expected = i18n_theme_test();
+
+		$this->assertSame( 'Das ist ein Dummy Theme', $expected );
+
 		restore_previous_locale();
 
 		switch_theme( WP_DEFAULT_THEME );
-
-		$this->assertSame( 'Das ist ein Dummy Theme', $expected );
 	}
 
 	/**
@@ -231,10 +235,10 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 
 		$expected = i18n_theme_test();
 
+		$this->assertSame( 'Das ist ein Dummy Theme', $expected );
+
 		set_current_screen( 'front' );
 		switch_theme( WP_DEFAULT_THEME );
-
-		$this->assertSame( 'Das ist ein Dummy Theme', $expected );
 	}
 
 	/**
@@ -245,16 +249,16 @@ class Tests_L10n_loadTextdomainJustInTime extends WP_UnitTestCase {
 
 		add_filter( 'locale', array( $this, '_filter_locale_count' ) );
 
-		__( 'Foo', $textdomain );
-		__( 'Bar', $textdomain );
-		__( 'Baz', $textdomain );
-		__( 'Foo Bar', $textdomain );
-		__( 'Foo Bar Baz', $textdomain );
-
-		remove_filter( 'locale', array( $this, '_filter_locale_count' ) );
+		$foo         = (string) __( 'Foo', $textdomain );
+		$bar         = (string) __( 'Bar', $textdomain );
+		$baz         = (string) __( 'Baz', $textdomain );
+		$foo_bar     = (string) __( 'Foo Bar', $textdomain );
+		$foo_bar_baz = (string) __( 'Foo Bar Baz', $textdomain );
 
 		$this->assertFalse( is_textdomain_loaded( $textdomain ) );
 		$this->assertSame( 1, $this->locale_count );
+
+		remove_filter( 'locale', array( $this, '_filter_locale_count' ) );
 	}
 
 	public function _filter_locale_count( $locale ) {
diff --git a/tests/phpunit/tests/l10n/localeSwitcher.php b/tests/phpunit/tests/l10n/localeSwitcher.php
index f100c8a1db..84190c1961 100644
--- a/tests/phpunit/tests/l10n/localeSwitcher.php
+++ b/tests/phpunit/tests/l10n/localeSwitcher.php
@@ -48,10 +48,10 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 	public function test_switch_to_locale_returns_true() {
 		$expected = switch_to_locale( 'en_GB' );
 
+		$this->assertTrue( $expected );
+
 		// Cleanup.
 		restore_previous_locale();
-
-		$this->assertTrue( $expected );
 	}
 
 	public function test_switch_to_locale_changes_the_locale() {
@@ -59,10 +59,10 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 
 		$locale = get_locale();
 
+		$this->assertSame( 'en_GB', $locale );
+
 		// Cleanup.
 		restore_previous_locale();
-
-		$this->assertSame( 'en_GB', $locale );
 	}
 
 	public function test_switch_to_locale_loads_translation() {
@@ -70,10 +70,10 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 
 		$actual = __( 'Invalid parameter.' );
 
+		$this->assertSame( 'Parámetro no válido. ', $actual );
+
 		// Cleanup.
 		restore_previous_locale();
-
-		$this->assertSame( 'Parámetro no válido. ', $actual );
 	}
 
 	public function test_switch_to_locale_changes_wp_locale_global() {
@@ -88,10 +88,10 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 
 		$wp_locale_de_DE = clone $wp_locale;
 
+		$this->assertEqualSetsWithIndex( $expected, $wp_locale_de_DE->number_format );
+
 		// Cleanup.
 		restore_previous_locale();
-
-		$this->assertEqualSetsWithIndex( $expected, $wp_locale_de_DE->number_format );
 	}
 
 	public function test_switch_to_locale_en_US() {
@@ -100,11 +100,11 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 		switch_to_locale( 'en_US' );
 		$locale_en_US = get_locale();
 
-		// Cleanup.
-		restore_current_locale();
-
 		$this->assertSame( 'en_GB', $locale_en_GB );
 		$this->assertSame( 'en_US', $locale_en_US );
+
+		// Cleanup.
+		restore_current_locale();
 	}
 
 	public function test_switch_to_locale_multiple_times() {
@@ -112,11 +112,11 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 		switch_to_locale( 'es_ES' );
 		$locale = get_locale();
 
+		$this->assertSame( 'es_ES', $locale );
+
 		// Cleanup.
 		restore_previous_locale();
 		restore_previous_locale();
-
-		$this->assertSame( 'es_ES', $locale );
 	}
 
 	public function test_switch_to_locale_multiple_times_loads_translation() {
@@ -126,12 +126,12 @@ class Tests_Locale_Switcher extends WP_UnitTestCase {
 
 		$actual = __( 'Invalid parameter.' );
 
+		$this->assertSame( 'Parámetro no válido. ', $actual );
+
 		// Cleanup.
 		restore_previous_locale();
 		restore_previous_locale();
 		restore_previous_locale();
-
-		$this->assertSame( 'Parámetro no válido. ', $actual );
 	}
 
 	public function test_restore_previous_locale_without_switching() {
diff --git a/tests/phpunit/tests/locale.php b/tests/phpunit/tests/locale.php
index 98a700509c..6ef9963223 100644
--- a/tests/phpunit/tests/locale.php
+++ b/tests/phpunit/tests/locale.php
@@ -20,13 +20,13 @@ class Tests_Locale extends WP_UnitTestCase {
 	}
 
 	public function test_get_weekday() {
-		$this->assertEquals( __( 'Sunday' ), $this->locale->get_weekday( 0 ) );
-		$this->assertEquals( __( 'Monday' ), $this->locale->get_weekday( 1 ) );
-		$this->assertEquals( __( 'Tuesday' ), $this->locale->get_weekday( 2 ) );
-		$this->assertEquals( __( 'Wednesday' ), $this->locale->get_weekday( 3 ) );
-		$this->assertEquals( __( 'Thursday' ), $this->locale->get_weekday( 4 ) );
-		$this->assertEquals( __( 'Friday' ), $this->locale->get_weekday( 5 ) );
-		$this->assertEquals( __( 'Saturday' ), $this->locale->get_weekday( 6 ) );
+		$this->assertEquals( (string) __( 'Sunday' ), $this->locale->get_weekday( 0 ) );
+		$this->assertEquals( (string) __( 'Monday' ), $this->locale->get_weekday( 1 ) );
+		$this->assertEquals( (string) __( 'Tuesday' ), $this->locale->get_weekday( 2 ) );
+		$this->assertEquals( (string) __( 'Wednesday' ), $this->locale->get_weekday( 3 ) );
+		$this->assertEquals( (string) __( 'Thursday' ), $this->locale->get_weekday( 4 ) );
+		$this->assertEquals( (string) __( 'Friday' ), $this->locale->get_weekday( 5 ) );
+		$this->assertEquals( (string) __( 'Saturday' ), $this->locale->get_weekday( 6 ) );
 	}
 
 	/**
@@ -37,72 +37,72 @@ class Tests_Locale extends WP_UnitTestCase {
 	}
 
 	public function test_get_weekday_initial() {
-		$this->assertEquals( __( 'S' ), $this->locale->get_weekday_initial( __( 'Sunday' ) ) );
-		$this->assertEquals( __( 'M' ), $this->locale->get_weekday_initial( __( 'Monday' ) ) );
-		$this->assertEquals( __( 'T' ), $this->locale->get_weekday_initial( __( 'Tuesday' ) ) );
-		$this->assertEquals( __( 'W' ), $this->locale->get_weekday_initial( __( 'Wednesday' ) ) );
-		$this->assertEquals( __( 'T' ), $this->locale->get_weekday_initial( __( 'Thursday' ) ) );
-		$this->assertEquals( __( 'F' ), $this->locale->get_weekday_initial( __( 'Friday' ) ) );
-		$this->assertEquals( __( 'S' ), $this->locale->get_weekday_initial( __( 'Saturday' ) ) );
+		$this->assertEquals( (string) __( 'S' ), $this->locale->get_weekday_initial( __( 'Sunday' ) ) );
+		$this->assertEquals( (string) __( 'M' ), $this->locale->get_weekday_initial( __( 'Monday' ) ) );
+		$this->assertEquals( (string) __( 'T' ), $this->locale->get_weekday_initial( __( 'Tuesday' ) ) );
+		$this->assertEquals( (string) __( 'W' ), $this->locale->get_weekday_initial( __( 'Wednesday' ) ) );
+		$this->assertEquals( (string) __( 'T' ), $this->locale->get_weekday_initial( __( 'Thursday' ) ) );
+		$this->assertEquals( (string) __( 'F' ), $this->locale->get_weekday_initial( __( 'Friday' ) ) );
+		$this->assertEquals( (string) __( 'S' ), $this->locale->get_weekday_initial( __( 'Saturday' ) ) );
 	}
 
 	public function test_get_weekday_abbrev() {
-		$this->assertEquals( __( 'Sun' ), $this->locale->get_weekday_abbrev( __( 'Sunday' ) ) );
-		$this->assertEquals( __( 'Mon' ), $this->locale->get_weekday_abbrev( __( 'Monday' ) ) );
-		$this->assertEquals( __( 'Tue' ), $this->locale->get_weekday_abbrev( __( 'Tuesday' ) ) );
-		$this->assertEquals( __( 'Wed' ), $this->locale->get_weekday_abbrev( __( 'Wednesday' ) ) );
-		$this->assertEquals( __( 'Thu' ), $this->locale->get_weekday_abbrev( __( 'Thursday' ) ) );
-		$this->assertEquals( __( 'Fri' ), $this->locale->get_weekday_abbrev( __( 'Friday' ) ) );
-		$this->assertEquals( __( 'Sat' ), $this->locale->get_weekday_abbrev( __( 'Saturday' ) ) );
+		$this->assertEquals( (string) __( 'Sun' ), $this->locale->get_weekday_abbrev( __( 'Sunday' ) ) );
+		$this->assertEquals( (string) __( 'Mon' ), $this->locale->get_weekday_abbrev( __( 'Monday' ) ) );
+		$this->assertEquals( (string) __( 'Tue' ), $this->locale->get_weekday_abbrev( __( 'Tuesday' ) ) );
+		$this->assertEquals( (string) __( 'Wed' ), $this->locale->get_weekday_abbrev( __( 'Wednesday' ) ) );
+		$this->assertEquals( (string) __( 'Thu' ), $this->locale->get_weekday_abbrev( __( 'Thursday' ) ) );
+		$this->assertEquals( (string) __( 'Fri' ), $this->locale->get_weekday_abbrev( __( 'Friday' ) ) );
+		$this->assertEquals( (string) __( 'Sat' ), $this->locale->get_weekday_abbrev( __( 'Saturday' ) ) );
 	}
 
 	public function test_get_month() {
-		$this->assertEquals( __( 'January' ), $this->locale->get_month( 1 ) );
-		$this->assertEquals( __( 'February' ), $this->locale->get_month( 2 ) );
-		$this->assertEquals( __( 'March' ), $this->locale->get_month( 3 ) );
-		$this->assertEquals( __( 'April' ), $this->locale->get_month( 4 ) );
-		$this->assertEquals( __( 'May' ), $this->locale->get_month( 5 ) );
-		$this->assertEquals( __( 'June' ), $this->locale->get_month( 6 ) );
-		$this->assertEquals( __( 'July' ), $this->locale->get_month( 7 ) );
-		$this->assertEquals( __( 'August' ), $this->locale->get_month( 8 ) );
-		$this->assertEquals( __( 'September' ), $this->locale->get_month( 9 ) );
-		$this->assertEquals( __( 'October' ), $this->locale->get_month( 10 ) );
-		$this->assertEquals( __( 'November' ), $this->locale->get_month( 11 ) );
-		$this->assertEquals( __( 'December' ), $this->locale->get_month( 12 ) );
+		$this->assertEquals( (string) __( 'January' ), $this->locale->get_month( 1 ) );
+		$this->assertEquals( (string) __( 'February' ), $this->locale->get_month( 2 ) );
+		$this->assertEquals( (string) __( 'March' ), $this->locale->get_month( 3 ) );
+		$this->assertEquals( (string) __( 'April' ), $this->locale->get_month( 4 ) );
+		$this->assertEquals( (string) __( 'May' ), $this->locale->get_month( 5 ) );
+		$this->assertEquals( (string) __( 'June' ), $this->locale->get_month( 6 ) );
+		$this->assertEquals( (string) __( 'July' ), $this->locale->get_month( 7 ) );
+		$this->assertEquals( (string) __( 'August' ), $this->locale->get_month( 8 ) );
+		$this->assertEquals( (string) __( 'September' ), $this->locale->get_month( 9 ) );
+		$this->assertEquals( (string) __( 'October' ), $this->locale->get_month( 10 ) );
+		$this->assertEquals( (string) __( 'November' ), $this->locale->get_month( 11 ) );
+		$this->assertEquals( (string) __( 'December' ), $this->locale->get_month( 12 ) );
 	}
 
 	public function test_get_month_leading_zero() {
-		$this->assertEquals( __( 'January' ), $this->locale->get_month( '01' ) );
-		$this->assertEquals( __( 'February' ), $this->locale->get_month( '02' ) );
-		$this->assertEquals( __( 'March' ), $this->locale->get_month( '03' ) );
-		$this->assertEquals( __( 'April' ), $this->locale->get_month( '04' ) );
-		$this->assertEquals( __( 'May' ), $this->locale->get_month( '05' ) );
-		$this->assertEquals( __( 'June' ), $this->locale->get_month( '06' ) );
-		$this->assertEquals( __( 'July' ), $this->locale->get_month( '07' ) );
-		$this->assertEquals( __( 'August' ), $this->locale->get_month( '08' ) );
-		$this->assertEquals( __( 'September' ), $this->locale->get_month( '09' ) );
+		$this->assertEquals( (string) __( 'January' ), $this->locale->get_month( '01' ) );
+		$this->assertEquals( (string) __( 'February' ), $this->locale->get_month( '02' ) );
+		$this->assertEquals( (string) __( 'March' ), $this->locale->get_month( '03' ) );
+		$this->assertEquals( (string) __( 'April' ), $this->locale->get_month( '04' ) );
+		$this->assertEquals( (string) __( 'May' ), $this->locale->get_month( '05' ) );
+		$this->assertEquals( (string) __( 'June' ), $this->locale->get_month( '06' ) );
+		$this->assertEquals( (string) __( 'July' ), $this->locale->get_month( '07' ) );
+		$this->assertEquals( (string) __( 'August' ), $this->locale->get_month( '08' ) );
+		$this->assertEquals( (string) __( 'September' ), $this->locale->get_month( '09' ) );
 	}
 
 	public function test_get_month_abbrev() {
-		$this->assertEquals( __( 'Jan' ), $this->locale->get_month_abbrev( __( 'January' ) ) );
-		$this->assertEquals( __( 'Feb' ), $this->locale->get_month_abbrev( __( 'February' ) ) );
-		$this->assertEquals( __( 'Mar' ), $this->locale->get_month_abbrev( __( 'March' ) ) );
-		$this->assertEquals( __( 'Apr' ), $this->locale->get_month_abbrev( __( 'April' ) ) );
-		$this->assertEquals( __( 'May' ), $this->locale->get_month_abbrev( __( 'May' ) ) );
-		$this->assertEquals( __( 'Jun' ), $this->locale->get_month_abbrev( __( 'June' ) ) );
-		$this->assertEquals( __( 'Jul' ), $this->locale->get_month_abbrev( __( 'July' ) ) );
-		$this->assertEquals( __( 'Aug' ), $this->locale->get_month_abbrev( __( 'August' ) ) );
-		$this->assertEquals( __( 'Sep' ), $this->locale->get_month_abbrev( __( 'September' ) ) );
-		$this->assertEquals( __( 'Oct' ), $this->locale->get_month_abbrev( __( 'October' ) ) );
-		$this->assertEquals( __( 'Nov' ), $this->locale->get_month_abbrev( __( 'November' ) ) );
-		$this->assertEquals( __( 'Dec' ), $this->locale->get_month_abbrev( __( 'December' ) ) );
+		$this->assertEquals( (string) __( 'Jan' ), $this->locale->get_month_abbrev( __( 'January' ) ) );
+		$this->assertEquals( (string) __( 'Feb' ), $this->locale->get_month_abbrev( __( 'February' ) ) );
+		$this->assertEquals( (string) __( 'Mar' ), $this->locale->get_month_abbrev( __( 'March' ) ) );
+		$this->assertEquals( (string) __( 'Apr' ), $this->locale->get_month_abbrev( __( 'April' ) ) );
+		$this->assertEquals( (string) __( 'May' ), $this->locale->get_month_abbrev( __( 'May' ) ) );
+		$this->assertEquals( (string) __( 'Jun' ), $this->locale->get_month_abbrev( __( 'June' ) ) );
+		$this->assertEquals( (string) __( 'Jul' ), $this->locale->get_month_abbrev( __( 'July' ) ) );
+		$this->assertEquals( (string) __( 'Aug' ), $this->locale->get_month_abbrev( __( 'August' ) ) );
+		$this->assertEquals( (string) __( 'Sep' ), $this->locale->get_month_abbrev( __( 'September' ) ) );
+		$this->assertEquals( (string) __( 'Oct' ), $this->locale->get_month_abbrev( __( 'October' ) ) );
+		$this->assertEquals( (string) __( 'Nov' ), $this->locale->get_month_abbrev( __( 'November' ) ) );
+		$this->assertEquals( (string) __( 'Dec' ), $this->locale->get_month_abbrev( __( 'December' ) ) );
 	}
 
 	public function test_get_meridiem() {
-		$this->assertEquals( __( 'am' ), $this->locale->get_meridiem( 'am' ) );
-		$this->assertEquals( __( 'AM' ), $this->locale->get_meridiem( 'AM' ) );
-		$this->assertEquals( __( 'pm' ), $this->locale->get_meridiem( 'pm' ) );
-		$this->assertEquals( __( 'PM' ), $this->locale->get_meridiem( 'PM' ) );
+		$this->assertEquals( (string) __( 'am' ), $this->locale->get_meridiem( 'am' ) );
+		$this->assertEquals( (string) __( 'AM' ), $this->locale->get_meridiem( 'AM' ) );
+		$this->assertEquals( (string) __( 'pm' ), $this->locale->get_meridiem( 'pm' ) );
+		$this->assertEquals( (string) __( 'PM' ), $this->locale->get_meridiem( 'PM' ) );
 	}
 
 	public function test_is_rtl() {
