wp_get_image_alttext()WP 7.0.0

Retrieves alternative text from XMP metadata in an image file.

Looks for the Iptc4xmpCore:AltTextAccessibility field. When it contains multiple language variants, it selects the first suitable one in this order:

  • an exact match for the site locale, for example fr_FR.
  • a match for the first two characters of the locale, for example ru.
  • the x-default language variant.

When an image is uploaded, WordPress uses this text to populate the Alt field in the Media Library.

The function retrieves text directly from the file, not from the _wp_attachment_image_alt meta-field. It does not save the found text to the database.

To retrieve Alt text saved for an attachment in the Media Library, use get_post_meta():

$alt_text = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );

On the front end, the function file may need to be included manually:

require_once ABSPATH . `wp-admin/includes/image.php`.

No Hooks.

Returns

string.

  • string - the found alternative text.
  • '' - if the file could not be read, XMP metadata is missing or corrupt, the required field was not found, or no suitable language variant exists.

Usage

wp_get_image_alttext( $file );
$file(string) (required)
The image file path. The function reads the entire file.

Examples

#1 Retrieve embedded image Alt text

require_once ABSPATH . 'wp-admin/includes/image.php';

$file = wp_get_original_image_path( 123 );

if ( $file ) {
	$alt_text = wp_get_image_alttext( $file );

	echo esc_html( $alt_text );
}

Changelog

Since 7.0.0 Introduced.

wp_get_image_alttext() code WP 7.1.1

function wp_get_image_alttext( $file ) {
	$alt_text     = '';
	$img_contents = file_get_contents( $file );

	if ( false === $img_contents ) {
		return $alt_text;
	}

	// Find the start and end positions of the XMP metadata.
	$xmp_start = strpos( $img_contents, '<x:xmpmeta' );
	$xmp_end   = strpos( $img_contents, '</x:xmpmeta>' );

	if ( false === $xmp_start || false === $xmp_end ) {
		// No XMP metadata found.
		return $alt_text;
	}

	// Extract the XMP metadata from the JPEG contents
	$xmp_data = substr( $img_contents, $xmp_start, $xmp_end - $xmp_start + 12 );

	// Parse the XMP metadata using DOMDocument.
	$doc = new DOMDocument();
	if ( false === $doc->loadXML( $xmp_data ) ) {
		// Invalid XML in metadata.
		return $alt_text;
	}

	// Instantiate an XPath object, used to extract portions of the XMP.
	$xpath = new DOMXPath( $doc );

	// Register the relevant XML namespaces.
	$xpath->registerNamespace( 'x', 'adobe:ns:meta/' );
	$xpath->registerNamespace( 'rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' );
	$xpath->registerNamespace( 'Iptc4xmpCore', 'http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/' );

	$node_list = $xpath->query( '/x:xmpmeta/rdf:RDF/rdf:Description/Iptc4xmpCore:AltTextAccessibility' );
	if ( $node_list && $node_list->count() ) {

		$node = $node_list->item( 0 );

		// Get the site's locale.
		$locale = get_locale();

		// Get the alt text accessibility alternative most appropriate for the site language.
		// There are 3 possibilities:
		//
		// 1. there is an rdf:li with an exact match on the site locale.
		// 2. there is an rdf:li with a partial match on the site locale (e.g., site locale is en_US and rdf:li has @xml:lang="en").
		// 3. there is an rdf:li with an "x-default" lang.
		//
		// Evaluate in that order, stopping when we have a match.
		$alt_text = $xpath->evaluate( "string( rdf:Alt/rdf:li[ @xml:lang = '{$locale}' ] )", $node );
		if ( ! $alt_text ) {
			$alt_text = $xpath->evaluate( 'string( rdf:Alt/rdf:li[ @xml:lang = "' . substr( $locale, 0, 2 ) . '" ] )', $node );
			if ( ! $alt_text ) {
				$alt_text = $xpath->evaluate( 'string( rdf:Alt/rdf:li[ @xml:lang = "x-default" ] )', $node );
			}
		}
	}

	return $alt_text;
}