<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Joe Gornick</title>
	
	<link>http://joegornick.com</link>
	<description>Web Geekology 101</description>
	<lastBuildDate>Mon, 24 Jan 2011 15:13:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/jgornick" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="jgornick" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Setting up multiple browsers on Mac OS X</title>
		<link>http://joegornick.com/2010/01/14/setting-up-multiple-browsers-on-mac-os-x/</link>
		<comments>http://joegornick.com/2010/01/14/setting-up-multiple-browsers-on-mac-os-x/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 17:06:26 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://joegornick.com/?p=116</guid>
		<description><![CDATA[<p><a href="http://joegornick.com/wp-content/uploads/2010/01/browsers.jpg"><img class="alignleft size-medium wp-image-117" title="Multiple Browsers on Mac OS X" src="http://joegornick.com/wp-content/uploads/2010/01/browsers-300x213.jpg" alt="Multiple Browsers on Mac OS X" width="300" height="213" /></a> When doing web development, you need to test your work on many operating systems and browsers.  Depending on your host operating system, you will also need to run virtual machines to test other operating systems and browsers.  For this article, we are focusing on setting up different browsers/version on OS X (10.6 &#8211; Snow Leopard).</p>
<p><a href="http://joegornick.com/2010/01/14/setting-up-multiple-browsers-on-mac-os-x/" class="more-link">Read more on Setting up multiple browsers on Mac OS X&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p><a href="http://joegornick.com/wp-content/uploads/2010/01/browsers.jpg"><img class="alignleft size-medium wp-image-117" title="Multiple Browsers on Mac OS X" src="http://joegornick.com/wp-content/uploads/2010/01/browsers-300x213.jpg" alt="Multiple Browsers on Mac OS X" width="300" height="213" /></a> When doing web development, you need to test your work on many operating systems and browsers.  Depending on your host operating system, you will also need to run virtual machines to test other operating systems and browsers.  For this article, we are focusing on setting up different browsers/version on OS X (10.6 &#8211; Snow Leopard).</p>
<p>For Mac, the most common browsers are Safari, Firefox, Opera and recently Chrome.  On my machine, I have setup the following browsers and versions:</p>
<ul>
<li>Safari: 2.04, 3.04, 3.12, 3.21, 4.04</li>
<li>Firefox: 2.0.0.20, 3.0.17, 3.5.7</li>
<li>Opera: 9.52, 9.64, 10.01, 10.10</li>
<li>Chrome: 4.0.249.49 (Latest)</li>
</ul>
<p>Well, let&#8217;s get to it!</p>
<p>First, I setup a folder in my Applications called Browsers (<code>/Applications/Browsers</code>).  I will explain later why we place all of our browsers in the Browsers folder.  Now, let&#8217;s install each browser individually.</p>
<h3>Safari</h3>
<p>Since I&#8217;m running OS X 10.6 with latest updates, Safari version 4.04 is installed.  So, in order to install previous versions, I use <a href="http://michelf.com/projects/multi-safari/" target="_blank">Multi Safari</a>.  Multi Safari provides different versions of Safari with the specified WebKit bundled into the application.</p>
<p>To install, you simply download the files, and extract to our <code>/Applications/Browsers</code> directory.  All of the applications are named appropriately and ready to execute.  To my knowledge, there isn&#8217;t any profile management we need to perform unlike Firefox and Opera.</p>
<h3>Firefox</h3>
<p>To get started, we need to download the specific versions.  During the time of writing, 3.5.7 was the latest version.  I was able to download easily from <a href="http://www.mozilla.com" target="_blank">mozilla.com</a>.  Next we need to find archived versions.  These are located on <a href="http://ftp.mozilla.org/pub/mozilla.org/mozilla.org/firefox/releases/" target="_blank">Mozilla&#8217;s FTP server</a>.  Once you&#8217;ve downloaded the versions you&#8217;re interested in, let&#8217;s start the installation process.</p>
<p>In order to run multiple instances of Firefox, I&#8217;ve found the best way is to create a different profile for each version use that profile when launching the browser.  Since I&#8217;m only interested in 2.x, 3.0.x and 3.5.x, I like to start with the oldest version first.  So, copy the Firefox application over to our <code>/Applications/Browsers</code> directory.  Once installed, we need to immediately rename it.  I renamed my to <code>Firefox 2</code>.</p>
<p>Next, let&#8217;s modify the script to launch Firefox and setup our profile.  Open up Terminal and perform the following commands:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>Applications<span style="color: #000000; font-weight: bold;">/</span>Browsers<span style="color: #000000; font-weight: bold;">/</span>Firefox\ 2.app<span style="color: #000000; font-weight: bold;">/</span>Contents<span style="color: #000000; font-weight: bold;">/</span>MacOS
<span style="color: #c20cb9; font-weight: bold;">mv</span> firefox-bin firefox.bin
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">'!#/bin/bash'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> firefox-bin
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">'/Applications/Browsers/Firefox\ 2.app/Contents/MacOS/firefox.bin -P firefox2 -no-remote'</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> firefox-bin
<span style="color: #c20cb9; font-weight: bold;">chmod</span> +x firefox-bin</pre></div></div>

<p>The previous commands essentially rename <code>firefox-bin</code> to <code>firefox.bin</code> and create a new bash script to execute <code>firefox.bin</code> with a specified profile and to tell Firefox that it&#8217;s OK to run more than one instance.  You may be asking yourself, why is <code>firefox-bin</code> so important?  Well, <code>firefox-bin</code> is the bundle executable (<code>CFBundleExecutable</code>) according to the <code>Info.plist</code> in <code>Firefox 2.app</code>.  This means, when you load the application, it executes <code>firefox-bin</code>.  You can look at other command line arguments <a href="http://kb.mozillazine.org/Command_line_arguments" target="_blank">here</a>.</p>
<p>Now, before you run the application, let&#8217;s setup our &#8220;firefox2&#8243; profile. In the same directory, enter command: <code>./firefox.bin -ProfileManager</code>.  This will prompt you with the Firefox profile manager where you will want to create a new profile labeled &#8220;firefox2&#8243; (which is what we used as the <code>-P</code> argument in <code>firefox-bin</code>).  Once you&#8217;ve created the profile, exit from the profile manager and try loading the application by double clicking on it through Finder.</p>
<p>These steps can be repeated for each specific version you want to install.  Just keep in mind, the rule I follow is to create a new profile for each version being installed.  So, for example, Firefox 3.5, I would create a &#8220;firefox35&#8243; profile and setup my <code>firefox-bin</code> to load it.</p>
<p>A few notes:</p>
<ul>
<li>If you installed OS X with the &#8220;Case-sensitive, Journaled&#8221; file system, multiple Firefox instances do not seem to work.  If you find a work-around, please let me know, I had to re-install after having an unsuccessful attempt.</li>
<li>I like to tell my different versions of Firefox to not update automatically.  However, if you forget and it updates, you will simply need to follow the previous steps after the update has been applied.</li>
</ul>
<h3>Opera</h3>
<p>I&#8217;ve provided a link to the <a href="http://www.opera.com/browser/download/?os=mac&amp;list=all" target="_blank">Download for Mac OS X</a> on Opera&#8217;s website.  This link also contains another link to more archived versions.</p>
<p>The steps taken after downloading your versions are somewhat similar to how we handled Firefox.  So, I will use the example of starting with the oldest version I&#8217;ve decided to install, 9.52.  So, copy the Opera application over to our <code>/Applications/Browsers</code> directory.  Once installed, we need to immediately rename it to <code>Opera 9.52</code>.</p>
<p>In order to keep individual profiles of Opera, you need to provide a <code>PrefsSuffix</code> file in the <code>/Applications/Browsers/Opera 9.52.app/Content/Resources</code> directory of the application.  This file will tell Opera what suffix needs to be added to the preferences folder created in <code>~/Library/Preferences</code>.  Use the following command to set this up:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">'9.52'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>Applications<span style="color: #000000; font-weight: bold;">/</span>Browsers<span style="color: #000000; font-weight: bold;">/</span>Opera\ 9.52.app<span style="color: #000000; font-weight: bold;">/</span>Contents<span style="color: #000000; font-weight: bold;">/</span>Resources<span style="color: #000000; font-weight: bold;">/</span>PrefsSuffix</pre></div></div>

<p>That&#8217;s it!  Now you can run the application and you will notice a folder is created in the <code>~/Library/Preferences/Opera Preferences 9.52</code>.  If you intend to install more versions, follow the same instructions that we just used.</p>
<h3>Chrome</h3>
<p>When writing this article, Google Chrome is in beta.  I was able to download the latest version <a href="http://www.google.com/chrome" target="_blank">here</a>.  Since there&#8217;s only one version of Chrome for Mac OS X, I didn&#8217;t have to do any profile setup.  However, I&#8217;m sure when Chrome 5 arrives, I&#8217;ll have to figure this out so I can run different versions of Chrome simultaneously.</p>
<h3>Browsers Folder + Dock</h3>
<p>Ok, all of our browsers are setup and ready to roll.  However, remember earlier I said I would explain why we created the <code>/Applications/Browsers</code> folder?  Well, because it provides a nice way to be able to load any browser from your dock.  The attached screenshot is the <code>Browsers</code> folder dragged to my dock.</p>
<p>I hope this helps my fellow web developers in setting up your environment.   </p>
]]></content:encoded>
			<wfw:commentRss>http://joegornick.com/2010/01/14/setting-up-multiple-browsers-on-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>MySQL: Created &amp; Modified Date Fields</title>
		<link>http://joegornick.com/2009/12/30/mysql-created-modified-date-fields/</link>
		<comments>http://joegornick.com/2009/12/30/mysql-created-modified-date-fields/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 22:42:03 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://joegornick.com/?p=79</guid>
		<description><![CDATA[<p>I&#8217;ve been searching for an efficient way to set created and modified date fields in MySQL.  Of course, this can be done in the application you&#8217;re writing, however, I wanted to find a way to automatically do this on the database layer.</p>
<p><a href="http://joegornick.com/2009/12/30/mysql-created-modified-date-fields/" class="more-link">Read more on MySQL: Created &#038; Modified Date Fields&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been searching for an efficient way to set created and modified date fields in MySQL.  Of course, this can be done in the application you&#8217;re writing, however, I wanted to find a way to automatically do this on the database layer.</p>
<p>Please note, this approach is targeted for MySQL 5.0+.</p>
<p>The approach I take here is a combination of using the <code><a href="http://dev.mysql.com/doc/refman/5.0/en/timestamp.html">TIMESTAMP</a></code> field data type and a <code>TRIGGER</code>.  </p>
<p><b>IMPORTANT:</b> When using multiple <code>TIMESTAMP</code> fields in a table, there can be only one <code>TIMESTAMP</code> column with <code>CURRENT_TIMESTAMP</code> in <code>DEFAULT</code> or <code>ON UPDATE</code> clause.  This is why we need to use a <code>TRIGGER</code> to update one of the fields values.</p>
<p>In our case, we will set the <code>date_modified</code> field to contain the <code>DEFAULT</code> of <code>CURRENT_TIMESTAMP</code> and also set the <code>ON UPDATE</code> clause to <code>CURRENT_TIMESTAMP</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`temp`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`field_value`</span> VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`date_created`</span> TIMESTAMP <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`date_modified`</span> TIMESTAMP <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CURRENT_TIMESTAMP <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #993333; font-weight: bold;">UPDATE</span> CURRENT_TIMESTAMP
<span style="color: #66cc66;">&#41;</span>
ENGINE <span style="color: #66cc66;">=</span> InnoDB;</pre></div></div>

<p>If you noticed in the <code>CREATE TABLE</code> snippet above we use the <code>TIMESTAMP</code> features on the <code>date_modified</code> field, but set our <code>date_created</code> field to <code>NULL</code> by default.  We do this because our <code>TRIGGER</code> will populate the value before the insert.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">DELIMITER <span style="color: #66cc66;">//</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TRIGGER</span> temp_before_insert_created_date BEFORE <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #ff0000;">`temp`</span>
<span style="color: #993333; font-weight: bold;">FOR</span> EACH ROW
BEGIN
  <span style="color: #993333; font-weight: bold;">SET</span> NEW<span style="color: #66cc66;">.</span>date_created <span style="color: #66cc66;">=</span> CURRENT_TIMESTAMP;
END<span style="color: #66cc66;">//</span>
&nbsp;
DELIMITER ;</pre></div></div>

<p>In our trigger, we simply set the <code>date_created</code> value to the <code>CURRENT_TIMESTAMP</code>.</p>
<p>Now you will be able to insert and update rows in your table without having to specify the <code>date_created</code> or <code>date_modified</code> values.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`temp`</span> <span style="color: #66cc66;">&#40;</span>field_value<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'testing'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #ff0000;">`temp`</span> <span style="color: #993333; font-weight: bold;">SET</span> field_value <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'testing1'</span>;</pre></div></div>

<p>Another approach that can be used is by setting the <code>date_created</code> value to <code>NULL</code> when inserting a row.  This involves a different <code>CREATE TABLE</code> syntax.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`temp`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`field_value`</span> VARCHAR<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`date_created`</span> TIMESTAMP <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0000-00-00 00:00:00'</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`date_modified`</span> TIMESTAMP <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CURRENT_TIMESTAMP <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #993333; font-weight: bold;">UPDATE</span> CURRENT_TIMESTAMP
<span style="color: #66cc66;">&#41;</span>
ENGINE <span style="color: #66cc66;">=</span> InnoDB;</pre></div></div>

<p>Notice our <code>date_created</code> field is now set to <code>NOT NULL</code> with a default value of <code>0000-00-00 00:00:00</code>.  Here&#8217;s an important note from the documentation:</p>
<p><cite>TIMESTAMP columns are NOT NULL by default, cannot contain NULL values, and assigning NULL assigns the current timestamp.</cite></p>
<p>In other words, when we insert and set the value to <code>NULL</code> on a <code>TIMESTAMP</code> field, it will insert the current timestamp.</p>
<p>An example insert/update statement would look like:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`temp`</span> <span style="color: #66cc66;">&#40;</span>field_value<span style="color: #66cc66;">,</span> date_created<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'testing'</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">UPDATE</span> <span style="color: #ff0000;">`temp`</span> <span style="color: #993333; font-weight: bold;">SET</span> field_value <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'testing1'</span>;</pre></div></div>

<p>This approach allows us to avoid using triggers, however requires you to specify the <code>NULL</code> value when the query is executed.   </p>
]]></content:encoded>
			<wfw:commentRss>http://joegornick.com/2009/12/30/mysql-created-modified-date-fields/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Announcing Reserved Word Search. Find reserved words instantly as you type!</title>
		<link>http://joegornick.com/2009/12/30/announcing-reserved-word-search/</link>
		<comments>http://joegornick.com/2009/12/30/announcing-reserved-word-search/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 21:03:32 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://joegornick.com/?p=101</guid>
		<description><![CDATA[<p>To keep things rolling, I&#8217;ve released another project called Reserved Word Search.  With Reserved Word Search you can instantly find reserved words as you type.  This is extremely useful when doing database design and/or designing an API.</p>
<p><a href="http://joegornick.com/2009/12/30/announcing-reserved-word-search/" class="more-link">Read more on Announcing Reserved Word Search. Find reserved words instantly as you type!&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>To keep things rolling, I&#8217;ve released another project called Reserved Word Search.  With Reserved Word Search you can instantly find reserved words as you type.  This is extremely useful when doing database design and/or designing an API.</p>
<p>So go ahead and check out Reserved Word Search @ <a href="http://www.reservedwordsearch.com">www.reservedwordsearch.com</a>.   </p>
]]></content:encoded>
			<wfw:commentRss>http://joegornick.com/2009/12/30/announcing-reserved-word-search/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing GistDoIt! Run your gists and see the output!</title>
		<link>http://joegornick.com/2009/12/29/introducing-gistdoit/</link>
		<comments>http://joegornick.com/2009/12/29/introducing-gistdoit/#comments</comments>
		<pubDate>Tue, 29 Dec 2009 07:51:41 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://joegornick.com/?p=96</guid>
		<description><![CDATA[<p>For the past couple of months, I&#8217;ve been working on a mashup service between <a href="http://gist.github.com">gist.github.com</a> and <a href="http://ideone.com">ideone.com</a>.  The service allows someone to execute a gist and view the results.</p>
<p>For more information, please check out GistDoIt! @ <a href="http://www.gistdoit.com">www.gistdoit.com</a>.   </p>
<p><a href="http://joegornick.com/2009/12/29/introducing-gistdoit/" class="more-link">Read more on Introducing GistDoIt! Run your gists and see the output!&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>For the past couple of months, I&#8217;ve been working on a mashup service between <a href="http://gist.github.com">gist.github.com</a> and <a href="http://ideone.com">ideone.com</a>.  The service allows someone to execute a gist and view the results.</p>
<p>For more information, please check out GistDoIt! @ <a href="http://www.gistdoit.com">www.gistdoit.com</a>.   </p>
]]></content:encoded>
			<wfw:commentRss>http://joegornick.com/2009/12/29/introducing-gistdoit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Framework Best Practices – Part 2: I18n</title>
		<link>http://joegornick.com/2009/12/02/zend-framework-best-practices-part-2-i18n/</link>
		<comments>http://joegornick.com/2009/12/02/zend-framework-best-practices-part-2-i18n/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 04:08:26 +0000</pubDate>
		<dc:creator>Joe</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://joegornick.com/?p=46</guid>
		<description><![CDATA[<p>For the second part of my Zend Framework Best Practices series, I&#8217;d like to show you what I&#8217;ve found to be a simple and solid implementation of internationalizing your website.</p>
<p>Zend Framework already contains components like <a href="http://framework.zend.com/manual/en/zend.locale.html">Zend_Locale</a> and <a href="http://framework.zend.com/manual/en/zend.translate.html">Zend_Translate</a> to assist in internationalizing your website.  You use the <code>Zend_Locale</code> instance in conjunction with the <code>Zend_Translate</code> to know what current locale is being used and how to translate the content.  I&#8217;m going to show you how to implement these into your website.</p>
<p><a href="http://joegornick.com/2009/12/02/zend-framework-best-practices-part-2-i18n/" class="more-link">Read more on Zend Framework Best Practices – Part 2: I18n&#8230;</a></p>
]]></description>
			<content:encoded><![CDATA[<p>For the second part of my Zend Framework Best Practices series, I&#8217;d like to show you what I&#8217;ve found to be a simple and solid implementation of internationalizing your website.</p>
<p>Zend Framework already contains components like <a href="http://framework.zend.com/manual/en/zend.locale.html">Zend_Locale</a> and <a href="http://framework.zend.com/manual/en/zend.translate.html">Zend_Translate</a> to assist in internationalizing your website.  You use the <code>Zend_Locale</code> instance in conjunction with the <code>Zend_Translate</code> to know what current locale is being used and how to translate the content.  I&#8217;m going to show you how to implement these into your website.</p>
<p>If you haven&#8217;t read the <a href="http://joegornick.com/2009/11/18/zend-framework-best-practices-part-1-getting-started/">first part of this series</a>, I would recommend it as all my examples here will be based on that structure.</p>
<p>To start off, let&#8217;s talk about how we are going to allow our website to know what locale to use.  What I&#8217;ve found to be a common practice to switch locales is based off of the URL.  For example, a sample format may look like <code>mysite.com/:locale/controller/action</code>.  Locales are usually represented with a <code>language_REGION</code> combination.  However, locales in our case are specified by only the <code>language</code> code.  You can find a list of language codes <a href="http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/languages_and_territories.html">here</a>.  If you wanted your site to be in Japanese, you would use the language code of <code>ja</code>.  An example of the URL might look something like <code>mysite.com/ja/controller/action</code>.  On top of specifying the locale in the path of the URL, I&#8217;ve also provided a way to determine the locale based off of the TLD in the URL.  For example, let&#8217;s say our <code>mysite.com</code> also has a Japanese TLD like <code>mysite.jp</code>.  When a request comes in and we find a supported TLD, we set the localed based on it.</p>
<p>Enough talk, let&#8217;s look at some code.</p>
<p>Let&#8217;s start by setting up our <code>Zend_Locale</code>.  In the <code>application.ini</code>, we use the <code>Zend_Application_Resource_Locale</code> to setup the locale component and set our default locale.  In our case here, I&#8217;m setting the default locale to <strong>English</strong>.</p>
<p>application.ini:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">...
# Locale
resources.locale.default <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;en&quot;</span>
...</pre></div></div>

<p>Next, we need to tell our application which locales are supported and also specify our TLD mappings.  We do this by specifying front controller parameters in the <code>application.ini</code>.  </p>
<p>application.ini:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">...
# Front Controller Params
resources.frontController.params.locales<span style="">&#91;</span><span style="">&#93;</span> <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;en&quot;</span>
resources.frontController.params.locales<span style="">&#91;</span><span style="">&#93;</span> <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;ja&quot;</span>
resources.frontController.params.tldLocales.jp <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;ja&quot;</span>
...</pre></div></div>

<p>If you notice from the configuration above, I&#8217;ve added English and Japanese as my supported locales and I also mapped the <code>jp</code> TLD to use the <code>ja</code> language code.  More on how we use those later.</p>
<p>Before I show the rest of the configuration needed, let me explain how the process works.</p>
<p>In order for your application to recognize when a locale is specified in the URL, you need to create special routes to parse out the locale.  The approach I took was to override the existing <code>Zend_Application_Resource_Router</code> and implement the ability to automatically add locale routes to the application when enabled.</p>
<p>The process in which I added routes to my application was done previously in my <code>Bootstrap.php</code> with the <code>_initRoutes()</code> method.  I&#8217;ve removed that code and moved the routes to be configured in the <code>application.ini</code>.  Now that the routes are specified in the <code>application.ini</code>, it allows us to easily add/edit/remove routes from our application.  There is also a benefit to doing this in regards to caching, which I will explain in a future article.</p>
<p>First, let&#8217;s take a look at how we will load the custom router application resource and override the existing application resource.</p>
<p>application.ini</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">...
# Custom Resource Plugins
pluginPaths.My_Application_Resource <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> APPLICATION_PATH </span><span style="color: #933;">&quot;/../lib/My/Application/Resource/&quot;</span>
...</pre></div></div>

<p>Now the application is setup to load custom application resources for the namespace specified.  Since I am overriding the <code>Zend_Application_Resource_Router</code>, let&#8217;s look at <code>My_Application_Resource_Router</code>:</p>
<p>My/Application/Resource/Router.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> My_Application_Resource_Router <span style="color: #000000; font-weight: bold;">extends</span> Zend_Application_Resource_Router
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$_explicitType</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'router'</span><span style="color: #339933;">;</span>
&nbsp;
    protected <span style="color: #000088;">$_front</span><span style="color: #339933;">;</span>
    protected <span style="color: #000088;">$_locale</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/**
     * Retrieve router object
     *
     * @return Zend_Controller_Router_Rewrite
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getRouter<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOptions</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'enabled'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span>
            <span style="color: #339933;">!</span><span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'enabled'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">getRouter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$bootstrap</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBootstrap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_front<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$bootstrap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bootstrap</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'FrontController'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_front <span style="color: #339933;">=</span> <span style="color: #000088;">$bootstrap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContainer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">frontcontroller</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_locale<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$bootstrap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bootstrap</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Locale'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_locale <span style="color: #339933;">=</span> <span style="color: #000088;">$bootstrap</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContainer</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">locale</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$defaultLocale</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_locale<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$defaultLocale</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$defaultLocale</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$locales</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_front<span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'locales'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$requiredLocalesRegex</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'^('</span> <span style="color: #339933;">.</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$locales</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">')$'</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$routes</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'routes'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$routes</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// First let's add the default locale to this routes defaults.</span>
            <span style="color: #000088;">$defaults</span> <span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'defaults'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
                ? <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'defaults'</span><span style="color: #009900;">&#93;</span>
                <span style="color: #339933;">:</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Always default all routes to the Zend_Locale default</span>
            <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'defaults'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'locale'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$defaultLocale</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$defaults</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$routes</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Get our route and make sure to remove the first forward slash</span>
            <span style="color: #666666; font-style: italic;">// since it's not needed.</span>
            <span style="color: #000088;">$routeString</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$routeString</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ltrim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$routeString</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/\\'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Modify our normal route to have the locale parameter.</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span>
                <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #0000ff;">'Zend_Controller_Router_Route'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">':locale/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$routeString</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'reqs'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$requiredLocalesRegex</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #000088;">$routes</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale_'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #0000ff;">'Zend_Controller_Router_Route_Regex'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'('</span> <span style="color: #339933;">.</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$locales</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">')\/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$routeString</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #666666; font-style: italic;">// Since we added the local regex match, we need to bump the existing</span>
                <span style="color: #666666; font-style: italic;">// match numbers plus one.</span>
                <span style="color: #000088;">$map</span> <span style="color: #339933;">=</span> <span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'map'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'map'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$map</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$index</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$word</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$map</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$index</span><span style="color: #339933;">++</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #000088;">$map</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$index</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$word</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #666666; font-style: italic;">// Add our locale map</span>
                <span style="color: #000088;">$map</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'locale'</span><span style="color: #339933;">;</span>
                <span style="color: #990000;">ksort</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$map</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'map'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$map</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #000088;">$routes</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale_'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'type'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #0000ff;">'Zend_Controller_Router_Route_Static'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$locales</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$locale</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'route'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$locale</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$routeString</span><span style="color: #339933;">;</span>
                    <span style="color: #000088;">$value</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'defaults'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$locale</span><span style="color: #339933;">;</span>
                    <span style="color: #000088;">$routes</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale_'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$locale</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'_'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$key</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'routes'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$routes</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOptions</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">getRouter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>In order for this custom application resource to override the existing one, the key is <code>public $_explicitType = 'router';</code>.  Now when routes are setup in the <code>application.ini</code> for the router resource it won&#8217;t use the <code>Zend_Application_Resource_Router</code>, but rather <code>My_Application_Resource_Router</code>.</p>
<p>This application resource sets up the <code>Zend_Controller_Router_Rewrite</code> by parsing the specified options parsed from the <code>application.ini</code>.  Notice this custom application resource extends from the original <code>Zend_Application_Resource_Router</code> which allows us to have the application resource perform the default actions if the locale option is not enabled in the configuration.  By default, the custom router application resource will perform the default actions to the routes.  You need to explicitly specify in the <code>application.ini</code> that the router is locale aware.</p>
<p><code>My_Application_Resource_Router</code> simply takes in the specified routes from the <code>application.ini</code> and adds locale routes automatically so you don&#8217;t have to chain/duplicate routes in the configuration.</p>
<p>Let&#8217;s look at our <code>application.ini</code> to see how we are setting up the router to be locale aware and adding a route.</p>
<p>application.ini:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">...
# Router/Routes
resources.router.locale.enabled <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> true</span>
resources.router.routes.action_index.route <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;:action/*&quot;</span>
resources.router.routes.action_index.defaults.controller <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;index&quot;</span>
resources.router.routes.action_index.defaults.action <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;index&quot;</span>
...</pre></div></div>

<p>In the previous configuration snippet, we enable our router application resource to be locale aware and add a basic <code>Zend_Controller_Router_Route</code> which is the same as specified previously in our <code>Bootstrap.php</code>.  When the router application resource is finished adding the routes to the router, there will be two:</p>
<ol>
<li><code>:action/*</code></li>
<li><code>:locale/:action/*</code></li>
</ol>
<p>Currently the <code>My_Application_Resource_Router</code> supports <code>Zend_Controller_Router_Route</code>, <code>Zend_Controller_Router_Route_Regex</code> and <code>Zend_Controller_Router_Static</code> routes.  When these routes are specified and the router application resource is locale aware, it will automatically create routes for the supported locales.</p>
<p>We&#8217;ve covered a lot already, but there are still a few more steps involved.  We are almost finished, I promise!</p>
<p>At this point, we have specified our default and supported locales and setup our routes using our custom router application resource.  Now we need to do one more thing and that is to determine which locale to load and create our <code>Zend_Translate</code> instance.</p>
<p>In order for us to determine which locale, if any, has been specified in the request, we use a controller plugin to parse the request and set the correct locale and setup our translation component.</p>
<p>First, we need to enable the controller plugin in our <code>application.ini</code>.</p>
<p>application.ini:</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;">...
# Front Controller Plugins
resources.frontController.plugins.I18n <span style="color: #000066; font-weight:bold;">=</span> <span style="color: #933;">&quot;My_Controller_Plugin_I18n&quot;</span>
...</pre></div></div>

<p>Next, let&#8217;s look at the controller plugin source:</p>
<p>My/Controller/Plugin/I18n.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> My_Controller_Plugin_I18n <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_Abstract
<span style="color: #009900;">&#123;</span>
    <span style="color: #009933; font-style: italic;">/**
    * Sets the application locale and translation based on the locale param, if
    * one is not provided it defaults to english
    *
    * @param Zend_Controller_Request_Abstract $request
    */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> routeShutdown<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$frontController</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParams</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$registry</span> <span style="color: #339933;">=</span> Zend_Registry<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Steps setting the locale.</span>
        <span style="color: #666666; font-style: italic;">// 1. Defaults to English (Done in config)</span>
        <span style="color: #666666; font-style: italic;">// 2. TLD in host header</span>
        <span style="color: #666666; font-style: italic;">// 3. Locale params specified in request</span>
        <span style="color: #000088;">$locale</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$registry</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Locale'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Check host header TLD.</span>
        <span style="color: #000088;">$tld</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^.*\./'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHeader</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Host'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Provide a list of tld's and their corresponding default languages</span>
        <span style="color: #000088;">$tldLocales</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tldLocales'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tld</span><span style="color: #339933;">,</span> <span style="color: #000088;">$tldLocales</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// The TLD in the request matches one of our specified TLD -&gt; Locales</span>
            <span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLocale</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tldLocales</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$tld</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// There is a locale specified in the request params.</span>
            <span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLocale</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'locale'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Now that our locale is set, let's check which language has been selected</span>
        <span style="color: #666666; font-style: italic;">// and try to load a translation file for it. If the language is the default,</span>
        <span style="color: #666666; font-style: italic;">// then we do not need to load a translation.</span>
        <span style="color: #000088;">$language</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLanguage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$language</span> <span style="color: #339933;">!==</span> <span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$i18nFile</span> <span style="color: #339933;">=</span> APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/data/i18n/source-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$language</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'.mo'</span><span style="color: #339933;">;</span>
            try <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$translate</span> <span style="color: #339933;">=</span>
                    <span style="color: #000000; font-weight: bold;">new</span> Zend_Translate<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'gettext'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$i18nFile</span><span style="color: #339933;">,</span> <span style="color: #000088;">$locale</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'disableNotices'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                Zend_Registry<span style="color: #339933;">::</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Translate'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$translate</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                Zend_Form<span style="color: #339933;">::</span><span style="color: #004000;">setDefaultTranslator</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$translate</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> catch <span style="color: #009900;">&#40;</span>Zend_Translate_Exception <span style="color: #000088;">$e</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// Since there was an error when trying to load the translation catalog,</span>
                <span style="color: #666666; font-style: italic;">// let's not load a translation object which essentially defaults to</span>
                <span style="color: #666666; font-style: italic;">// locale default.</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Now that we have our locale setup, let's check to see if we are loading</span>
        <span style="color: #666666; font-style: italic;">// a language that is not the default, and update our base URL on the front</span>
        <span style="color: #666666; font-style: italic;">// controller to the specified language.</span>
        <span style="color: #000088;">$defaultLanguage</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$defaultLanguage</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$defaultLanguage</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">ltrim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPathInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/\\'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// If the language is in the path, then we will want to set the baseUrl</span>
        <span style="color: #666666; font-style: italic;">// to the specified language.</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^\/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$language</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'\/?/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setBaseUrl</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBaseUrl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$language</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #990000;">setcookie</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Locale'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$language</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getHttpHost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>To start, notice this plugin listens on the <code>routeShutdown()</code> method.  We use this because our request has gone through our router and the request is now setup and ready to be processed.  In the <code>routeShutdown()</code> method, we first load our <code>Zend_Locale</code> instance from the registry where it was set up in our <code>application.ini</code>.  Next, we need to determine which locale, if any, needs to be set.  By default, we&#8217;ve set our locale to use English (en) in our <code>application.ini</code>.  We will parse out the TLD from the host and see if it maps to one of our specified TLD locales.  If that doesn&#8217;t exist, then we will look in the request to see if the locale param was set.  If both of the checks can&#8217;t find a specified locale, we then simply use the default.</p>
<p>Since our locale is now setup, we need to load a translation file.  In my example provided, I use <code>gettext</code> translation files.  I place these files in the <code>app/data/i18n</code> folder.  The file naming scheme looks like <code>source-{locale}.mo</code>.  Another example would be if we had a Japanese translation file, it would look something like <code>source-ja.mo</code>.  The plugin will try to load the translation file based on the locale language specified and add it to our <code>Zend_Registry</code> and tell our <code>Zend_Form</code> it&#8217;s default translator.</p>
<p>Finally, our plugin uses the specified locale language to determine if we need to update our base URL in the front controller.  We want to set the base URL to the specified locale which allows other components like <code>Zend_Navigation</code> to persist the locale in the links produced.</p>
<p>There you have it!  You&#8217;re site is now internationalized and ready for it&#8217;s content to be translated.</p>
<p>But wait, that&#8217;s not all!  I&#8217;ve also provided a view helper which produces a locale switcher.  This view helper simply creates elements that contain images of the specified locale and shows the enabled/disabled locale while allowing you to click on the image and switch the current locale.</p>
<p>app/views/helpers/LocaleSwitcher.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> Default_View_Helper_LocaleSwitcher <span style="color: #000000; font-weight: bold;">extends</span> Zend_View_Helper_Abstract
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> localeSwitcher<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$output</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$frontController</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$locales</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParam</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'locales'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$request</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$baseUrl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getBaseUrl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPathInfo</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/\\'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$locales</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$locale</span> <span style="color: #339933;">=</span> Zend_Registry<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Locale'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$localeLanguage</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLanguage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$defaultLocaleLanguage</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$locale</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDefault</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$defaultLocaleLanguage</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$defaultLocaleLanguage</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;ul id=&quot;locale_switcher&quot;&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$locales</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$language</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000088;">$imageSrc</span>  <span style="color: #339933;">=</span> <span style="color: #0000ff;">'img/i18n_'</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$imageSrc</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$language</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'_'</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$localeLanguage</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$language</span> ? <span style="color: #0000ff;">'on'</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">'off'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000088;">$imageSrc</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'.gif'</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #000088;">$urlLanguage</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$defaultLocaleLanguage</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$language</span>
                    ? <span style="color: #0000ff;">''</span>
                    <span style="color: #339933;">:</span> <span style="color: #0000ff;">'/'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$language</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$baseUrl</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$localeUrl</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$urlLanguage</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$path</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000088;">$localeUrl</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/^'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">preg_quote</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$baseUrl</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'\/?/'</span><span style="color: #339933;">,</span>
                        <span style="color: #000088;">$urlLanguage</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;li&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;a href=&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$localeUrl</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot;&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;img src=&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assetUrl</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$imageSrc</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot; alt=&quot;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$language</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&quot; /&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;/a&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;/li&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$output</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;/ul&gt;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">join</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span> <span style="color: #000088;">$output</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I&#8217;ve included an updated <a href='http://joegornick.com/wp-content/uploads/2009/12/zfbp.zip'>Zend Framework Best Practices</a> zip file which contains all of the files/directory structure we&#8217;ve discussed so far in the series.</p>
<p>The original gist of this process can be found here: <a href="http://gist.github.com/189194">http://gist.github.com/189194</a>.</p>
<p>That&#8217;s it for now.  Until next time!   </p>
]]></content:encoded>
			<wfw:commentRss>http://joegornick.com/2009/12/02/zend-framework-best-practices-part-2-i18n/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
	</channel>
</rss>

