<?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>Internationalisation Tips &#187; Translations</title>
	<atom:link href="http://internationalisationtips.com/tag/translations/feed/" rel="self" type="application/rss+xml" />
	<link>http://internationalisationtips.com</link>
	<description>practical tips on building an international presence</description>
	<lastBuildDate>Wed, 24 Aug 2011 14:20:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Translating dynamic text strings</title>
		<link>http://internationalisationtips.com/2009/03/24/translating-dynamic-text-strings/</link>
		<comments>http://internationalisationtips.com/2009/03/24/translating-dynamic-text-strings/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 13:24:15 +0000</pubDate>
		<dc:creator>Isofarro</dc:creator>
				<category><![CDATA[Translations]]></category>
		<category><![CDATA[internationalisation]]></category>
		<category><![CDATA[localisation]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[tokens]]></category>
		<category><![CDATA[variables]]></category>

		<guid isPermaLink="false">http://www.internationalisationtips.com/?p=17</guid>
		<description><![CDATA[Translating text dynamically generated at request time is more complicated than static non-changing text. Depending on the reason why the text needs to be flexible at request time means taking a different approach. In the last post we looked at simple static text replacement where the text doesn&#8217;t change from request to request. But as [...]]]></description>
			<content:encoded><![CDATA[<p>Translating text dynamically generated at request time is more complicated than static non-changing text. Depending on the reason why the text needs to be flexible at request time means taking a different approach.</p>
<p>In the last post we looked at <a href="http://www.internationalisationtips.com/2009/03/24/replacing-static-text-strings-with-references/">simple static text replacement</a> where the text doesn&#8217;t change from request to request. But as soon as we use conditionals to build up a text string this simple lookup method is no longer sufficient.</p>
<h3>Simple data inclusion</h3>
<p>The simplest of dynamic text examples we have is a message telling us which page we are on.</p>
<pre><code>
&lt;?php
$pageNo = 6;
echo "You are currently on page ", $pageNo;
?&gt;
</code></pre>
<p>The first pitfall to avoid is to resist creating a translation string for the static-looking text <q>You are currently on page</q>. Yes, this is a static piece of text, but it requires additional context for the message to make sense. This is done in the code by tacking on the page number at the end of the string. The resulting string is <q>You are currently on page 16</q> which makes sense without further context.</p>
<p>This works in English, but in other languages it may not be appropriate, or grammatically correct for the page number to be at the end. We need to ensure that the placement of the page number is as flexible as possible.</p>
<p>The most straightforward solution is to use a token to represent the <code>$pageNo</code> variable in the text string. And at request time replace these tokens with their variable amounts. This is a three step process:</p>
<ul>
<li>Refactor the static looking text to use a text replacement</li>
<li>Process the refactored string at request time</li>
<li>Add the refactored string to the translation table</li>
</ul>
<p>The commonly accepted practice for tokens is to use a single word wrapped in curly brackets. I&#8217;d recommend this approach because translation strings are independent of any language limitations, it&#8217;s easy to do replacement in PHP. And if you need to use these translations in JavaScript then YUI&#8217;s <a href="http://developer.yahoo.com/yui/docs/YAHOO.lang.html#method_substitute"><code>YAHOO.lang.substitute()</code></a> handles curly bracket replacement right out of the box. (The alternative is <code>sprintf</code>&#8216;s <code>%s</code> syntax, but be careful if there are multiple tokens that could be in a different order to what you&#8217;d expect)</p>
<pre><code>
&lt;?php
// Step 1: Refactor string
$pageNo = 6;
$pageMsg = "You are currently on page {page}";
echo $pageMsg;
?&gt;
</code></pre>
<p>With this refactoring we are basically just echoing out a static string that&#8217;s sitting in a new variable. Between defining the variable and writing it out we need to add in some extra code to replace <code>{page}</code> with the actual page number:</p>
<pre><code>
&lt;?php
// Step 2: Replace tokens
$pageMsg = "You are currently on page {page}";
$pageMsg = preg_replace('/{page}/', $pageNo, $pageMsg);
echo $pageMsg;
?&gt;
</code></pre>
<p>The <code>preg_replace</code> looks for an occurrence of <samp>{page}</samp> and replaces it with the contents of the variable <code>$pageNo</code>.</p>
<p>Now we can treat the starting string as a static text string and add it to our translations array:</p>
<pre><code>
&lt;?php
$translations = array(
	"pageMessage" => "You are currently on page {page}";
);
?&gt;
</code></pre>
<p>And update our main code to reference this translation</p>
<pre><code>
&lt;?php
// Step 3: Add to the translations dictionary
$pageMsg = $translations['pageMessage'];
$pageMsg = preg_replace('/{page}/', $pageNo, $pageMsg);
echo $pageMsg;
?&gt;
</code></pre>
<p>The benefit of this approach is that the token can be anywhere in the string and now requires no code modifications if in one language the token needs to be somewhere other than at the end. We&#8217;ve removed the locale dependencies.</p>
<h3>Grammatical differences</h3>
<p>One of the difficult problems of creating text on the fly is grammatical differences between languages. We have to be careful where our code is implementing grammar rules. For example, here&#8217;s a PHP snippet that prints out the number of unread email items:</p>
<pre><code>
&lt;?php
$unread = 2;
echo $unread, " unread email", ($unread==1)?'':'s';
?&gt;
</code></pre>
<p>This just about works in English. But translating for a different locale we can&#8217;t assume the same grammar rules apply. Obviously pluralising a word isn&#8217;t as straightforward as adding the letter &#8216;s&#8217; to the end.</p>
<p>This particular piece of code needs to be refactored to remove the grammar logic, and then it is in a state to be localised. The obvious first step, along with our text replacement token, is to remove the conditional logic and create two separate text strings:</p>
<pre><code>
&lt;?php
$unread = 2;

// Select the right message
$unreadMsg = "{total} unread emails";
if ($unread==1) {
	$unreadMsg = "{total} unread email";
}

// Replace the token
$unreadMsg = preg_replace('/{total}/', $unread, $unreadMsg);

echo $unreadMsg;
?&gt;
</code></pre>
<p>And we are back into the normal lines of replacing static text with a reference to a translation. (Although Polish pluralisation is more complicated, so would need more logic or perhaps a different approach &#8211; hat tip <a href="http://intranation.com/">Brad</a>).</p>
<h3>String translation libraries</h3>
<p>It becomes a little tedious to create a regex rule for every token that needs to be replaced. And there are classes or libraries to do this for just about any web-facing programming language. A very elegant solution is <a href="http://ejeliot.com/">Ed Eliot&#8217;s</a> PHP 5 <a href="http://www.ejeliot.com/blog/114">text translation library</a>.</p>
<p>Ed&#8217;s class gets the basics right:</p>
<ul>
<li>Translations are in a separate file, one per language</li>
<li>Specifying the language code and it grabs the right translations file</li>
<li>the <code>Get</code> method takes an array of token replacements, and applies them to the translations for you</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://internationalisationtips.com/2009/03/24/translating-dynamic-text-strings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Avoid text image buttons</title>
		<link>http://internationalisationtips.com/2009/01/27/avoid-text-image-buttons/</link>
		<comments>http://internationalisationtips.com/2009/01/27/avoid-text-image-buttons/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 16:20:50 +0000</pubDate>
		<dc:creator>Isofarro</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[buttons]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[fonts]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[sliding doors]]></category>
		<category><![CDATA[style]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[Translations]]></category>

		<guid isPermaLink="false">http://www.internationalisationtips.com/?p=3</guid>
		<description><![CDATA[Localising sites should not be about recreating the same images over and over with different text and then spending days fixing layout bugs as each locale needs a different widths to comfortably fit in each text label.]]></description>
			<content:encoded><![CDATA[<p>Styling buttons are a nightmare for web developers, thanks to the inconsistent cross-browser and cross-platform handling. So we take the easy way out and cut out the button image from the design mocks, save it in an image, and replace the default button with our new image.</p>
<p>Using images for buttons is nothing new. Accessibility wise, all you really need is some way of specifying a text-equivalent to the image, and you are essentially done.</p>
<p>The two main techniques of using imaged buttons are using the input type of image, or a button element styled with image replacement.</p>
<p>Typically the size of the image button comes directly from the design specification, which means that the text on the button has actually been a design decision, and the page design has taken that into consideration.</p>
<p>The result is a button that cannot be internationalised, for the following reasons:</p>
<ul>
<li>translating the button text means creating a new image for each translation</li>
<li>the size of each image now has to change to accommodate the translated text.</li>
</ul>
<p>There are two sane approaches to dealing with this situation, and it depends on the willingness of your designers to compromise in favour of international-friendly designs. But both solutions involve reimplementing the button markup, and if there are JavaScript event-handlers registered, there&#8217;s a strong possibility that these would need to be updated to take into account the changed markup.</p>
<p>The first solution is to get rid of the button image entirely, and use a proper submit input button. Then use CSS to style the button away from the default set into something closer to the original design, compromising the exacting details of text-shadows, rounded corners.</p>
<p>Designs that require a particular font, with specific kerning and other font metrics are unfit for internationalising websites, unless you can get your designer to guarantee that they will create and supply all the button images you need for every localisation from now on.</p>
<p>The second solution is to get the design team to create a tile-able button background big enough to cater for any reasonable width of text. Then using a sliding doors technique, a button element (or a cleverly marked-up submit button) can be styled to produce an elastic button background. All that&#8217;s left is to style the font of the real text as closely as reasonably possible to the original design specification.</p>
<p>By making the actual text back into real text your existing ways of translating text can be used, and localising forms becomes a matter of translations and other unique locale-specific requirements, not laboriously dealing with image manipulation.</p>
<p>Text inside images cause headaches in localising sites. It is far better to spend more time upfront coming up with a reasonable compromise that is based on text being real text, not an image.</p>
]]></content:encoded>
			<wfw:commentRss>http://internationalisationtips.com/2009/01/27/avoid-text-image-buttons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

