Skip to content

Instantly share code, notes, and snippets.

@tacoverdo
Last active November 13, 2017 07:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tacoverdo/2ffad5693b9532305a41 to your computer and use it in GitHub Desktop.
Save tacoverdo/2ffad5693b9532305a41 to your computer and use it in GitHub Desktop.
What is the best way to translate a text with hyperlink?
@coenjacobs
Copy link

Method 3, but change the single quotes around attributes to double quotes so they are easier to read and don't need any escaping. Also, the sprintf() variable parameters don't need to be wrapped in quotes:

sprintf( __( 'Please read <a href="%s">this</a>.', 'tacoverdo-example-domain' ), esc_url( 'https://goo.gl' ) );

@tacoverdo
Copy link
Author

Thanks Coen, I updated method 3 in the above gist :)

@Rarst
Copy link

Rarst commented Oct 14, 2014

There is no point in runtime escaping if URL is hardcoded. Most of these treat URL as separate from the string, but I very well might imagine scenarios where it is translatable information, for example linking to language–specific version of target page.

So I'd say path of least resistance is 5 sans escaping.

@johnbillion
Copy link

As Coen mentioned, method 3. This is how core does it, with the addition of separate i18n on the URL so localised installs can change the link destination. Depends on the context of the link though.

@danielpataki
Copy link

I personally do not like putting HTML tags in translations as I feel they don't belong here. One possible solution is:

sprintf( __( '%s <a href="%s">%s</a> %s', 'texdomain' ), 'Please read', 'http://goo.gl', 'this link', 'as soon as possible' );

This is a little overkill though. In my experience if someone takes the time to translate something they are OK with a little bit of HTML so I would probably also use method 3.

@zedejose
Copy link

Agree with Method 3, disagree with @Rarst, re Method 5. As any validator of translations will tell you, it is far too easy for a translator (i.e. not a dev), to mess up or mistype the esc_url( 'http://goo.gle') bit (see what I did there? :) ). If we have to go and check stuff like that in addition to the normal strings, validating becomes a bigger headache than it needs to be.

@Rarst
Copy link

Rarst commented Oct 14, 2014

Yeah, after some pondering 3 with separate translation call on URL is probably the way to go (as per John). And keeping escaping in that case since it won't hurt if it doesn't hurt.

@justintadlock
Copy link

This is the best method if the entire text is to be translated.

echo '<a href="#">' . __( 'Please read this.', 'textdomain' ) . '</a>';

If the link is within the text, this can be the easiest if there are no other placeholders. I like this method because I prefer to not have translators tinkering with the HTML.

/* Translators: %s are placeholders are for HTML. The order cannot be changed. */
printf( __( 'Please read %sthis%s.', 'textdomain' ), '<a href="#">', '</a>' );

Otherwise, this is probably the way to go:

_e( 'Please read <a href="#">this</a>.', 'textdomain' );

You don't need to use esc_url() if you're hardcoding the URL. If that's a variable, it changes things about the above method, which would need to be:

printf( __( 'Please read <a href="%s">this</a>.', 'textdomain' ), esc_url( $url ) );

And, like Rarst said, sometimes URLs need to be translated, so that may change things up.

@zedejose
Copy link

@danielpataki, you're assuming that the sequence 'Please read', url , 'this' is valid for any language, which it is not true.

@markhowellsmead
Copy link

Method 3.

@tacoverdo
Copy link
Author

To be honest, I expected method 1 to be the most widely used/favorited.

The reason for that is that method 3 requires every translator to "translate" <a href="%s"> as part of the string, even though it does not change per language. Therefore using %s for the whole seemed to make more sense.
Using that also lowers the chance that translators make (un)intentional mistakes in the HTML.
The downside of method 1 however is readability. %ssentence%s can be quite easily misread.

So, why do most of you prefer method 3 over method 1?
Because core does it that way? Or is there an argument I overlooked?

@zedejose
Copy link

So, why do most of you prefer method 3 over method 1?

I can only speak as a translator, validator, and team lead of translators: It's the way core does it, and we're all used to it. A variation would cause a translator to stop and ponder on the meaning of the unusual placeholders. That said, you're of course free to use Method 1.

@johnbillion
Copy link

Regarding method 1: It's not clear to a translator what the %1$s and %2$s placeholders represent (A <strong> tag? An <a> tag? Speech marks?). It would need to be accompanied by a translator comment, or the translator would need to look up the string in the source code to see what was going on.

@bueltge
Copy link

bueltge commented Oct 14, 2014

I'm for a version there exclude the html, is not helpful to translate this and makes harder to secure this.
I'm agree with the hints from @justintadlock . But if you will add context for the translators use the function _x() or a related function with context.

The esc_url() in method 3 is not helpful, only a performance topic here if you hardcoded the url.

@cfoellmann
Copy link

In some cases I would recommend something like:

sprintf( __( 'Please read the %s.', 'tacoverdo-example-domain' ), '<a href="' . esc_html__( 'https://goo.gl', 'tacoverdo-example-domain' ) . '">' . __( 'docs', 'tacoverdo-example-domain' ) . '</a>' );

you might want to use _x() to clarify the connection but I think this way the translator is safe from screwing up html elements

EDIT:
Or do I need to go with:

sprintf( __( 'Please read the %s.', 'tacoverdo-example-domain' ), '<a href="' . esc_url( __( 'https://goo.gl', 'tacoverdo-example-domain' ) ) . '">' . __( 'docs', 'tacoverdo-example-domain' ) . '</a>' );

@tacoverdo
Copy link
Author

@cfoellmann I must say I disagree with both, as Otto explained under Law the Second.

@bueltge & @johnbillion I think it's good practice to provide context when needed, but do translators really need it in this case? Do they need to know whether %s stands for <strong> or <a href target="#">? Does it influence their translation?

@bueltge
Copy link

bueltge commented Oct 14, 2014

I find context helpful. if you add a context for %s, makes easier for translators, especially if she don't know about the position, the context in the source.

@nlemoine
Copy link

I used to include HTML tag in translations until some people reported bugs that I couldn't figure out. It turns out that a translator messed up with some HTML closing tags: < /a> (space between < and /a>) which caused some errors.

So from now, I will go for a non including HTML tags method.

@cfoellmann
Copy link

@tacoverdo You are totally right. The "chapter" is great and logical but I think the case here with a link it a little bit beyond the described case. This discussion is a good indicator for that.
Hopefully there are some more ideas coming up here. I am not happy with either of the solutions (including mine)

@Rarst
Copy link

Rarst commented Oct 14, 2014

I summarized my thoughts and my interpretation of this discussion in answer at WPSE, but since Ze grumbled at me for it — alternate answers welcomed. :)

@grappler
Copy link

If you can go with method 2 then that is the best but not always possible. Method 3 is simple and balanced.

Method 1 and 4 are the same except for using %s or %1$s

@cfoellmann solution should work in every language as you can move the variable as needed but requires a certain understanding to make it work.

@2ndkauboy
Copy link

I would also opt for method 3. It's not uncommon for a translator to have strings with some HTML markup inside. As long as it's just as much as you need.

I would also find 1 and 4 not easy to translate if you don't know what the placeholders stand for. And beside readability, it's quite easy to mess it up. Method 2 would be somehow OK. I would never use method 5, as it's quite impossible to parse such a translation. If you hard code the URL in method 5, to make the URL itself translatable (as @Rarst pointed out), than I am also OK with method 5, but still wouldn't do it this way.

@tacoverdo
Copy link
Author

Please continue discussion here, if necessary.

Thanks!

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