<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>plugin Archives - Alexandros Georgiou</title>
	<atom:link href="https://www.alexgeorgiou.gr/tag/plugin/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.alexgeorgiou.gr/tag/plugin/</link>
	<description>Balancing brackets for a living</description>
	<lastBuildDate>Wed, 20 Dec 2023 10:30:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.alexgeorgiou.gr/wp-content/uploads/2021/07/cropped-alexgeorgiou-icon-32x32.png</url>
	<title>plugin Archives - Alexandros Georgiou</title>
	<link>https://www.alexgeorgiou.gr/tag/plugin/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>👻 Monitor analytics of a public WordPress plugin using PhantomJS</title>
		<link>https://www.alexgeorgiou.gr/scrape-daily-analytics-wordpress-plugin/</link>
					<comments>https://www.alexgeorgiou.gr/scrape-daily-analytics-wordpress-plugin/#respond</comments>
		
		<dc:creator><![CDATA[alexg]]></dc:creator>
		<pubDate>Sat, 09 Jun 2018 10:14:06 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[analytics]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[installations]]></category>
		<category><![CDATA[issues]]></category>
		<category><![CDATA[metric]]></category>
		<category><![CDATA[phantomjs]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[scraper]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[usage]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.alexgeorgiou.gr/?p=262</guid>

					<description><![CDATA[<p>A script to scrape and save daily usage statistics for a WordPress plugin for later use in analytics.</p>
<p>The post <a href="https://www.alexgeorgiou.gr/scrape-daily-analytics-wordpress-plugin/">👻 Monitor analytics of a public WordPress plugin using PhantomJS</a> appeared first on <a href="https://www.alexgeorgiou.gr">Alexandros Georgiou</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>When a WordPress plugin is hosted on WordPress.org, some basic usage statistics are shown on its page. These can be used in your plugin analytics.</p>
<h2>The problem</h2>
<p>I needed an easy way to gather up some of these daily stats into a <code>.csv</code> file for later analysis and monitoring.</p>
<p>Data I was interested in:</p>
<ul>
<li>The approximate current number of installs (this number is rounded)</li>
<li>The number of yesterday&#8217;s new downloads (today&#8217;s downloads depends on what time you run the script)</li>
<li>The number of total downloads</li>
<li>The number of support issues reported within the last month</li>
<li>The number of support issues resolved within the last month</li>
</ul>
<p>Most of these numbers are found in the static HTML, but the download counts are added in later via JavaScript. Hence the need for phantomjs.</p>
<h2>The solution</h2>
<p>A good place to go to gather these statistics is the <em>advanced</em> view of WordPress.org. For example, to see some basic statistics for my plugin, <a href="http://dashed-slug.net/bitcoin-altcoin-wallets-wordpress-plugin/" target="_blank" rel="noopener">Bitcoin and Altcoin Wallets</a>, you could visit:</p>
<pre><a href="https://wordpress.org/plugins/wallets/advanced/" target="_blank" rel="noopener">https://wordpress.org/plugins/wallets/advanced/</a></pre>
<p>Scraping a static HTML page is easy. For example, it could have been done in PHP using <a href="https://code.google.com/archive/p/phpquery/" target="_blank" rel="noopener">phpQuery</a>. But I decided to use this opportunity as a gentle introduction into learning <a href="http://phantomjs.org/" target="_blank" rel="noopener">PhantomJS</a>. PhantomJS is very useful for black box testing, but it is also suitable for scraping data. Additionally, I would like to scrape the download counts that are not available as part of the static HTML.</p>
<p>The script is now posted on <a href="https://github.com/alex-georgiou/wordpress-plugin-stats-scraper" target="_blank" rel="noopener">github</a>. See the <code>README.md</code> file for usage instructions.</p>
<p style="text-align: center;"><a href="https://github.com/alex-georgiou/wordpress-plugin-stats-scraper" target="_blank" rel="noopener">https://github.com/alex-georgiou/wordpress-plugin-stats-scraper</a></p>
<h2>Running it daily</h2>
<p>The plugin is suitable for running via cron. You should run it once a day.</p>
<p>Keep in mind that tasks running with cron may not have the working directory you expect. And the path variable might be empty. So make sure to specify full paths. Here&#8217;s how it looks like in my crontab:</p>
<pre>0 1 * * * QT_QPA_PLATFORM=offscreen /usr/bin/phantomjs /home/alexg/wordpress-plugin-stats-scraper/wordpress-plugin-stats-scraper.js wallets /home/alexg/wallets-stats.csv</pre>
<p>&nbsp;</p>
<p>The post <a href="https://www.alexgeorgiou.gr/scrape-daily-analytics-wordpress-plugin/">👻 Monitor analytics of a public WordPress plugin using PhantomJS</a> appeared first on <a href="https://www.alexgeorgiou.gr">Alexandros Georgiou</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.alexgeorgiou.gr/scrape-daily-analytics-wordpress-plugin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>😛 How to make pot with WordPress</title>
		<link>https://www.alexgeorgiou.gr/make-pot-wordpress/</link>
					<comments>https://www.alexgeorgiou.gr/make-pot-wordpress/#respond</comments>
		
		<dc:creator><![CDATA[alexg]]></dc:creator>
		<pubDate>Thu, 29 Mar 2018 18:08:46 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[grunt]]></category>
		<category><![CDATA[grunt-po2mo]]></category>
		<category><![CDATA[grunt-pot]]></category>
		<category><![CDATA[grunt-wp-i18n]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[l10n]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[pot]]></category>
		<category><![CDATA[translation]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.alexgeorgiou.gr/?p=241</guid>

					<description><![CDATA[<p>Build translation files to localize a WordPress plugin using grunt. Create separate translation files for the front-end and back-end.</p>
<p>The post <a href="https://www.alexgeorgiou.gr/make-pot-wordpress/">😛 How to make pot with WordPress</a> appeared first on <a href="https://www.alexgeorgiou.gr">Alexandros Georgiou</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>In this article I will detail how to use grunt to build translation files to <a href="https://developer.wordpress.org/plugins/internationalization/localization/" target="_blank" rel="noopener">localize a WordPress plugin</a>. We&#8217;ll create separate translation files for the front-end and back-end (admin area), potentially allowing a translator to translate only one or the other.</em></p>
<h2>Have you tried POT?</h2>
<p>Hopefully you&#8217;ve already used the i18n functions in your PHP code. For example, a simple translatable string would look like:</p>
<pre>$text = <a href="https://developer.wordpress.org/reference/functions/__/" target="_blank" rel="noopener">__</a>( 'Text to internationalize', 'language-domain-slug' );</pre>
<p>The purpose of this article is not to list all the relevant functions, you can look them up <a href="https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/" target="_blank" rel="noopener">here</a>. These are all wrappers to <a href="https://www.gnu.org/software/gettext/" target="_blank" rel="noopener">gettext</a>.</p>
<p>The important thing to note is that you need to run something to generate your <em>Portable Object Template</em> files. These <code>.pot</code> files can then be copied to <em>Portable Object</em> <code>.po</code> files, then translated to <em>Machine Object</em> <code>.mo</code> files. These <code>.mo</code> binaries are finally loaded by the end user&#8217;s WordPress installation to provide the translated strings to the plugin, or theme. No surprises up to here, all of this is standard.</p>
<h2>Grow your own with Grunt!</h2>
<p>What I will present today is an easy way to use <a href="https://gruntjs.com" target="_blank" rel="noopener">grunt</a> to generate the following:</p>
<ol>
<li>Two <code>.pot</code> files, one with the front-end strings and one with the admin area strings, and</li>
<li><code>.mo</code> files for any <code>.po</code> files in your project</li>
</ol>
<p>You will still need to copy the <code>.pot</code> files to <code>.po</code> files manually and provide the translations. Let&#8217;s get started:</p>
<p>The first thing to add to our <code>Gruntfile.js</code> is <a href="https://www.npmjs.com/package/grunt-wp-i18n" target="_blank" rel="noopener">grunt-wp-i18n</a>. This is a grunt plugin that I have found to be a little more flexible than the alternative, <a href="https://www.npmjs.com/package/grunt-pot" target="_blank" rel="noopener">grunt-pot</a>. So, as usual, add this grunt plugin to your dev toolbox:</p>
<div class="highlight shell">
<pre class="line"><span class="source shell">npm install grunt-wp-i18n --save-dev</span></pre>
<div class="line">and then add the following into your Gruntfile, to get the plugin loaded:</div>
<div class="line">
<div class="highlight js">
<pre class="line"><span class="source js"><span class="variable other object js">grunt</span><span class="meta js"><span class="meta delimiter method period js">.</span><span class="entity name function js">loadNpmTasks</span><span class="punctuation definition begin round js">(</span> <span class="string quoted single js"><span class="punctuation definition string begin js">'</span>grunt-wp-i18n<span class="punctuation definition string end js">'</span></span> <span class="punctuation definition end round js">)</span></span><span class="punctuation terminator statement js">;</span></span></pre>
<div class="line">Now we need to configure this build task. We will hide our pot in our usual stash, the <code>/languages</code> directory of our WordPress plugin. I like to keep my source code in version control under <code>/src</code> and copy it over to assemble the build under <code>/build</code>. I keep any <code>.po</code> translations under <code>/src/languages</code>, and auto-generate <code>.pot</code> files into the <code>/build/languages</code> dir. Any <code>.po</code> files are simply copied from the <code>/src</code> to the <code>/build</code> directory. This is a good practice that keeps our pot always fresh!</div>
<pre class="line">makepot: {
    front: {
        options: {
            cwd: 'build',
            potFilename: 'myplugin-front.pot',
            include: [ '/path/to/files', '/more/files', '/etc' ],
            domainPath: 'languages/',
            type: 'wp-plugin'
        }
    },
    admin: {
        options: {
            cwd: 'build',
            potFilename: 'myplugin.pot',
            include: [ '.*' ],
            exclude: [ '/path/to/files', '/more/files', '/etc' ],
            domainPath: 'languages/',
            type: 'wp-plugin'
    }
}</pre>
<div class="line">Notice that in this example there are two files: The <code>myplugin-front.pot</code> file pulls strings from a list of files that make up the front-end, while the <code>myplugin.pot</code> pulls strings from every other thing in my plugin, which would be the admin area.</div>
<blockquote>
<div class="line">Now a translator is free to only translate the front-end, leaving the back-end, which may contain a lot more strings, to its default (English?) language.</div>
</blockquote>
<div class="line">In functions such as <a href="https://developer.wordpress.org/reference/functions/__/" target="_blank" rel="noopener">__()</a>, the second argument is a <em>language domain</em>. People usually set here the plugin&#8217;s slug, but this is not strictly necessary: You can use different domains for e.g. the front-end and the back-end. Here we will use <code>myplugin-front</code> for the front-end and <code>myplugin</code> for the back-end. This has to be done in the PHP code, wherever the i18n functions are used.</div>
</div>
</div>
</div>
<h2 class="line">Make pot</h2>
<div class="line">If all is set up correctly, you can now easily make pot with:</div>
<pre class="line">grunt makepot</pre>
<p class="line">This will make two files in your project, <code>/build/languages/myplugin.pot</code> and <code>/build/languages/myplugin-frontend.pot</code>. Do not commit these files, we&#8217;ll let them auto-generate every time. The <code>/build</code> directory is in my <code>.gitignore</code> list.</p>
<h2 class="line">Using pot</h2>
<div class="line">For your plugin to actually use this, you need to copy the <code>.pot</code> files into <code>.po</code> files. Depending on your language, you will have to use the correct <em>language code</em> in your filename. See the <a href="https://www.gnu.org/software/gettext/manual/gettext.html#Language-Codes" target="_blank" rel="noopener">gettext list of language codes</a> or simply the <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes" target="_blank" rel="noopener">Wikipedia list of ISO 639-1 language codes</a>. For instance, to do a German translation in our example, you would need to copy the following:</div>
<pre class="line">cp build/languages/myplugin-front.pot src/languages/myplugin-front-de_DE.po
cp build/languages/myplugin.pot src/languages/myplugin-de_DE.po</pre>
<div class="line">or to do a translation to Arabic:</div>
<div class="line">
<pre class="line">cp build/languages/myplugin-front.pot src/languages/myplugin-front-ar.po
cp build/languages/myplugin.pot src/languages/myplugin-ar.po</pre>
<div class="line">You will need to check to make sure whether you need to use a <em>country code</em> along with your language code.</div>
<div class="line">Once you have your <code>.po</code> files you can load them up in <a href="https://poedit.net/" target="_blank" rel="noopener">poedit</a> and start translating. Once the translations are ready you can commit them to your source tree.</div>
<h2 class="line">Packaging it all together for shipment</h2>
<div class="line">WordPress will not use your <code>.pot</code> or <code>.po</code> files. You only include these in your plugin so as to help future translators. To actually enable translation you need to convert the <code>.po</code> files to <code>.mo</code> files.</div>
</div>
<p>We&#8217;ll use another grunt plugin, <a href="https://www.npmjs.com/package/grunt-po2mo" target="_blank" rel="noopener">grunt-po2mo</a>. First add it to your project:</p>
<div class="highlight shell">
<pre class="line"><span class="source shell">npm install grunt-po2mo --save-dev</span></pre>
</div>
<p>And add the following into your Gruntfile to load it:</p>
<div class="highlight js">
<pre class="line"><span class="source js"><span class="variable other object js">grunt</span><span class="meta js"><span class="meta delimiter method period js">.</span><span class="entity name function js">loadNpmTasks</span><span class="punctuation definition begin round js">( </span><span class="string quoted single js"><span class="punctuation definition string begin js">'</span>grunt-po2mo<span class="punctuation definition string end js">' </span></span><span class="punctuation definition end round js">)</span></span><span class="punctuation terminator statement js">;</span></span></pre>
</div>
<p>This one requires very little configuration. Add the following target into your Gruntfile:</p>
<pre>po2mo: {
    plugin: {
        cwd: 'src',
        src: 'languages/*.po',
        dest: 'build',
        expand: true
    }
},</pre>
<p>This config expects that the <code>.po</code> files are in the <code>/src/languages</code> directory where we placed them earlier. It places the <code>.mo</code> files in the <code>/build/languages</code> dir. All you need to do for this is:</p>
<pre>grunt po2mo</pre>
<p>You will also need to tell your plugin to actually go and use these <code>.mo</code> files. Easy. Just hook to the <code>plugins_loaded</code> action and load the text domains:</p>
<pre>function action_plugins_loaded() {
    load_plugin_textdomain( 'myplugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
    load_plugin_textdomain( 'myplugin-front', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
} // end function action_plugins_loaded

add_action( 'plugins_loaded', 'action_plugins_loaded' );</pre>
<h2>That&#8217;s it!</h2>
<p>Make sure to include the <code>makepot</code> and <code>po2mo</code> targets in your build task. Finally use <code>grunt-contrib-compress</code> or another plugin to compress your entire build directory to a <code>.zip</code> file that is ready to be installed into WordPress!</p>
<p>Pass it on.</p>
<p>&nbsp;</p>
<p>The post <a href="https://www.alexgeorgiou.gr/make-pot-wordpress/">😛 How to make pot with WordPress</a> appeared first on <a href="https://www.alexgeorgiou.gr">Alexandros Georgiou</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.alexgeorgiou.gr/make-pot-wordpress/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
