Skip to content

Instantly share code, notes, and snippets.

@kailoon
Last active July 1, 2023 08:54
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save kailoon/01fa8e95d2e910e666c6 to your computer and use it in GitHub Desktop.
Save kailoon/01fa8e95d2e910e666c6 to your computer and use it in GitHub Desktop.
<?php
/**
* Escape all translations with
*/
__( ‘Some String’, ‘text-domain’ ); _e( ‘Some string’, ‘text-domain’ );.
/**
* When there is no HTML use:
*/
esc_html__( ‘Some String’, ‘text-domain’ ); esc_html_e( ‘Some String’, ‘text-domain’ );
/**
* For some HTML:
*/
wp_kses( __( ‘Some String something’, ‘text-domain’ ), $allowed_html_array );
@vkurko
Copy link

vkurko commented Jul 10, 2022

@kailoon

If I need to pass translations using wp_localize_script() to a JS application written in Vue.js or Svelte, where those texts would be escaped during rendering anyway, would it be a problem for an Envato reviewer the usage of __() function?


Let me explain in more detail.

Let's take a simple template that displays the contents of a variable:

// In Vue
<div>{{i18n.text}}</div>

// In Svelte
<div>{i18n.text}</div>

I would pass the text to JS like this:

wp_localize_script( 'my-app.js', 'i18n', array(
  'text' => __( 'Say "hello"', 'textdomain' )
) );

Since both Vue and Svelte render the expression as text and not as html, we will get the desired result (XSS vulnerability or broken html is ruled out in this case):

image

If I use esc_html__ instead of __():

wp_localize_script( 'my-app.js', 'i18n', array(
  'text' => esc_html__( 'Say "hello"', 'textdomain' )
) );

Then we get the wrong result because there is redundant escaping on the PHP side:

image

Sorry to have to ask this question here, but maybe it will be helpful to other developers who, like me, are trying to go through the review process of their plugin and are wondering why they are getting a soft rejection.

Thanks in advance for your reply.

@ajayshrivas
Copy link

Hello vkurko,
https://developer.wordpress.org/reference/functions/esc_html__/

"If I use esc_html__ instead of (): " You can user esc_html

esc_html() escapes a string so that it is not parsed as HTML. Characters like < are converted to <, for example. This will look the same to the reader, but it means that if the value being output is <script> then it won't be interpreted by the browser as an actual script tag.

Use this function whenever the value being output should not contain HTML.

esc_attr() escapes a string so that it's safe to use in an HTML attribute, like class="" for example. This prevents a value from breaking out of the HTML attribute. For example, if the value is "><script>alert();</script> and you tried to output it in an HTML attribute it would close the current HTML tag and open a script tag. This is unsafe. By escaping the value it won't be able to close the HTML attribute and tag and output unsafe HTML.

Use this function when outputting a value inside an HTML attribute.

esc_url() escapes a string to make sure that it's a valid URL.

Use this function when outputting a value inside an href="" or src="" attribute.

esc_textarea() escapes a value so that it's safe to use in a <textarea> element. By escaping a value with this function it prevents a value being output inside a <textarea< from closing the <textarea> element and outputting its own HTML.

Use this function when outputting a value inside a <textarea> element.

esc_html() and esc_attr() also have versions ending in __(), _e() and _x(). These are for outputting translatable strings.

WordPress has functions, __(), _e() and _x(), for outputting text that can be translated. __() returns a translatable string, _e() echoes a translatable string, and _x() returns a translatable string with a given context. You've probably seen them before.

Since you can't necessarily trust a translation file to contain safe values, using these functions when outputting a translatable string ensures that the strings being output can't cause the same issue described above.

Use these functions when outputting translatable strings.

esc_html would be used inside of html for example between a

tag

esc_attr would be used for escaping [attribute values](https://wp-qa.com/filter-woocommerce-archive-pages-with-product-attribute-values-by-default) on html tags like so:

applying _e to the end is for using it with text domains and will automatically echo it for you e.g:

@vkurko
Copy link

vkurko commented Jul 11, 2022

You can user esc_html

No, I can't, because the result will be the same. The problem is that escaping cannot be double. If it happens in a JS application, then you shouldn't escape texts in PHP.

Are you familiar with React, Vue or Svelte? In these frameworks, text values are rendered exactly as texts, and to render html, you need to use special syntax. Thus, you cannot escape texts in PHP because they will appear escaped on the page.

Please look at this example:
https://svelte.dev/repl/12ead03462944e4f9b2811025d37075a?version=3.49.0

It displays 2 strings, the first one with untouched text, the second one after being processed by esc_html() on the PHP side. It is clear that in the second case, we get the wrong result due to redundant escaping in PHP.

@ngothoai
Copy link

ngothoai commented Jul 1, 2023

  1. All theme text strings are to be translatable and properly escaped. https://gist.github.com/kailoon/01fa8e95d2e910e666c6 example(s) from your code and there are more: https://envato.d.pr/fWcY4T
    @kailoon could you explain for me clear more about this point. What's it wrong?
    Envato required using function esc_html__() inserted __()?

Exactly, We can not use (), Only verify esc_html()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment