WordPress.org

Make WordPress Core

Ticket #21914: test.php

File test.php, 11.2 KB (added by Otto42, 7 years ago)

Demo file

Line 
1<?php
2
3function fake_pingback_result($pagelinkedto, $linea, $method = 1) {
4
5        $linea = str_replace('<!DOC', '<DOC', $linea);
6        $linea = preg_replace( '/[\s\r\n\t]+/', ' ', $linea ); // normalize spaces
7        if ($method == 1) $linea = preg_replace( "/ <(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea );
8        if ($method == 2) $linea = preg_replace( "/<\/?(h1|h2|h3|h4|h5|h6|p|th|td|li|dt|dd|pre|caption|input|textarea|button|body)[^>]*>/", "\n\n", $linea );
9       
10        $linea = strip_tags( $linea, '<a>' ); // just keep the tag we need
11
12        $p = explode( "\n\n", $linea );
13
14        $preg_target = preg_quote($pagelinkedto, '|');
15
16        foreach ( $p as $para ) {
17                if ( strpos($para, $pagelinkedto) !== false ) { // it exists, but is it a link?
18                        preg_match("|<a[^>]+?".$preg_target."[^>]*>([^>]+?)</a>|", $para, $context);
19
20                        // If the URL isn't in a link context, keep looking
21                        if ( empty($context) )
22                                continue;
23
24                        // We're going to use this fake tag to mark the context in a bit
25                        // the marker is needed in case the link text appears more than once in the paragraph
26                        $excerpt = preg_replace('|\</?wpcontext\>|', '', $para);
27
28                        // prevent really long link text
29                        if ( strlen($context[1]) > 100 )
30                                $context[1] = substr($context[1], 0, 100) . '...';
31
32                        $marker = '<wpcontext>'.$context[1].'</wpcontext>';    // set up our marker
33                        $excerpt= str_replace($context[0], $marker, $excerpt); // swap out the link for our marker
34                        $excerpt = strip_tags($excerpt, '<wpcontext>');        // strip all tags but our context marker
35                        $excerpt = trim($excerpt);
36                        $preg_marker = preg_quote($marker, '|');
37                        $excerpt = preg_replace("|.*?\s(.{0,100}$preg_marker.{0,100})\s.*|s", '$1', $excerpt);
38                        $excerpt = strip_tags($excerpt); // YES, again, to remove the marker wrapper
39                        break;
40                }
41        }
42
43        return '[...]'. $excerpt .'[...]';
44}
45
46
47
48
49$demo = <<< END
50                <div class="post" id="post-849">
51<img style="float:right" src="http://chart.apis.google.com/chart?cht=qr&chs=80x80&choe=UTF-8&chld=L|0&chl=http://otto42.com/bo">                        <h2 class="posttitle"><a href="http://ottopress.com/2012/more-internationalization-fun/" rel="bookmark" title="Permanent Link to More Internationalization Fun" itemprop="url"><span itemprop="name">More Internationalization Fun</span></a></h2>
52                        <div style="clear:none" class="postmetadata">September 19, 2012, 5:10 pm <!-- by <span rel="author">Otto</span> --></div>
53                        <div class="postentry">
54                                <div itemprop="articleBody"><fb:like href='http://ottopress.com/2012/more-internationalization-fun/' send='true' layout='standard' show_faces='true' width='450' height='65' action='recommend' colorscheme='light' font='lucida grande'></fb:like><p><a href="http://ottopress.com/files/2012/02/international_flags.jpg"><img src="http://ottopress.com/files/2012/02/international_flags.jpg" alt="" title="international_flags" width="280" height="280" class="alignright size-full wp-image-777" /></a><br />
55So in my <a href="http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/">last post about Internationalization</a>, I covered some non-obvious things that you should consider when adding translation capabilities to your code.</p>
56<p>Today, let&#8217;s add to that by covering some non-obvious translation functions. You&#8217;re probably not using these, since they don&#8217;t get talked about as much. But there&#8217;s probably places where you should be using them, so knowing about them is the first step. And <a href="http://www.youtube.com/watch?v=P4mQ7UUkjro">knowing is half the battle</a>.</p>
57<h3>Basic functions, again</h3>
58<p>Last time I talked about these functions:</p>
59<ul>
60<li><code>__()</code></li>
61<li><code>_e()</code></li>
62<li><code>_x()</code></li>
63<li><code>_ex()</code></li>
64<li><code>_n()</code></li>
65</ul>
66<p>Let&#8217;s cover the ones I didn&#8217;t talk about.</p>
67<h3>Escaping output</h3>
68<p>In practice, you tend to use these mostly when outputting things onto the main page or in the admin. But, one thing you also use a lot when outputting text is the standard escaping functions. These are things like <code>esc_html()</code>, which outputs text in a way that makes it &#8220;safe&#8221; to go onto a webpage, without being interpreted as HTML. If the text comes from user input, then this is a good idea.</p>
69<p>Now, if you think about it, then the text you have may be translated in some other file, which you don&#8217;t control either. So escaping that text might be a good idea too. If somebody snuck bad code into a translation file, a user might get bad things displayed without being able to easily find it.</p>
70<p>So you could write something like <code>echo esc_html(__('text','text-domain'))</code>, but that&#8217;s a bit wordy. Let&#8217;s talk about some shortcuts.</p>
71<p>The <code>esc_html__()</code> function is the equivalent of <code>esc_html(__(...))</code>. It does the escaped html and the double-underscore translation all in one go. Similarly, the <code>esc_html_e()</code> function does the same thing, but it echoes the result, just like the <code>_e()</code> function would. And there&#8217;s also <code>esc_html_x()</code>, which is the equivalent of combining <code>esc_html()</code> and <code>_x()</code>.</p>
72<p>Along with those three are the three identical equivalents for attributes: <code>esc_attr__()</code>, <code>esc_attr_e()</code>, and <code>esc_attr_x()</code>. As the name implies, these combine the translation functions with <code>esc_attr()</code>, which is the escape function specifically intended when you&#8217;re outputting text into html attributes.</p>
73<p>Also note there&#8217;s no shortcut for the equivalent of <code>_ex()</code>. It&#8217;s just not used that much, or at least not enough to need something special for it. Use an <code>echo esc_html_x()</code> instead.</p>
74<p>There are no shortcuts for the other escaping functions as yet, but these can save a few keystrokes and make your code that much more readable.</p>
75<h3>The Numerical No-op</h3>
76<p>So we&#8217;ve got some shortcuts for escaping with those three functions, but where&#8217;s the love for <code>_n()</code>?</p>
77<p>One of the problems with <code>_n()</code> is that it tends to require the strings to be in the same place that the PHP variable is. For all the other functions, you could have a big file of strings in an array, and then reference those strings by name or something elsewhere because they don&#8217;t require any PHP variables. Nothing about them is computed at the time of the output.</p>
78<p>But not so with <code>_n()</code>, that $number to decide which string to use means that the strings have to be right there, they can&#8217;t be translated separately and referenced.</p>
79<p>This is where <code>_n_noop()</code> comes in. The <code>_n_noop()</code> function basically takes the singular and plural strings for something, along with the text domain, and stores them in an array so that they can be referenced later by a function named <code>translate_nooped_plural()</code>.</p>
80<p>Perhaps an example is in order. Let&#8217;s go back to the tacos:</p>
81<pre class="brush: php; notranslate">
82$string = sprintf( _n('You have %d taco.', 'You have %d tacos.', $number, 'plugin-domain'), $number );
83</pre>
84<p>What if we wanted those strings somewhere else? Like in a big file with all of our strings. Here&#8217;s a way to separate the strings from the _n() call:</p>
85<pre class="brush: php; notranslate">
86$taco_plural = _n_noop('You have %d taco.', 'You have %d tacos.', 'plugin-domain');
87$string = sprintf( translate_nooped_plural( $taco_plural, $number) , $number );
88</pre>
89<p>Now, that $taco_plural can be defined anywhere. Note that it contains no references to PHP variables. It&#8217;s basically static and unchanging. This allows us to separate it, then reference it elsewhere for the actual translation. The <code>translate_nooped_plural()</code> function performs the same job as <code>_n()</code> does, choosing which string to use based on the $number of tacos. The sprintf then pushes the $number into the chosen string, replacing the %d with the number.</p>
90<p>Thus, that lets us extract the translatable strings out and put them anywhere we choose.</p>
91<p>Also of note: The <code>_nx_noop()</code> function is a cross between <code>_n_noop()</code> and <code>_x()</code>. It takes a context for the translators as the third argument, and the domain becomes the fourth argument. Useful if you need to explain to the translators the context surrounding the pluralization choice.</p>
92<h3>Numbers and Dates</h3>
93<p>The <code>number_format_i18n()</code> function is functionally equivalent to the <a href="http://php.net/manual/en/function.number-format.php">PHP number_format</a> function. It lets you format numbers with commas at the thousands mark and so forth, except that it also takes localization into account. Not everybody uses commas for thousands and periods for decimals. This function will do the translation appropriately for that aspect.</p>
94<p>The <code>date_i18n()</code> function is functionally equivalent to the <a href="http://php.net/manual/en/function.date.php">PHP date</a> function. It will handle all the same string formatting parameters as date() will, but it will cause output to be translated for month names, day-of-week names, and so forth. Of note is that it doesn&#8217;t change the format requested. If some places put days before months, for example, it won&#8217;t handle that. But it will output the month name in the native language (if the translation pack has the right month name in it). So you may want to run the date formatting string through <code>__()</code> as well, to let translators adjust the date format accordingly.</p>
95<h3>Wrap up</h3>
96<p>And that&#8217;s pretty much all the rest of the translation functions that I didn&#8217;t cover before. I may have forgotten a few useful ones here or there. Feel free to comment about anything I missed, or what you see most often, especially if you&#8217;re doing <a href="http://localhost/example">translations</a> yourself.</p>
97<a href='http://twitter.com/share?url=http%3A%2F%2Fotto42.com%2Fbo&count=vertical&related=otto42%2Cottodestruct&text=More Internationalization Fun' class='twitter-share-button' data-text='More Internationalization Fun' data-url='http://otto42.com/bo' data-counturl='http://ottopress.com/2012/more-internationalization-fun/' data-count='vertical' data-via='' data-related='otto42,ottodestruct'></a><span class="fb_share"><fb:like href="http://ottopress.com/2012/more-internationalization-fun/" layout="box_count"></fb:like></span><div class="plusone"><g:plusone size=tall annotation=bubble align=left href="http://ottopress.com/2012/more-internationalization-fun/"></g:plusone></div><p class="yarpp">Related posts:</p><ol class="yarpp"><li><a href='http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/' rel='bookmark' title='Internationalization: You&#8217;re probably doing it wrong'>Internationalization: You&#8217;re probably doing it wrong</a></li></ol></div></div><p><span class="post-shortlink">Shortlink: <input type='text' value='http://otto42.com/bo' onclick='this.focus(); this.select();' /></span></p>
98END;
99
100
101echo "Before:\n" . fake_pingback_result('http://localhost/example', $demo, 1) . "\n\n";
102
103echo "After:\n" . fake_pingback_result('http://localhost/example', $demo, 2) . "\n\n";