<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Aristotle</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/aristotle/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/aristotle//15</id>
    <updated>2013-02-07T12:12:40Z</updated>
    <subtitle>Slicing and dicing the onion, tears running</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>It’s the things we know that just ain’t so</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2013/02/perl-naming-past-and-future.html" />
    <id>tag:blogs.perl.org,2013:/users/aristotle//15.4267</id>

    <published>2013-02-07T12:15:00Z</published>
    <updated>2013-02-07T12:12:40Z</updated>

    <summary>chromatic: Posting grand pronouncements about what Perl 5 has to become or the new name it absolutely must adopt won’t do anything. That’s irrelevant. “What people manning the booths at non-Perl conferences say is the perception of Perl among those...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p><cite><a href="http://www.modernperlbooks.com/mt/2013/02/project-facepalm.html" title="Project “Facepalm”">chromatic</a></cite>:</p>

<blockquote cite="http://www.modernperlbooks.com/mt/2013/02/project-facepalm.html"><p>Posting grand pronouncements about what Perl 5 has to become or the new name it absolutely must adopt won’t do anything. That’s irrelevant.</p></blockquote>

<p>“What people manning the booths at non-Perl conferences say is the perception of Perl among those outside the echo chamber is irrelevant; I know the REAL problems Perl is having: they are the ones we think must be the reason based on our perspective from <em>inside</em> the echo chamber.”</p>

<p>If that still sounds rational to you, try a thought experiment:</p>

<p>“I don’t care what my profiler is telling me. That function does nothing important. I know where the REAL performance problem is, and it’s the one I’ve been thinking has to be optimised all along.”</p>]]>
        
    </content>
</entry>

<entry>
    <title>Making DBI’s type info data usable for its quote method</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2013/01/making-dbi-type-info-useful.html" />
    <id>tag:blogs.perl.org,2013:/users/aristotle//15.4187</id>

    <published>2013-01-09T12:31:34Z</published>
    <updated>2013-01-09T12:41:25Z</updated>

    <summary><![CDATA[I’m putting this here mostly as future copy-paste fodder: my %sql_type = do { my $ti = $dbh-&gt;type_info_all; my $tidx = shift @$ti; my ( $n, $t ) = @$tidx{qw( TYPE_NAME SQL_DATATYPE )}; map {; uc $_-&gt;[$n], $_-&gt;[$t] } @$ti;...]]></summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>I’m putting this here mostly as future copy-paste fodder:</p>

<pre><code>my %sql_type = do {
    my $ti = $dbh-&gt;type_info_all;
    my $tidx = shift @$ti;
    my ( $n, $t ) = @$tidx{qw( TYPE_NAME SQL_DATATYPE )};
    map {; uc $_-&gt;[$n], $_-&gt;[$t] } @$ti;
};
</code></pre>

<p>Now you can say things like <code>$dbh-&gt;quote( $latitude, $sql_type{'DOUBLE'} )</code>. This is useful in situations where you cannot use placeholders, e.g. when generating some kind of <code>fixture.sql</code> file from CSV data.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>A little “state” idiom</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2012/10/if-state-idiom.html" />
    <id>tag:blogs.perl.org,2012:/users/aristotle//15.3950</id>

    <published>2012-10-13T17:30:14Z</published>
    <updated>2012-10-13T17:44:05Z</updated>

    <summary>{ # ... something that needs to be done twice ... if ( not state $first_iteration_done++ ) { # ... something that must only happen after the first time ... redo; } } In general, some form of “if state...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<pre><code>{
    # ... something that needs to be done twice ...

    if ( not state $first_iteration_done++ ) {
        # ... something that must only happen after the first time ...
        redo;
    }
}</code></pre>

<p>In general, some form of “<code>if state $flag</code>” can be used as a “have I been here?” idiom that avoids the need to mention the flag’s identifier anywhere else. Without <code>state</code>, one must repeat oneself some distance away at least to declare the flag in whichever outer scope has the appropriate lifetime.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>A concise forking idiom in pure Perl</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2012/10/concise-fork-idiom.html" />
    <id>tag:blogs.perl.org,2012:/users/aristotle//15.3932</id>

    <published>2012-10-08T09:33:01Z</published>
    <updated>2012-10-23T21:16:53Z</updated>

    <summary>One of the first module I took over as a maintainer on CPAN was Proc::Fork. It is a beautiful interface. It did get a bit uglier in relatively recent times when I added the run_fork wrapper, an unfortunate necessity in...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>One of the first module I took over as a maintainer on CPAN was <a href="https://metacpan.org/module/Proc::Fork">Proc::Fork</a>.</p>

<p>It is a beautiful interface.</p>

<p>It did get a bit uglier in relatively recent times when I added the <code>run_fork</code> wrapper, an unfortunate necessity in certain cases.</p>

<p>But for small single-file-redistributable programs that can be offered to people who are merely users of a Unix system, who do not have any sort of CPAN setup or installation experience, it always felt like a burden to pull in a dependency for something as… <em>insubstantial</em> as this little bit of syntactic sugar:</p>

<pre><code>run_fork {
    child {
        # ...
    }
    parent {
        my $kid = shift;
        # ...
    }
}
</code></pre>

<p>Just the other day, it occurred to me that with <code>given</code>/<code>when</code>, it is easy to construct an idiom for forking that is just as concise, if not self-documenting to the same extent:</p>
]]>
        <![CDATA[<pre><code>given ( fork ) {
    when ( undef ) { die "Couldn't fork: $!\n" }
    when ( 0 ) {
        # ... child code here ...
    }
    default {
        my $kid = $_;
        # ... parent code here ...
    }
}
</code></pre>

<p>If the code is to run on older perls as well (unfortunately 5.8 is <em>still</em> quite widespread), a less elegant version can be constructed with <code>foreach</code>:</p>

<pre><code>for ( scalar fork ) {
    die "Couldn't fork: $!\n" if not defined;
    if ( my $kid = $_ ) {
        # ... parent code here ...
    }
    else {
        # ... child code here ...
    }
}
</code></pre>

<p>[<b>Update:</b> unfortunately, in all perls released to date, <code>fork</code> in list context returns <code>()</code> on failure so it is necessary to spell this <code>scalar fork</code>, ruining the æsthetic. Sigh.]</p>

<p>While by this point we’ve gone a far cry away from the simple explicitness of the Proc::Fork API, to my mind it is still a lot better than the usual (non-)“idiom” without the outer scope:</p>

<pre><code>my $kid = fork;
die "Couldn't fork: $!\n" if not defined $kid;
if ( $kid ) {
    # ... parent code here ...
}
else {
    # ... child code here ...
}
</code></pre>

<p>This leaves <code>$kid</code> declared in the outer scope and leaves the flow control scattered below it in the same scope, with nothing holding together the whole thing visually as one unit – to the point where I get a strong Proc::Fork craving to clean away the chaff…</p>
]]>
    </content>
</entry>

<entry>
    <title>Quote of the day</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2012/09/qotd.html" />
    <id>tag:blogs.perl.org,2012:/users/aristotle//15.3777</id>

    <published>2012-09-02T01:49:02Z</published>
    <updated>2012-09-02T01:52:26Z</updated>

    <summary>Chip Salzenberg: According to John P. Linderman: Barring some sort of formal definitions, the C code determines the language (pretty much what happened to trigger this whole thread) rather than the language determining the parser, and that just seems wrong....</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p><cite><a href="http://www.nntp.perl.org/group/perl.perl5.porters/;msgid=20050118164330.GA4503@perlsupport.com">Chip Salzenberg</a></cite>:</p>

<blockquote>
  <p>According to <cite><a href="http://www.nntp.perl.org/group/perl.perl5.porters/;msgid=200501171126.GAA09154@raptor.research.att.com">John P. Linderman</a></cite>:</p>

<blockquote>
  <p>Barring some sort of formal definitions, the C code determines the
language (pretty much what happened to trigger this whole thread)
rather than the language determining the parser, and that just seems
wrong.</p>
</blockquote>

<p>WRT Perl 5, I&#8217;m afraid that horse is not only out of the barn, but has
wandered off the ranch, joined a wild herd, and sired several foals.</p>

<p></blockquote></p>
]]>
        

    </content>
</entry>

<entry>
    <title>MetaCPAN-on-search.cpan.org update</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2012/09/metacpan-on-searchcpanorg-v2.html" />
    <id>tag:blogs.perl.org,2012:/users/aristotle//15.3775</id>

    <published>2012-09-01T16:08:51Z</published>
    <updated>2012-09-01T16:24:06Z</updated>

    <summary>I’ve uploaded a new version of the GreaseMonkey script I introduced in my last entry (to let you use search.cpan.org for searching but with links to MetaCPAN in the search results). This version is updated for GreaseMonkey 1.0, and also...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    <category term="metasearchcpanorg" label="meta.search.cpan.org" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>I’ve uploaded <a href="http://userscripts.org/scripts/show/142454">a new version</a> of the GreaseMonkey script I introduced in <a href="/users/aristotle/2012/08/metacpan-on-searchcpanorg.html" title="Marrying MetaCPAN to the search.cpan.org search engine">my last entry</a> (to let you use search.cpan.org for searching but with links to MetaCPAN in the search results).</p>

<p>This version is updated for GreaseMonkey 1.0, and also includes a small link at the top right of a search results page which links to the same search on MetaCPAN:</p>

<pre><code>var query = document.querySelector('input[type=text]').value;
if (query) {
    document.querySelector('.t4 small').insertAdjacentHTML('beforeend',' &lt;a id="goto-metacpan"&gt;&amp;#x2192; MetaCPAN&lt;/a&gt;');
    var link = document.getElementById('goto-metacpan');
    var href = 'https://metacpan.org/search?q=' + encodeURIComponent(query);
    link.href = href.replace(/%20/g,'+');
    link.style.setProperty('float','right');
    link.style.setProperty('padding-right','.4em');
    link.style.setProperty('color','inherit');
}
</code></pre>

<p><a href="http://userscripts.org/scripts/show/142454">Easily installable from userscripts.org</a>. Share and enjoy.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Marrying MetaCPAN to the search.cpan.org search engine</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2012/08/metacpan-on-searchcpanorg.html" />
    <id>tag:blogs.perl.org,2012:/users/aristotle//15.3763</id>

    <published>2012-08-29T11:14:35Z</published>
    <updated>2012-09-02T01:55:54Z</updated>

    <summary>I generally like MetaCPAN better than search.cpan.org, but as fREW mentioned in Using search.cpan.org AND metacpan, the latter’s search result ranking algorithm is far superior to the former’s. So fREW’s idea was to use GreaseMonkey – or actually not GreaseMonkey...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    <category term="metasearchcpanorg" label="meta.search.cpan.org" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>I generally like MetaCPAN better than search.cpan.org, but as fREW mentioned in <a href="http://blog.afoolishmanifesto.com/archives/1692">Using search.cpan.org AND metacpan</a>, the latter’s search result ranking algorithm is far superior to the former’s. So fREW’s idea was to use <a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/">GreaseMonkey</a> – or actually not GreaseMonkey – to rewrite the links in search.cpan.org search results so that he could use that site for searching, but go to MetaCPAN for everything else. In fact though, he used <a href="http://defunkt.io/dotjs/">dotjs</a> and took advantage of the built-in jQuery it ships with. Thus his script does not work with vanilla GreaseMonkey.</p>

<p>Here is a version that does. As a bonus, above and beyond fREW’s version, it also only rewrites the distribution and author links rather than just the module links.</p>

<pre><code>// ==UserScript==
// @name        Marry MetaCPAN to the search.cpan.org search engine
// @namespace   http://plasmasturm.org/
// @include     http://search.cpan.org/search?*
// @version     1
// ==/UserScript==

var _rx = new RegExp('^/~([^/]+)(.*)');
var urx = new RegExp('^https://metacpan.org/module/([^/]+)/$');
var rrx = new RegExp('^https://metacpan.org/module/([^/]+/[^/]+)/$');
var anchors = Array.prototype.slice.call(document.querySelectorAll('a[href^="/~"]'));
anchors.forEach(function(anchor){
    var href = anchor.getAttribute('href');
    href = href.replace(_rx, function (m,p1,p2) { return 'https://metacpan.org/module/' + p1.toUpperCase() + p2 });
    href = href.replace(urx, 'https://metacpan.org/author/$1');
    href = href.replace(rrx, 'https://metacpan.org/release/$1');
    anchor.href = href;
});
</code></pre>

<p><a href="http://userscripts.org/scripts/show/142454">And here it is ready to install on userscripts.org</a>. Share and enjoy.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Today&apos;s curiosity</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2012/02/todays-curiosity.html" />
    <id>tag:blogs.perl.org,2012:/users/aristotle//15.2881</id>

    <published>2012-02-28T12:48:41Z</published>
    <updated>2012-02-28T12:50:47Z</updated>

    <summary>use strict; push my @weight, &apos;around&apos;;...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<pre><code>use strict;
push my @weight, 'around';</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>The UTF8 flag and you</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/08/utf8-flag.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.2146</id>

    <published>2011-08-30T10:18:35Z</published>
    <updated>2011-08-30T10:20:25Z</updated>

    <summary>If you are looking at the UTF8 flag in application code then your code is broken. Period. The flag does NOT mean that the string contains character data. It ONLY means that the string contains a character &gt; 255 either...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>If you are looking at the UTF8 flag in application code then your code is broken. Period.</p>

<p>The flag does <em>NOT</em> mean that the string contains character data. It <em>ONLY</em> means that the string contains a character > 255 either now or <em>could</em> have, at some point in the past.</p>

<p>For strings that contain characters > 127 &lt; 256, you have <em>no idea whatsoever</em> about whether the string contains characters or bytes <em>regardless of what the UTF-8 flag says</em>. (For strings with only characters &lt; 128 there is no difference whether they are ASCII or binary, and strings with any characters > 255, must be either all characters – <em>or corrupt</em> (character and binary data mixed together).)</p>

<p>The following will produce a perfect copy of <tt>lolcat.jpg</tt> in <tt>lolol.jpg</tt>:</p>

<pre><code>my $funneh = do { local ( @ARGV, $/ ) = 'lolcat.jpg'; &lt;&gt; };
utf8::upgrade( $funneh );
# now the utf8 flag on $funneh is set!
open my $copy, '&gt;', 'lolol.jpg' or die $!;
print $copy $funneh;</code></pre>

<p>It makes no difference at all that the data was internally UTF-8-encoded at one point! Because those UTF-8-encoded string elements <em>still represented bytes</em>. And the UTF8 flag would not – because it <em>could</em> not, because that’s <em>not what it means</em> – (not) tell you that this is binary data.</p>

<p>So don’t ask it that.</p>

<p>The flag tells perl how the data is <em>stored</em>, it does not tell Perl code what it <em>means</em>. Strings in Perl are, essentially, simply sequences of arbitrarily large integers that know nothing of characters or bytes; and perl has two different internal formats for storing such integer sequences – a compact random-access one that cannot store integers > 255, and a variable-width one that can store anything and just so happens to use the same encoding as UTF-8 because that is convenient. The UTF8 flag just says which of these two <em>formats</em> a string uses. (It has been pointed out many times over the years that the flag should have been called UOK instead, in keeping with the other internal flags.)</p>

<p>If you check the <tt>perldelta</tt> you will in fact find that the major innovation that started in Perl 5.12 and largely completed in 5.14 is to (finally) <em>stop</em> the regex engine from making this exact mistake, namely, it no longer derives semantics about a string from its internal representation.</p>

<p>Whether any particular packed integer sequence represents bytes or characters, in Perl, is for the programmer to know. The strings themselves carry no knowledge of what they are. If you are designing an API in which bytes vs characters is a concern, then in each case it accepts a string you must decide whether you prefer bytes or characters there, then <em>document</em> that this is what you expect, and then write the code so it always treats that string the same way – either always as characters or always as bytes. No trying to magically do the right thing: <em>you can’t</em>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Something for Perl event organisers to take into consideration</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/08/events-need-codes-of-conduct.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.2064</id>

    <published>2011-08-08T15:10:33Z</published>
    <updated>2011-08-08T16:08:35Z</updated>

    <summary>Jacob Kaplan-Moss: I’ve decided this is so important to me that I’ll no longer attend or speak at conferences that don’t adopt and publish a code of conduct. I’ll also be using whatever clout I’ve got to encourage conference organizers...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p><cite><a href="http://www.jacobian.org/writing/codes-of-conduct/" title="Why conferences need a code of conduct">Jacob Kaplan-Moss</a></cite>:</p>

<blockquote cite="http://www.jacobian.org/writing/codes-of-conduct/"><p>I’ve decided this is so important to me that I’ll no longer attend or speak at conferences that don’t adopt and publish a code of conduct. I’ll also be using whatever clout I’ve got to encourage conference organizers to adopt and publish anti-harassment policies. […] So why, given the issues [<i>with codes of conduct that</i>] I outlined above, do I take this so seriously?</p></blockquote>

<p>He makes the point, but does not emphasise it enough in my opinion: the code of conduct is <em>not</em> there to communicate to attendants how or how not to behave (in which capacity it is superfluous with the well-behaved majority and ineffective with perpetrators): it is there to reassure members of minorities that they will be heard and their concerns are understood.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Java humour</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/08/java-humour.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.2041</id>

    <published>2011-08-03T06:09:06Z</published>
    <updated>2011-08-03T06:10:32Z</updated>

    <summary>AbstractSingletonProxyFactoryBean: Convenient proxy factory bean superclass for proxy factory beans that create only singletons....</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p><a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.html">AbstractSingletonProxyFactoryBean</a>:</p>

<blockquote cite="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.html"><p>Convenient proxy factory bean superclass for proxy factory beans that create only singletons. </p></blockquote>
]]>
        

    </content>
</entry>

<entry>
    <title>Bead, ivory, off-white</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/06/bead-ivory-off-white.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.1903</id>

    <published>2011-06-25T02:26:57Z</published>
    <updated>2011-06-25T02:53:37Z</updated>

    <summary>Chromatic makes fun of Alberto. I understand the sarcasm: much of it, I share. (Falling into editorial we seems common in Alberto’s posts.) And yet, Perl From The Outside. Calling it Perl&#160;6 was sensible at the time of its inception,...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p><a href="http://www.modernperlbooks.com/mt/2011/06/perl-perl-5-perl-6-and-names.html" title="chromatic: Perl, Perl 5, Perl 6, and Names">Chromatic makes fun of</a> <a href="http://blogs.perl.org/users/alberto_simoes/2011/06/perl-perl-5-perl-6-and-names.html" title="Alberto Simões: Perl, Perl 5, Perl 6, and names">Alberto</a>. I understand the sarcasm: much of it, I share. (Falling into editorial we seems common in Alberto’s posts.) And yet, <a href="http://www.curmudgeonlysoftware.com/2011/05/23/perl-from-the-outside/" title="Brian Meeker: Perl From The Outside">Perl From The Outside</a>.</p>

<p>Calling it Perl&#160;6 was sensible at the time of its inception, for all the reasons chromatic outlined there in caricature. But the premise and direction of The Language has evolved dramatically since the time its name was chosen. In premise it’s a similar idea now, and at the same time one with naught in common with the original. And still, the name persists.</p>

<p>As programmers we (yes, us, us all, not editorial we) should know of the importance of naming: any good programmer spends a lot of time in agony over variable names and function names.</p>

<p>What we (the editorial, this time) have done here is refactor the entire codebase rug from underneath the variable, yet insistently kept its now-misleading name the same. Become, became: we left the frame.</p>

<p>On the other hand – of course! –, names create. There are no things until there are words to name them. And also: names identify. You don’t rename your son or daughter because they’ve grown and changed.</p>

<p>And Perl&#160;6 is Larry’s baby.</p>

<p>I get that. And yet: <a href="http://www.curmudgeonlysoftware.com/2011/05/23/perl-from-the-outside/" title="Brian Meeker: Perl From The Outside">Perl From The Outside</a>. <a href="http://www.curmudgeonlysoftware.com/2011/05/23/perl-from-the-outside/" title="Brian Meeker: Perl From The Outside">Perl From The Outside</a>.</p>

<p>I don’t know what to say.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Hey Nelson, or, Perceptions</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/06/antiperlconfirmationbias.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.1826</id>

    <published>2011-06-05T22:29:08Z</published>
    <updated>2011-06-06T00:28:24Z</updated>

    <summary>Hey Nelson, While I’m delivering the news, here’s something for you ignorant American backwoods motherfuckers. Some people’s names have “special characters” in them. Like François Rabelais or Björk Guðmundsdóttir or 艾未未. It’s 2011; the only software that can’t handle Unicode...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>Hey <a href="http://www.somebits.com/weblog/tech/bad/username-restrictions.html" title="Nelson Minar: People’s names have spaces">Nelson</a>,</p>

<blockquote>
  <p>While I’m delivering the news, here’s something for you ignorant American backwoods motherfuckers. Some people’s names have “special characters” in them. Like François Rabelais or Björk Guðmundsdóttir or <a href="http://en.wikipedia.org/wiki/Ai_Wei_Wei">艾未未</a>. It’s 2011; the only software that can’t handle Unicode properly is <a href="http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default">Perl</a>. (As if you needed another reason not to use Perl.)</p>
</blockquote>

<p>please quit being an ignorant backwoods motherfucker and stop talking shit about crap you don’t know anything about.</p>

<hr />

<p>To the Perl folk reading this&#x200a;—&#x200a;the problem we’re dealing with in terms of perception nowadays is confirmation bias. Nelson hates Perl, sees one question on StackOverflow that is making the rounds because Tom answered with one of his obsessively detailed (and therefore huge) missives, generalises wildly from a shallow read of the QA, and then – surprise – finds his opinion further confirmed.</p>

<p>I don’t know that there is a way to get out of this bind. <a href="http://www.edge.org/documents/archive/edge.org/conversation/the-argumentative-theory" title="The Argumentative Theory">Reasoning is flawed because it evolved as a means to convince others, not to figure out the best decisions to make</a>. This is why we are addled with so many cognitive biases. That hypothesis also explains why people slip entirely unrelated jabs (or memes in general) into some other argument they’re making, as Nelson did there: a bonding ritual for the likeminded.</p>

<p>Finding a community that largely has no prior opinion of Perl (which likely means it has cohered around something other than programming) might be the only way to overcome this. Cf. BioPerl as an example.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Stop using Locale::Maketext</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/04/stop-using-maketext.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.1633</id>

    <published>2011-04-08T03:14:19Z</published>
    <updated>2011-04-08T03:28:27Z</updated>

    <summary>The following is a translation of a talk given by Steffen Winkler at German Perl Workshop 10, Internationalisierungs-Framework auswählen, in 2010. You can find my translation of the POD on Github. (In fact you are better off reading it there,...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<p>The following is a translation of <a href="http://download.steffen-winkler.de/dpws2010/I18N_STEFFENW.pod">a talk given by Steffen Winkler at German Perl Workshop 10, <i>Internationalisierungs-Framework auswählen</i></a>, in 2010. You can find <a href="https://gist.github.com/909197">my translation of the POD on Github</a>. (In fact you are better off reading it there, because the CSS formatting on <tt>blogs.perl.org</tt> sucks, at least for now. If you’re seeing this in a feed reader, feel free to stay.)</p>

<p>Aside from Steffen’s talk, there is also <a href="http://rassie.org/archives/247">Nikolai Prokoschenko’s rant <i>On the state of i18n in Perl</i></a>, which mentions to some extent the fact that gettext has established workflows as well as supporting software (such as graphical tools) known in many software communities and even outside the open source world, whereas Maketext has… none of that, and is known only to Perl folk.</p>

<p>Be smart. Don’t use Maketext.</p>
]]>
        <![CDATA[<hr />

<h2>Selecting an Internationalization Framework</h2>

<h3>Author</h3>

<p>Steffen Winkler <code>perl-ws@steffen-winkler.de</code></p>

<h3>Bio</h3>

<p>Since 1960, I exist.</p>

<p>I've been programming Perl since the end of 2000,
first privately and then professionally.</p>

<p>Currently I am working at SIEMENS AG in Erlangen,
primarily in the area of web programming.</p>

<p>I have been attending the German Perlworkshop since 2003.</p>

<h3>Abstract</h3>

<p>Why use Locale::TextDomain
when so many frameworks on CPAN use Locale::Maketext?</p>

<p>Following my presentation on DBD::PO in Frankfurt/Main
there was a lively discussion,
both in Frankfurt and at Erlangen-PM.</p>

<p>There are 2 internationalization frameworks on CPAN,
Locale::TextDomain (Perl interface to Uniform Message Translation)
and Locale::Maketext (framework for localization).</p>

<p>What are the differences?</p>

<p>Where are the limits?</p>

<h3>What I want to talk about today</h3>

<p>From source to multilingual application in 2 ways.</p>

<p>No matter what internationalization framework from the CPAN you use
you have to live with limitations.
A good choice greatly reduces them.</p>

<h3>It begins with the application's source code</h3>

<pre><code>print  'You can log out here.';
printf 'He lives in %s, %s.', $town, $address;
printf '%d people live here.', $people;
printf 'These are %d books.', $books;
printf 'He has %s houses in %s, %s.', $houses, $town, $address;
printf '%s books are in %s shelves.', $books, shelves;
</code></pre>

<h3>PO files - what's that?</h3>

<p>PO is an abbreviation for "portable object".</p>

<p>GNU gettext PO files can be used to make programs multilingual.</p>

<p>Along with the original text and its translation
the file contains various comments and flags.</p>

<p>MO files are the binary version of PO files.</p>

<h3>Rewriting to Locale::Maketext::Simple</h3>

<p>Here we use the basic module Locale::Maketext
and a module which reads gettext PO/MO files,
namely Locale::Maketext::Lexicon::Gettext.
Locale::Maketext::Simple exports the function "loc".</p>

<pre><code>[_n] where n = 1, 2, ...
</code></pre>

<p>is the general notation for placeholders.
Within [] a function name can be used as a prefix
followed by its parameters,
separated by ",".
"quant", or "*", is the function name for plural processing.</p>

<pre><code>print loc('You can log out here.');

print loc(
    'He lives in [_1], [_2].',
    $town,
    $address,
);

print loc(
    '[quant,_1,person lives,people live] here.',
    $people,
);
</code></pre>

<p>I have no idea
how to write the following phrase with "quant".
With "quant" you write something along the lines of value followed by unit.
But here the plural form starts before the value.
The problem is that "quant" requires the omission of "_1" in the plural forms
and also the omission of the following space.</p>

<pre><code>print loc(  
    '[myplural,_1,It is _1 book,These are _1 books].',
    # ????????    ^^^^^ ???     ^^^^^^^^^ ???
    $books, 
);

print loc(
    'He has [quant,_1,house,houses] in [_2], [_3].',
    $houses,
    $town,
    $address,
);

print loc(
    '[quant,_1,book is,books are] in [*,_2,shelf,shelves].',
    $books,
    $shelves,
);
</code></pre>

<h3>Rewriting to Locale::TextDomain</h3>

<p>Locale::TextDomain is part of the libintl-perl distribution.
There are several exported functions.
Function names follow a simple scheme.</p>

<pre><code>x for a placeholder,
n for plural and
p for context.
</code></pre>

<p>The order of parameters, when present:</p>

<pre><code>Context,
singular,
plural,
number for plural selection and
finally a hash with placeholder data.
</code></pre>

<p>Not all combinations of n, p and x are implemented.
If you use x without a placeholder
and adhere to the alphabetical order
then <em>_x, _</em>nx, <em>_px und _</em>npx are left.</p>

<pre><code>__('msgid')
__x(
    'msgid',
    name1 =&gt; $value1, name2 =&gt; $value2, ...
)
__n('msgid', 'msgid_plural', $count)
__nx(
    'msgid', 'msgid_plural', $count,
    name1 =&gt; $value1, name2 =&gt; $value2, ...
)
__xn(
    'msgid', 'msgid_plural',
    $count, name1 =&gt; $value1, name2 =&gt; $value2, ...
)
__p('context', 'msgid')
__px(
    'context', 'msgid',
    name1 =&gt; $value1, name2 =&gt; $value2, ...
)
__np('context', 'msgid', 'msgid_plural', $count)
__npx(
    'context', 'msgid', 'msgid_plural', $count,
    name1 =&gt; $value1, name2 =&gt; $value2, ...
)

print __('You can log out here.');

print __x(
    'He lives in {town}, {address}.',
    town    =&gt; $town,
    address =&gt; $address,
);

print __nx(
    '{num} person lives here.',
    '{num} people live here.',
    $people,
    num =&gt; $people,
);



print __nx(
    'It is {num} book.',
    'These are {num} books.',
    $books,
    num =&gt; $books,
);

print __nx(
    'He has {num} house in {town}, {address}.',
    'He has {num} houses in {town}, {address}.',
    $houses,
    num     =&gt; $houses,
    town    =&gt; $town,
    address =&gt; $address,
);

print
    __nx(
        '{num} book is',
        '{num} books are',
        $books,
        num =&gt; $books,
    ),
    __nx(
        ' in {num} shelf.',
        ' in {num} shelves.',
        $shelves,
        num =&gt; $shelves,
    );
</code></pre>

<h3>What do you see at first glance?</h3>

<p>Locale::Maketext has numbered parameters.
If there are many, you may confuse them.
All the translator knows is that something is included, but not what.</p>

<pre><code>[_1] is a [_2] in [_3].
</code></pre>

<p>Locale::Maketext can handle multiple plural forms in a text phrase.</p>

<pre><code>[quant,_1,book is,books are] in [*,_2,shelf,shelves].
</code></pre>

<p>The text in plural forms (quant) is not automatically translatable
because it's contained in a kind of "or" block.</p>

<p>Within this "or" block does placeholders such as _1 are absent.
There no plural forms can be represented
which start before the number.</p>

<pre><code>[myplural,_1,It is _1 book,These are _1 books].
</code></pre>

<p>Of course this "myplural" function does not exist.</p>

<hr />

<p>Locale::TextDomain has named parameters,
which are easier to translate
because the translator can understand the meaning of the sentence
in spite of the placeholders.</p>

<pre><code>{name} is a {locality} in {country}.
</code></pre>

<p>A text phrase containing several plural forms needs to be divided
which makes it not automatically translatable.</p>

<h3>Things you won't spot immediately</h3>

<h4>Number of plural forms</h4>

<p>Locale Maketext:</p>

<pre><code>Singular
Singular + Plural
Singular + Plural + Zero
</code></pre>

<p>Locale::Textdomain:</p>

<pre><code>2 in the source language
arbitrarily many in the target language
</code></pre>

<p>The header of each PO/MO file contains something called "Plural-Forms".
This is a calculation formula, written in C except for one thing,
"OR" is allowed in place of "||".
Different versions are contained in different PO/MO files depending on language.
Locale::Maketext ignores this entry.</p>

<p>German/English:</p>

<pre><code>"Plural-Forms: nplurals=2; plural=n != 1\n";
</code></pre>

<p>Russian:</p>

<pre><code>"Plural-Forms: nplurals=3; plural=n%10==1 &amp;&amp; n%100!=11"
" ? 0 : n%10&gt;=2 &amp;&amp; n%10&lt;=4 &amp;&amp; (n%100&lt;10 || n%100&gt;=20) ? 1 : 2;\n"
</code></pre>

<p>An example from the Russian language:</p>

<pre><code>0          books -&gt; книг  (Plural 2)
1          book  -&gt; книга (Singular)
2 .. 4     books -&gt; книги (Plural 1)
5 .. 20    books -&gt; книг  (Plural 2)
21         books -&gt; книга (Singular)
22 .. 30   books -&gt; книг  (Plural 2)
...
100        books -&gt; книг  (Plural 2)
101        books -&gt; книга (Singular)
102 .. 104 books -&gt; книги (Plural 1)
105 .. 120 books -&gt; книг  (Plural 2)
121        book  -&gt; книга (Singular)
122 .. 124 books -&gt; книги (Plural 1)
125 .. 130 books -&gt; книг  (Plural 2)
...
</code></pre>

<p>3 plural forms also exist in e.g. Czech, Lithuanian, Polish, Romanian, Slovak.
4 plural forms exist in eg. Slovenian and Celtic.
So in the EU we can get by with 4 plural forms.
Arabic has 6 has plural forms.</p>

<p>Because Locale::Maketext ignores "Plural-Forms" in PO/MO files,
it can only support languages with 2 plural forms,
that is, singular and plural,
such as we know from German and English.
There is a function "quant"
which in principle corresponds to "quant2" (singular + 1st plural)
assuming we ignore the zero form.
One could define functions "quant3" to "quant6" for Locale::Maketext
But then the programmer would need to already know
which text phrases need 2, 3, 4, 5 or 6 plural forms.
Because he does not know, he would have to always use "quant6".
That's a whole lot of typing.</p>

<h4>Position of words in a sentence in different languages</h4>

<p>The position of the individual words can differ in different languages
e.g. in one language it is</p>

<pre><code>I have 2 books.
</code></pre>

<p>and in another</p>

<pre><code>2 books I have.
</code></pre>

<p>If that is so,
then with Locale::Maketext you have to write complete sentences as the plural forms.
The English-native programmer cannot know that.
The conflict is thus only discovered during translation.</p>

<p>If you want to avoid the conflict,
you always write entire sentences.</p>

<p>But even that doesn't always work,
because Locale::Maketext always expects "quant" to be followed by "_1"
and then implicitly adds a space
and then the text.</p>

<p>Yet what's needed is:</p>

<pre><code>[myplural,_1,It is _1 book.,These are _1 books.]
</code></pre>

<p>But then that's nothing else than Locale::TextDomain.</p>

<h4>Comma in plural forms, or the "join and can never split" trap</h4>

<p>Due to the use of commas as separators
no commas may exist in enumerating texts.</p>

<p>Is there any simple quoting mechanism as in Text::CSV?
I know of none.</p>

<pre><code>I need 1 book, computer or notebook to do this.
</code></pre>

<p>Here's a dirty workaround using ";".</p>

<pre><code>I need [*_1,book; computer or notebook,books; computers or notebooks] to do this.
</code></pre>

<h4>Value and unit may be wrapped</h4>

<p>Due to string concatenation using spaces
line breaks may occur between value and unit.</p>

<p>Depending on line length you get</p>

<pre><code>I have
1 book.
</code></pre>

<p>or</p>

<pre><code>I have 1
book.
</code></pre>

<p>With Locale::TextDomain you can write:</p>

<pre><code>I have {num}\N{NO-BREAK SPACE}book.
I have {num}\N{NO-BREAK SPACE}books.
</code></pre>

<p>In Locale::Maketext the space is hardwrite in the module code.</p>

<h3>Excerpt from a PO file for Locale::Maketext</h3>

<pre><code># header
msgid ""
msgstr ""
"...\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"..."

msgid  "You can log out here."
msgstr "Sie können sich hier abmelden."

msgid  "He lives in %1, %2."
msgstr "Er wohnt in %1, %2."

msgid  "%quant(%1,person lives,people live) here."
msgstr "%quant(%1,Mensch wohnt,Menschen wohnen) hier."


# a bad workaround (no singular before placeholder)
msgid  "This are %quant(%1,book,books)."
msgstr "Das sind %quant(%1,Buch,Bücher)."

msgid  "%quant(%1,book is,books are) in %quant(%2,shelf,shelves)."
msgstr "%quant(%1,Buch ist,Bücher sind) in %quant(%2,Regal,Regalen)."
</code></pre>

<h3>extract from the PO file for Locale::TextDomain</h3>

<pre><code># header
msgid ""
msgstr ""
"...\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"..."

msgid        "You can log out here."
msgstr       "Sie können sich hier abmelden."

msgid        "He lives in {town}, {address}."
msgstr       "Er wohnt in {town}, {address}."

msgid        "{num} person lives here."
msgid_plural "{num} people live here."
msgstr[0]    "{num} Mensch wohnt hier."
msgstr[1]    "{num} Menschen wohnen hier."

msgid        "It is {num} book."
msgid_plural "These are {num} books."
msgstr[0]    "Es ist {num} Buch."
msgstr[1]    "Es sind {num} Bücher."

msgid        "He has {num} house in {town}, {address}."
msgid_plural "He has {num} houses in {town}, {address}."
msgstr[0]    "Er hat {num} Haus in {town}, {address}."
msgstr[1]    "Er hat {num} Häuser in {town}, {address}."

msgid        "{num} book is"
msgid_plural "{num} books are"
msgstr[0]    "{num} Buch ist"
msgstr[1]    "{num} Bücher sind"

msgid        " in {num} shelf."
msgid_plural " in {num} shelves.
msgstr[0]    " in {num} Regal."
msgstr[1]    " in {num} Regalen."
</code></pre>

<h3>PO file for English/Russian translation</h3>

<h4>for Locale::Maketext</h4>

<pre><code># header
msgid ""
msgstr ""
"...\n"
"Plural-Forms: nplurals=3; plural=n%10==1 &amp;&amp; n%100!=11"
" ? 0 : n%10&gt;=2 &amp;&amp; n%10&lt;=4 &amp;&amp; (n%100&lt;10 || n%100&gt;=20) ? 1 : 2;\n"
"..."

msgid  "You can log out here."
msgstr "Выход из системы."

# Hier wäre Beugung des Stadtnamens notwendig: 
# Москва -&gt; в Москве
# Киев   -&gt; в Киеве
# Мытищи -&gt; в Мытищах (nicht regulär)
msgid  "He lives in %1, %2."
msgstr "Он живет в %1, %2"

# This is not correctly translatable.
# The plural form for number 2 to 4 (человека живут) is not storable.
msgid  "%quant(%1,person lives,people live) here."
msgstr "%quant(%1,человек живет,человек живут) здесь."

# This is not correctly translatable.
# The plural form for number 2 to 4 (дома) is not storable.
msgid  "He has %quant(%1,house,houses) in %2, %3."
msgstr "У него %quant(%1,дом,домов) в %2, %3."


# This is not correctly translatable.
# The plural form for number 2 to 4 (книги) is not storable.
msgid  "%quant(%1,book is,books are) in %quant(%2,shelf,shelves)."
msgstr "%quant(%1,книга,книг) на %quant(%1,полке,полках)."
</code></pre>

<h4>for Locale::TextDomain</h4>

<pre><code># header
msgid ""
msgstr ""
"...\n"
"Plural-Forms: nplurals=3; plural=n%10==1 &amp;&amp; n%100!=11"
" ? 0 : n%10&gt;=2 &amp;&amp; n%10&lt;=4 &amp;&amp; (n%100&lt;10 || n%100&gt;=20) ? 1 : 2;\n"
"..."

msgid        "You can log out here."
msgstr       "Выход из системы."

# Hier wäre Beugung des Stadtnamens notwendig: 
# Москва -&gt; в Москве
# Киев   -&gt; в Киеве
# Мытищи -&gt; в Мытищах (nicht regulär)
msgid        "He lives in {town}, {address}."
msgstr       "Он живет в {town}, {address}."

msgid        "{num} person lives here."
msgid_plural "{num} people live here."
msgstr[0]    "{num} человек живет здесь."
msgstr[1]    "{num} человека живут здесь."
msgstr[2]    "{num} человек живут здесь."

msgid        "It is {num} book."
msgid_plural "These are {num} books."
msgstr[0]    "Это {num} книга."
msgstr[1]    "Это {num} книги."
msgstr[2]    "Это {num} книг."

msgid        "He has {num} house in {town}, {address}."
msgid_plural "He has {num} houses in {town}, {address}."
msgstr[0]    "У него {num} дом в {town}, {address}."
msgstr[1]    "У него {num} дома в {town}, {address}."
msgstr[2]    "У него {num} домов в {town}, {address}."

# Translate this phrase together with the next one.
msgid        "{num} book is"
msgid_plural "{num} books are"
msgstr[0]    "{num} книга"
msgstr[1]    "{num} книги"
msgstr[2]    "{num} книг"

# Translate this phrase together with the previous one.
msgid        " in {num} shelf."
msgid_plural " in {num} shelves."
msgstr[0]    " на {num} полке."
msgstr[1]    " на {num} полках."
msgstr[2]    " на {num} полках."
</code></pre>

<h4>Inflecting "in {town}"</h4>

<pre><code>Berlin    -&gt; Берлин
in Berlin -&gt; в Берлине
</code></pre>

<p>If you want this,
you need to also translate placeholder values
and only them insert them.</p>

<p>That's doable,
but it makes it impossible to automatically translate the phrase
in which it is to be inserted.
Moreover, that one is then also hard to translate manually
because again to some extent the context is lost.</p>

<p>You can only tinker.</p>

<h3>neutral / masculin / feminine singular / plural</h3>

<p>Inflection of nouns:</p>

<pre><code>maskulin singular -&gt; Arzt
feminin singular  -&gt; Ärztin
maskulin plural   -&gt; Ärzte
feminin plural    -&gt; Ärztinnen
</code></pre>

<p>Inflection of verbs:</p>

<pre><code>Mascha ist zur Schule gegangen. -&gt; Маша пошла в школу.
Petja ist zur Schule gegangen.  -&gt; Петя пошёл в школу.
</code></pre>

<h3>Context</h3>

<pre><code>msgid   "design"
msgstr  "Design"

msgctxt "automobile"
msgid   "design"
msgstr  "Konstruktion"

msgctxt "verb"
msgid   "design"
msgstr  "zeichnen"
</code></pre>

<h3>Locale::Maketext::TPJ13 - Article by Sean M. Burke about software localization</h3>

<p>He writes:</p>

<p>Since I wrote this article in 1998,
I now see that the gettext docs are now trying more to come to terms with plurality.
Whether useful conclusions have come from it is another question altogether.
--- SMB, May 2001</p>

<p>It is many years later now and a jack of all trades still does not exist.</p>

<h3>Software for translation agencies</h3>

<p>In the current case known to me
the translation agency uses the software "SDL Trados".
Like other similar software it is based on a "translation memory".
This works very well for static documents.</p>

<p>For dynamism,
which exists in software localization due to plural and context,
such a software seems less suited.
It assumes a 1:1 relation in translations.
Therefor one has to expect
that the relatively small portion needing context or plural forms
can not well be accomplished with aid from software.</p>

<p>In the current case the POT file had to be converted into XML
and the target language had to be filled from the source language.
This kind of work would normally be expected from the translation agency.</p>

<p>Recommendation:
Have a translation done with a smaller test file.
This should contain all the typical constructs.
Do this per language, because subcontractors may be involved.</p>

<h3>Bibliography</h3>

<ul>
<li>GNU gettext</li>
</ul>

<p><em>wikipedia</em> <a href="http://en.wikipedia.org/wiki/Gettext">http://en.wikipedia.org/wiki/Gettext</a></p>

<p><em>gettext homepage</em> <a href="http://www.gnu.org/software/gettext/gettext.html">http://www.gnu.org/software/gettext/gettext.html</a></p>

<ul>
<li>Singular, Plural, Dual, Trial, Quadral</li>
</ul>

<p><em>wikipedia - dual</em> <a href="http://en.wikipedia.org/wiki/Dual_%28grammatical_number%29">http://en.wikipedia.org/wiki/Dual_%28grammatical_number%29</a></p>

<p><em>wikipedia - all forms</em> <a href="http://en.wikipedia.org/wiki/Sursurunga_language">http://en.wikipedia.org/wiki/Sursurunga_language</a></p>

<p><em>sourceforge - which language - which plural form</em> <a href="http://translate.sourceforge.net/wiki/l10n/pluralforms">http://translate.sourceforge.net/wiki/l10n/pluralforms</a></p>

<ul>
<li>CPAN module Locale::Maketext</li>
</ul>

<p><em>CPAN</em> <a href="http://search.cpan.org/dist/Locale-Maketext/">http://search.cpan.org/dist/Locale-Maketext/</a></p>

<ul>
<li>CPAN module Locale::Maketext::Simple</li>
</ul>

<p><em>CPAN</em> <a href="http://search.cpan.org/dist/Locale-Maketext-Simple/">http://search.cpan.org/dist/Locale-Maketext-Simple/</a></p>

<ul>
<li>obsolete article by Sean M. Burke about software localization</li>
</ul>

<p><em>CPAN</em> <a href="http://search.cpan.org/perldoc?Locale::Maketext::TPJ13">http://search.cpan.org/perldoc?Locale::Maketext::TPJ13</a></p>

<ul>
<li>CPAN module Locale::TextDomain</li>
</ul>

<p><em>CPAN</em> <a href="http://search.cpan.org/dist/libintl-perl/">http://search.cpan.org/dist/libintl-perl/</a></p>

<ul>
<li>Thanks for the support, the many ideas, examples and corrections.</li>
</ul>

<p><em>Nikolai Prokoschenko</em> <a href="http://rassie.org/">http://rassie.org/</a></p>

<p><em>Nikolai Prokoschenko - On the state of i18n in Perl</em> <a href="http://rassie.org/archives/247">http://rassie.org/archives/247</a></p>
]]>
    </content>
</entry>

<entry>
    <title>Today&apos;s lyrical excursion Perl perversion</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/aristotle/2011/02/todays-lyrical-excursion-perl-perversion.html" />
    <id>tag:blogs.perl.org,2011:/users/aristotle//15.1469</id>

    <published>2011-02-15T15:23:34Z</published>
    <updated>2011-02-16T17:46:54Z</updated>

    <summary>perl -e &apos;my (my (my (my (my (my $puerto_rico)))))&apos;...</summary>
    <author>
        <name>Aristotle</name>
        <uri>http://plasmasturm.org/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/aristotle/">
        <![CDATA[<pre><code>perl -e 'my (my (my (my (my (my $<a href="http://www.youtube.com/watch?v=MrlE61blt1g" title="Vaya Con Dios">puerto_rico</a>)))))'</code></pre>
]]>
        

    </content>
</entry>

</feed>
