esc_html__( string $text, string $domain = 'default' ): string
- Since
- 2.8.0
- Source
wp-includes/l10n.php:339
Runs $text through translate() for the given $domain, then passes the result through esc_html() before returning it. Use it whenever a translated string is being placed directly into HTML markup, such as a heading or table cell, rather than into an attribute. If the text domain named by $domain isn't loaded, the original $text is escaped and returned unchanged rather than throwing an error. Reach for esc_html_e() instead if you want the string echoed immediately rather than returned.
Description
If there is no translation, or the text domain isn't loaded, the original text is escaped and returned.
Compatibility
- WordPress
- since 2.8.0
- PHP
- 7.4–8.6-dev
- 6.7.7
- 6.8.8
- 6.9.7
- 7.0.4
- 7.1.0
Present in every tracked release (6.7.7 to 7.1.0), and compiles on PHP 7.4 through 8.6-dev.
Parameters
$textstring- Text to translate.
$domainstringoptional- Text domain. Unique identifier for retrieving translated strings.
Default 'default'.Default:'default'
Return value
string- Translated text.
Code examples
Every example is editable and runs in a real WordPress booted in your browser by WordPress Playground. Press Run, then edit the code: clicking away re-runs it. Nothing is sent anywhere until you do.
Print a translation-ready heading in a plugin admin page
A plugin settings page needs a heading that is both translatable and safe to place directly into HTML.
$heading = esc_html__( 'Manage Featured Posts', 'my-plugin' );
echo '<h2>' . $heading . '</h2>';The text domain 'my-plugin' isn't loaded in the sandbox, so the original English string is escaped and returned unchanged, which is exactly the fallback behavior the function documents.
Escape angle brackets in a translated string built from post meta
Post 2 in the baseline has a price meta value, and this builds a label that includes literal angle brackets around it.
$price = get_post_meta( 2, 'price', true );
$label = esc_html__( 'Current price: <' . $price . '>', 'my-plugin' );
echo $label;esc_html() turns the '<' and '>' characters into HTML entities so they render as visible text instead of being interpreted as tags.
Common problems and fixes · 4
- Why do the HTML tags inside my esc_html__ string show up as text instead of rendering?
- Should I use esc_html__ or esc_html_e for output?
- Why doesn't my string show up in the .pot file when I run it through esc_html__?
- Why did my string come back untranslated even though I set a text domain?
Why do the HTML tags inside my esc_html__ string show up as text instead of rendering?
Should I use esc_html__ or esc_html_e for output?
Why doesn't my string show up in the .pot file when I run it through esc_html__?
Why did my string come back untranslated even though I set a text domain?
Alternatives and related functions
esc_html_e- When you want the escaped, translated string echoed immediately instead of returned for further use.
esc_html- When the text is already translated (or never needs translation) and only escaping for HTML output is required.
esc_attr__- When the translated string is going into an HTML attribute value rather than into element content.
translate- When you need the raw translated string without any HTML escaping applied.
Performance profile
How much work a call to esc_html__() does, and what it touches: the algorithmic scaling, the Zend instruction count per call across PHP versions, the hooks it hands control to, and the core code that calls it. Measured from the compiled opcodes, not a stopwatch, so every number is identical on any machine running the same PHP version, and every function in core is ranked by cost.
- Cost class
- Trivial
- Scaling
- Constant
- Instructions
- 10
- Plugin surface
- None
- Called by
- 35
Touches nothing outside its own arguments.
No loop in the body: the same number of instructions runs whatever you pass in.
Executed per call on PHP 8.5. The body compiles to 10.
Nothing here hands control to plugin code.
35 places in core call this, so the cost is paid more often than your own code shows.
What it touches
- hookthird-party callbacks
apply_filters()one call below esc_html__()
Further down the call graph this can also reach option, cache, serialize, query and transient. Those are the worst case, several calls deep and usually down an error path, not what a normal call pays.
What one call costs · 1 distinct outcome
One number would be a lie: the work depends on which branch runs. These are every distinct cost esc_html__() can have, taken from its control-flow graph on PHP 8.5.
| When | Instructions | Calls it makes |
|---|---|---|
| always | 10 | translate(), esc_html() |
Across PHP versions
Compiles the same on PHP 7.4, 8.1, 8.2, 8.3, 8.4, 8.5 and 8.6-dev: 10 instructions, 10 executed per call, 0 branches. The work does not change between versions.
An instruction is not a fixed amount of time, so a matching count is not necessarily the same speed; what it rules out is a difference in the work itself.
Uses · 2
- esc_html()Escaping for HTML blocks.
- translate()Retrieves the translation of $text.
Used by · 35
- Plugin_Installer_Skin::do_overwrite()Checks if the plugin can be overwritten and outputs the HTML for overwriting a plugin on upload.
- Theme_Installer_Skin::do_overwrite()Checks if the theme can be overwritten and outputs the HTML for overwriting a theme on upload.
- Twenty_Twenty_One_Customize::register()Registers customizer options.
- Twenty_Twenty_One_Dark_Mode::customizer_controls()Registers customizer options.
- Twenty_Twenty_One_Dark_Mode::the_html()Prints the dark-mode switch HTML.
- WP_Application_Passwords_List_Table::print_js_template_row()Prints the JavaScript template for the new row item.
- WP_Privacy_Data_Export_Requests_List_Table::column_next_steps()Displays the next steps column.
- WP_Privacy_Data_Removal_Requests_List_Table::column_next_steps()Outputs the Next steps column.
- WP_Script_Modules::print_a11y_script_module_html()
- _block_template_add_skip_link()Inserts the block template skip-link into the template HTML.
- block_core_image_render_lightbox()Adds the directives and layout needed for the lightbox behavior.
- get_the_block_template_html()Returns the markup for the current template.
Show all 35
- render_block_core_comment_edit_link()Renders the `core/comment-edit-link` block on the server.
- twenty_twenty_one_add_sub_menu_toggle()Adds a button to top-level menu items that has sub-menus.
- twenty_twenty_one_continue_reading_text()Creates continue reading text.
- twenty_twenty_one_customize()Prevents the Customizer from being loaded on WordPress versions prior to 5.3.
- twenty_twenty_one_entry_meta_footer()Prints HTML with meta information for the categories, tags and comments.
- twenty_twenty_one_get_starter_content()Returns the array of starter content for the theme.
- twenty_twenty_one_password_form()Retrieves protected post password form content.
- twenty_twenty_one_posted_by()Prints HTML with meta information about theme author.
- twenty_twenty_one_posted_on()Prints HTML with meta information for the current post-date/time.
- twenty_twenty_one_preview()Prevents the Theme Preview from being loaded on WordPress versions prior to 5.3.
- twenty_twenty_one_register_block_pattern()Registers Block Patterns.
- twenty_twenty_one_register_block_pattern_category()Registers Block Pattern Category.
- twenty_twenty_one_register_block_styles()Registers block styles.
- twenty_twenty_one_setup()Sets up theme defaults and registers support for various WordPress features.
- twenty_twenty_one_the_posts_navigation()Prints the next and previous posts navigation.
- twenty_twenty_one_upgrade_notice()Adds a message for unsuccessful theme switch.
- twenty_twenty_one_widgets_init()Registers widget area.
- twentyeleven_skip_link()Includes a skip to content link at the top of the page so that users can bypass the menu.
- twentynineteen_add_ellipses_to_nav()Adds an extra menu to our nav for our priority+ navigation to use.
- twentynineteen_get_the_archive_title()Filters the default archive titles.
- twentythirteen_entry_meta()Prints HTML with meta information for current post: categories, tags, permalink, author, and date.
- wp_privacy_generate_personal_data_export_file()Generate the personal data export file.
- wp_privacy_generate_personal_data_export_group_html()Generate a single group for the personal data export report.
Source code
function esc_html__( $text, $domain = 'default' ) { return esc_html( translate( $text, $domain ) );}Changelog
Introduced in 2.8.0. Unchanged from 6.7.7 through 7.1.0.
Signature, return type and hooks compared across 5 parsed releases.
About this page
- Parsed data
- Generated from the wordpress-develop 7.0.4 tag, from
src/wp-includes/l10n.php, and regenerated for each WordPress release so it tracks the code rather than a snapshot of it. - Corrections
- Something wrong on this page? Report it and it gets fixed in the next regeneration.