Index: src/wp-includes/l10n.php
===================================================================
--- src/wp-includes/l10n.php	(revision 44184)
+++ src/wp-includes/l10n.php	(working copy)
@@ -888,6 +888,10 @@
 function load_script_textdomain( $handle, $domain, $path = null ) {
 	global $wp_scripts;
 
+	if ( ! isset( $wp_scripts->registered[ $handle ] ) ) {
+		return false;
+	}
+
 	$path   = untrailingslashit( $path );
 	$locale = determine_locale();
 
@@ -900,8 +904,12 @@
 
 	$obj = $wp_scripts->registered[ $handle ];
 
+	$src = $obj->src;
+	if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $wp_scripts->content_url && 0 === strpos( $src, $wp_scripts->content_url ) ) ) {
+		$src = $wp_scripts->base_url . $src;
+	}
 	/** This filter is documented in wp-includes/class.wp-scripts.php */
-	$src = esc_url( apply_filters( 'script_loader_src', $obj->src, $handle ) );
+	$src = esc_url( apply_filters( 'script_loader_src', $src, $handle ) );
 
 	$relative       = false;
 	$languages_path = WP_LANG_DIR;
@@ -913,10 +921,10 @@
 	// If the host is the same or it's a relative URL.
 	if (
 		strpos( $src_url['path'], $content_url['path'] ) === 0 &&
-		( ! isset( $src_url['host'] ) || $src_url['host'] !== $content_url['host'] )
+		( ! isset( $src_url['host'] ) || $src_url['host'] === $content_url['host'] )
 	) {
 		// Make the src relative the specific plugin or theme.
-		$relative = trim( substr( $src, strlen( $content_url['path'] ) ), '/' );
+		$relative = trim( substr( $src_url['path'], strlen( $content_url['path'] ) ), '/' );
 		$relative = explode( '/', $relative );
 
 		$languages_path = WP_LANG_DIR . '/' . $relative[0];
@@ -923,16 +931,26 @@
 
 		$relative = array_slice( $relative, 2 );
 		$relative = implode( '/', $relative );
-	} elseif ( ! isset( $src_url['host'] ) || $src_url['host'] !== $site_url['host'] ) {
+	} elseif ( ! isset( $src_url['host'] ) || $src_url['host'] === $site_url['host'] ) {
 		if ( ! isset( $site_url['path'] ) ) {
 			$relative = trim( $src_url['path'], '/' );
-		} elseif ( ( strpos( $src_url['path'], $site_url['path'] ) === 0 ) ) {
+		} elseif ( ( strpos( $src_url['path'], trailingslashit( $site_url['path'] ) ) === 0 ) ) {
 			// Make the src relative to the WP root.
-			$relative = substr( $src, strlen( $site_url['path'] ) );
+			$relative = substr( $src_url['path'], strlen( $site_url['path'] ) );
 			$relative = trim( $relative, '/' );
 		}
 	}
 
+	/**
+	 * Filters the relative path of scripts used for finding translation files.
+	 *
+	 * @since 5.0.2
+	 *
+	 * @param string $relative The relative path of the script. False if it could not be determined.
+	 * @param string $src      The full source url of the script.
+	 */
+	$relative = apply_filters( 'load_script_textdomain_relative_path', $relative, $src );
+
 	// If the source is not from WP.
 	if ( false === $relative ) {
 		return false;
Index: tests/phpunit/tests/l10n/loadScriptTextdomain.php
===================================================================
--- tests/phpunit/tests/l10n/loadScriptTextdomain.php	(nonexistent)
+++ tests/phpunit/tests/l10n/loadScriptTextdomain.php	(working copy)
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @group l10n
+ * @group i18n
+ */
+class Tests_L10n_loadScriptTextdomain extends WP_UnitTestCase {
+	public function site_url_subdirectory( $site_url ) {
+		return $site_url . '/wp';
+	}
+
+	public function relative_path_from_cdn( $relative, $src ) {
+		if ( 0 === strpos( $src, 'https://my-cdn.com/wordpress/' ) ) {
+			return substr( $src, strlen( 'https://my-cdn.com/wordpress/' ) );
+		}
+
+		return $relative;
+	}
+
+	/**
+	 * @ticket 45528
+	 */
+	public function test_resolve_relative_path() {
+		$json_translations = file_get_contents( DIR_TESTDATA . '/languages/en_US-813e104eb47e13dd4cc5af844c618754.json' );
+
+		wp_enqueue_script( 'test-example-root', '/wp-includes/js/script.js', array(), null );
+		$this->assertEquals( $json_translations, load_script_textdomain( 'test-example-root', 'default', DIR_TESTDATA . '/languages' ) );
+
+		// Assets on a CDN.
+		add_filter( 'load_script_textdomain_relative_path', array( $this, 'relative_path_from_cdn' ), 10, 2 );
+		wp_enqueue_script( 'test-example-cdn', 'https://my-cdn.com/wordpress/wp-includes/js/script.js', array(), null );
+		$this->assertEquals( $json_translations, load_script_textdomain( 'test-example-cdn', 'default', DIR_TESTDATA . '/languages' ) );
+		remove_filter( 'load_script_textdomain_relative_path', array( $this, 'relative_path_from_cdn' ) );
+
+		// Test for WordPress installs in a subdirectory.
+		add_filter( 'site_url', array( $this, 'site_url_subdirectory' ) );
+		wp_enqueue_script( 'test-example-subdir', '/wp/wp-includes/js/script.js', array(), null );
+		$this->assertEquals( $json_translations, load_script_textdomain( 'test-example-subdir', 'default', DIR_TESTDATA . '/languages' ) );
+		remove_filter( 'site_url', array( $this, 'site_url_subdirectory' ) );
+	}
+}
