grayskya lesser known character2009-07-09T22:51:46ZWordPresshttp://graysky.org/feed/atom/mikehttp://graysky.orghttp://graysky.org/?p=7682009-07-09T22:51:46Z2009-07-09T22:51:46Z<div><img src="http://files.snapmylife.com/pictures/4694162/838330_large_thumb.jpg" style="border: 0;"/> <img src="http://files.snapmylife.com/pictures/5570290/938643_large_thumb.jpg" style="border: 0;"/> <img src="http://files.snapmylife.com/pictures/578107/792486_large_thumb.jpg" style="border: 0;"/></div>
<div style="margin-bottom: 10px" ><img src="http://files.snapmylife.com/pictures/2015201/38978_large_thumb.jpg" style="border: 0;"/> <img src="http://files.snapmylife.com/pictures/1296164/21668_large_thumb.jpg" style="border: 0;"/> <img src="http://files.snapmylife.com/pictures/519383/611161_large_thumb.jpg" style="border: 0;"/></div>
<p>I was recently looking through my shots from a year <a href="http://www.snapmylife.com/pictures/user/46016" >experimenting with mobile-phone photography</a>. As something of a photo snob I’m surprised at how quickly it is becoming “good enough” for many snapshots. Duncan Davidson has a <a href="http://blog.duncandavidson.com/2009/07/sunset-along-interstate-5.html" >fantastic example that illustrates</a> that pros and cons of this trend. (Or, more humorously The Onion captures the zeitgeist perfectly with their report about <a href="http://www.theonion.com/content/node/95143" >40,000 insipid party pics of a dorm fire</a>.)</p>
<ul>
<li>The mobile camera is one that is always with you. Try as I might I’m not often disciplined enough of a photographer to have a better camera on me and want to dig it out. Having a camera at the ready is certainly critical to capturing a shot (as <a href="http://photo.net/learn/point-and-shoot-tips" >Phil Greenspun describes well</a> on the benefits of points-and-shoots) that may only last for a moment.
<li>Mobile phones are already on the network, so it is relatively simple to share. The time between snapping a picture on my iPhone and sharing it with friends is measured in seconds. Compare that to the slow pace of taking the SD card out of my 50d, importing onto my computer and then uploading. This can take between hours and days. There is real value to the immediacy of sharing a moment with friends and family. Products like the fantastic <a href="http://www.eye.fi/" >Eye-Fi</a> are an improvement for traditional point-and-shoots but they are playing catch up in this arena.
<li>This likely only appeals to nerds, but I love that my iPhone can provide geolocation information in the EXIF data. I really enjoy having a record of where my pictures were taken, but this may not be of mass appeal. Again, the Eye-Fi improves this for point-and-shoot cameras but lags the capabilities of my iPhone.
<li>The lens leaves a lot to be desired, as Duncan’s comparison shows. The iPhone 3GS “tap-to-focus” and 3MP image are a step up, but shooting in low light conditions mostly yields poor results. Perhaps good enough to share with a friend, but likely to be blurry. Of course mobile cameras won’t likely be ever used for fine art, but there is value to <a href="http://twitpic.com/135xa" >even technically flawed images</a>.
</ul>
<p>Like the mobile phone itself, the mobile phone camera is often worse than the traditional alternatives but has a few killer features. It seems similar to the appeal of the instant Polaroid picture for a prior generation. And next up is video.</p>
<img src="http://feeds.feedburner.com/~r/graysky/~4/iHImZUX5AdU" height="1" width="1"/>2http://graysky.org/2009/07/mobile-photography/mikehttp://graysky.orghttp://graysky.org/?p=9942009-06-26T05:01:36Z2009-06-26T04:53:53Z<div class="video-frame" style="margin: 9px; text-align:center;margin: 9px; text-align:center;">
<object type="application/x-shockwave-flash" width="600" height="338" data="http://www.flickr.com/apps/video/stewart.swf?v=71377" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ><param name="flashvars" value="intl_lang=en-us&photo_secret=8d94589b29&photo_id=3659137146&hd_default=true" /></param><param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=71377" /></param><param name="bgcolor" value="#000000" /></param><param name="allowFullScreen" value="true" /></param><embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/video/stewart.swf?v=71377" bgcolor="#000000" allowfullscreen="true" flashvars="intl_lang=en-us&photo_secret=8d94589b29&photo_id=3659137146&hd_default=true" height="338" width="600" ></embed></object>
</div>
<p>Last night we attended a live recording of <a href="http://www.onpointradio.org/" ><em>On Point</em></a> with Adam Davidson and David Kestenbaum of NPR’s <a href="http://www.npr.org/blogs/money/" ><em>Planet Money</em></a> podcast. The recording, held in <a href="http://www.longwoodevents.com/Venues/StateRoom/" >The State Room</a> in downtown Boston, was a fundraiser for <a href="http://www.wbur.org/" >WBUR</a>. The <a href="http://www.onpointradio.org/2009/06/planet-money" >episode aired today</a> and was a good conversation on how they’ve tried to explain complex economic news in an understandable and engaging way. I captured a <a href="http://www.flickr.com/photos/downtree/3659137146/" >quick video</a> from the evening’s conversation.</p>
<p>Like many others I was extremely impressed with This American Life’s <a href="http://www.thislife.org/radio_episode.aspx?episode=355" >“The Giant Pool of Money”</a> episode last year – even buying the CD version so I could give it to family not familiar with podcasts – and have listened to Planet Money since last fall’s economic meltdown. They’ve managed onto a winning formula of both being more explanatory and less formal than typical economic reporting. For example, Planet Money hasn’t shied away from dry subjects like explaining collateralized debt obligations or credit default swaps. And after spending time on Capital Hill Kestenbaum was rather forthright that he felt unconvinced that many lawmakers really understand the complexity of the financial markets they oversee. But perhaps the best aspect of the show is that they themselves are struggling to truly understand complicated economic issues along with the listeners. The quote of the night was from Davidson, who when asked about the difficulty of covering economic news after the crisis compared it to his feelings about Iraq, saying that “America went from fascination with Iraq to boredom without ever passing through knowledge.” Hopefully shows like Planet Money are small steps to helping actually learn about how the real economy works.</p>
<p>(But what is it that makes radio personalities look quite different than from how their voices lead you to expect? When I saw Adam Davidson in a <a href="http://www.pbs.org/wgbh/pages/frontline/breakingthebank/" >Frontline special</a> I was somehow rather surprised that a public radio economic reporter was a bit nerdish. What are the odds?)</p>
<img src="http://feeds.feedburner.com/~r/graysky/~4/iLW4noqILeQ" height="1" width="1"/>0http://graysky.org/2009/06/planet-money-on-point/mikehttp://graysky.orghttp://graysky.org/?p=9462009-06-22T01:51:27Z2009-06-21T23:29:01Z<p>One small annoyance of using <a href="http://macromates.com/" >TextMate</a> is how it refreshes the project tree when it regains focus. If you have a large source tree this can lead to waiting for many seconds while TextMate is frozen or showing the dreaded <a href="http://en.wikipedia.org/wiki/Spinning_wait_cursor" >beach ball</a>. Normally switching back from another application to TextMate has about a half second delay, but when the directory contents are changed it can be considerably longer when the project is large (presumably stat info is cached in the first case.) Our current project setup contains about 150MB of source code (including plugins and vendor’d rails) and a data directory that can be ~1GB, leading to some frustrating wait times.</p>
<p>Until the mythic <a href="http://blog.macromates.com/2009/working-on-it/" >TextMate 2 is released</a> and fixes <a href="http://fixedbytm2.com/" >each and every TextMate issue</a>, here are a few workarounds:</p>
<ol>
<li><strong>Change Project Structure</strong> – Move that huge data directory out from under the project hierarchy. For some projects this might be harder than others, especially for those projects with very large source trees.</li>
<li><strong>ReMate</strong> – There are 2 version of ReMate, a plugin that disables the automatic refreshing of the project tree. The <a href="http://ciaranwal.sh/remate/" >original version</a> adds a menu item to <em>Disable Refresh on Regaining Focus</em>. This makes TextMate instantly responsive during app switching, but I can’t get the option to remain enabled between TextMate sessions. And, obviously, changes made in the filesystem are not reflected in the TextMate project drawer and the manual <em>Refresh All Projects</em> menu item is broken as well. (This might be due to an interaction with <a href="http://ciaranwal.sh/2008/08/05/textmate-plug-in-projectplus" >ProjectPlus</a> plugin.)
<p>
<p>The <a href="http://ciaranwal.sh/2007/11/07/remate-update" >updated version of ReMate</a> will disable automatic refresh for specific mounted volumes and is designed for those editing files over networked filesystems like SFTP or WebDAV.</p>
</li>
<li><strong>Remove Folder Reference</strong> – Within TextMate a folder pattern can be removed from the tree. The advantage over ReMate is to remove the huge data directory but still have TextMate automatically pick up other filesystem changes. This will only stick if you have a TextMate Project (right click on the top level directory > <em>Show Information</em>) or make the change globally (<em>Preferences</em> > <em>Advanced</em> > <em>Folder References</em>). Within the dialog modify the <em>Folder Pattern</em> <a href="http://manual.macromates.com/en/regular_expressions" >regular expression</a> to exclude the “big_data” directory like:
<p></p>
<div class="wp_syntax" ><div class="code" ><pre class="bash bash" style="font-family:Monacofont-family:Monacomonospace;monospace;"><span style="color: #000000; font-weight: bold;" >!</span>.<span style="color: #000000; font-weight: bold;" >*/</span><span style="color: #7a0874; font-weight: bold;" >(</span>\.<span style="color: #7a0874; font-weight: bold;" >[</span>^<span style="color: #000000; font-weight: bold;" >/</span><span style="color: #7a0874; font-weight: bold;" >]</span>*|CVS|big_data|.<span style="color: #000000; font-weight: bold;" >*</span>~\.nib|.<span style="color: #000000; font-weight: bold;" >*</span>\.<span style="color: #7a0874; font-weight: bold;" >(</span>xcode<span style="color: #7a0874; font-weight: bold;" >(</span>proj<span style="color: #7a0874; font-weight: bold;" >)</span>?<span style="color: #7a0874; font-weight: bold;" >)</span><span style="color: #7a0874; font-weight: bold;" >)</span>$</pre></div></div>
<p>After making this change TextMate should be much snappier when bouncing between TM and other applications.
</ol>
<img src="http://feeds.feedburner.com/~r/graysky/~4/BhbsDdfD854" height="1" width="1"/>3http://graysky.org/2009/06/textmate-project-refresh-focus/mikehttp://graysky.orghttp://graysky.org/?p=8722009-06-02T03:24:58Z2009-06-02T02:58:42Z<div class="flickr-frame" style="padding-right: 4px; margin-right: 5px; padding-left: 4px; padding-top: 8px; margin-top: 8px;padding-right: 4px; margin-right: 5px; padding-left: 4px; padding-top: 8px; margin-top: 8px;"><a href="http://www.flickr.com/photos/downtree/sets/72157617638779824/" title="Harry Parker Boathouse by graysky., on Flickr" ><img src="http://graysky.org/images/harry_parker_boathouse.jpg" alt="Harry Parker Boathouse" style="border: 0;"/></a></div>
<p>The best addition to my morning commute is driving past <a href="http://www.communityrowing.org/" >Community Rowing Inc.’s</a> Harry Parker Boathouse along the Charles River in Brighton, MA. The <a href="http://www.gocrimson.com/ViewArticle.dbml?DB_OEM_ID=9000&ATCLID=1580207" >$15 million dollar, 30,000 sq. ft.</a> boathouse was designed by <a href="http://www.anmahian-winton.com" >Anmahian Winton Architects</a> to support public access to rowing. The choice of material and cross-hatching pattern for the exterior add to the striking yet inviting feel of the structure. [<a href="http://www.flickr.com/photos/downtree/sets/72157617638779824/" >more pics</a>]</p>
<div class="flickr-frame" style="padding-right: 4px; margin-right: 5px; padding-left: 4px; padding-top: 8px; margin-top: 8px;padding-right: 4px; margin-right: 5px; padding-left: 4px; padding-top: 8px; margin-top: 8px;"><a href="http://www.flickr.com/photos/downtree/sets/72157617638779824/" title="Community Rowing" ><img src="http://graysky.org/images/community_rowing.jpg" alt="Community Rowing" style="border: 0;"/></a></div>
<img src="http://feeds.feedburner.com/~r/graysky/~4/JHfB0a5FYqo" height="1" width="1"/>1http://graysky.org/2009/06/harry-parker-boathouse/mikehttp://graysky.orghttp://graysky.org/?p=8432009-05-25T14:57:46Z2009-05-25T14:57:46Z<div class="flickr-frame" style="padding-right: 4px; margin-right: 5px; padding-left: 4px; padding-top: 8px; margin-top: 8px;padding-right: 4px; margin-right: 5px; padding-left: 4px; padding-top: 8px; margin-top: 8px;"><a href="http://www.flickr.com/photos/downtree/3563197960/" ><img hspace="auto" vspace="0" src="http://graysky.org/images/veterans_lot.jpg" class="flickr-photo" style="margin-top: 0px; border: solid 1px #000000; display: block; margin-left: auto; margin-right: auto;border: 0;"/></a>
</div>
<p>The flags along the Veterans’ Lots in Cambridge Cemetery, in advance of the <a href="http://www.cambridgema.gov/VET/NewsDetail.cfm?story_id=2149" >Cambridge Memorial Day Observance</a>.</p>
<img src="http://feeds.feedburner.com/~r/graysky/~4/9Fi3eUFI-jw" height="1" width="1"/>0http://graysky.org/2009/05/memorial-day/mikehttp://graysky.orghttp://graysky.org/?p=8242009-07-04T14:52:06Z2009-04-13T21:41:23Z<p>I recently wrote to my State Representative, <a href=" http://www.mass.gov/legis/member/j_h1.htm" >Jonathan Hecht</a>, to support banning noncompete clauses in Massachusetts. House Bill 1794 would abolish non-competes clauses in employment agreements and has been <a href="http://opencompetition.wordpress.com/supporters/" >endorsed by those in the “Alliance for Open Competition”</a> and other tech founders like <a href="http://innocuous.org/articles/2008/12/30/ban-non-competes-in-massachusetts" >Richard Tibbets of StreamBase</a>. I believe changing the law in the Commonwealth to ban non-competes would help make our state more attractive to tech workers by ensuring their ability to make the best use of their skills and new businesses to hire the best talent. Even if they are rarely enforced they can contribute to a chilling effect that can make Massachusetts less competitive with states like California, <a href="http://en.wikipedia.org/wiki/Non-compete_clause#Enforceability_in_the_State_of_California" >where they are not enforced.</a></p>
<p>In reading up on the issue, I came across a few sites that I thought were interesting:</p>
<ul>
<li>Rep. Brownsberger, who sponsored the bill in the House, maintains a site with links to the legistlative proposal, discussions in the press and background information at the (unfortunately named but very useful): <a href="http://prohibitrestrictiveemploymentcovenants.net" >prohibitrestrictiveemploymentcovenants.net</a></li>
<li>Bijan Sabet has an <a href="http://bijansabet.com/post/22575311/matt-marx-is-a-researcher-and-doctoral-candidate" >interesting interview with Harvard Business School researcher Matt Marx</a> about effects of noncompetes agreements (and <a href="http://www.boston.com/business/articles/2007/12/30/why_noncompete_means_dont_thrive_/" >related Globe column by Scott Kirsner</a>.)</li>
<li>An article by Russell Beck, of Foley & Lardner, on what <a href="http://www.masshightech.com/stories/2008/09/01/focus4-Noncompete-agreements-that-dont-mean-what-they-say.html" >non-compete agreements actually mean</a>. Michael Rosen, also of Foley Hoag, maintains an interesting blog about noncompete law and other labor & employment law in Massachusetts at <a href="http://www.massachusettsnoncompetelaw.com/" >massachusettsnoncompetelaw.com</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/graysky/~4/ddDUowci9Mw" height="1" width="1"/>0http://graysky.org/2009/04/non-compete-clauses-massachusetts/mikehttp://graysky.orghttp://graysky.org/?p=8032009-04-01T21:04:59Z2009-04-02T06:50:57Z<p>Recently I added a few ads to <a href="http://whoshouldifollow.com" >WhoShouldiFollow</a> to cover our hosting costs and ran into a Javascript issue I hadn’t hit before. Specifically, trying to dynamically load a third party script that uses <tt>document.write</tt> to add HTML to the DOM was <b>erasing the whole page</b>! I found a (slightly-evil) solution after much hacking around and no luck finding anything similar in Google. Hopefully there is a cleaner solution out there, but thought I’d write up my fix.</p>
<p>The way that the ad network supplies the ad is for publishers to include a short snippet like this:</p>
<div class="wp_syntax" ><div class="code" ><pre class="html" style="font-family:Monacofont-family:Monacomonospace;monospace;"><script src="http://thirdparty.com/ad.js" type="text/javascript"></script></pre></div></div>
<p>Within the ad javascript it does something like this (simplified for this example):</p>
<div class="wp_syntax" ><div class="code" ><pre class="javascript javascript" style="font-family:Monacofont-family:Monacomonospace;monospace;">document.<span style="color: #000066; font-weight: bold;" >write</span><span style="color: #009900;" >(</span><span style="color: #3366CC;" >"<b>Click on this ad!</b>"</span><span style="color: #009900;" >)</span>;</pre></div></div>
<p>Nice and simple to drop in to HTML, but our results page is built dynamically from an AJAX call that fetches JSON. At first I thought I could just built a new script tag and append it to the div I wanted, but that resulted in a blank page with just the ad in the DOM. I’m assuming that without an enclosing context that the <tt>document.write</tt> is overwriting the root html node.</p>
<p>Instead what worked was to temporarily override <tt>document.write</tt> just before the ad is loaded and write the content of the ad into the DOM where I wanted. This works, but feels a bit evil. I’d be interested in finding a prettier solution than this.</p>
<div class="wp_syntax" ><div class="code" ><pre class="javascript javascript" style="font-family:Monacofont-family:Monacomonospace;monospace;"><span style="color: #003366; font-weight: bold;" >var</span> original_write <span style="color: #339933;" >=</span> document.<span style="color: #000066; font-weight: bold;" >write</span>;
<span style="color: #006600; font-style: italic;" >// Re-assign doc.write while the ad is loaded.</span>
document.<span style="color: #000066; font-weight: bold;" >write</span> <span style="color: #339933;" >=</span> <span style="color: #003366; font-weight: bold;" >function</span><span style="color: #009900;" >(</span>ad_html<span style="color: #009900;" >)</span> <span style="color: #009900;" >{</span>
<span style="color: #006600; font-style: italic;" >// Append the contents of the ad to a special div.</span>
$<span style="color: #009900;" >(</span><span style="color: #3366CC;" >'#my_ad_row'</span><span style="color: #009900;" >)</span>.<span style="color: #660066;" >append</span><span style="color: #009900;" >(</span>ad_html<span style="color: #009900;" >)</span>;
<span style="color: #006600; font-style: italic;" >// restore original write</span>
document.<span style="color: #000066; font-weight: bold;" >write</span> <span style="color: #339933;" >=</span> original_write;
<span style="color: #009900;" >}</span>
<span style="color: #006600; font-style: italic;" >// Create a script element in the DOM to load the ad.</span>
<span style="color: #003366; font-weight: bold;" >var</span> e <span style="color: #339933;" >=</span> document.<span style="color: #660066;" >createElement</span><span style="color: #009900;" >(</span><span style="color: #3366CC;" >"script"</span><span style="color: #009900;" >)</span>;
e.<span style="color: #660066;" >src</span> <span style="color: #339933;" >=</span> <span style="color: #3366CC;" >"http://thirdparty.com/ad.js"</span>;
e.<span style="color: #660066;" >type</span><span style="color: #339933;" >=</span><span style="color: #3366CC;" >"text/javascript"</span>;
document.<span style="color: #660066;" >getElementsByTagName</span><span style="color: #009900;" >(</span><span style="color: #3366CC;" >"head"</span><span style="color: #009900;" >)</span><span style="color: #009900;" >[</span>0<span style="color: #009900;" >]</span>.<span style="color: #660066;" >appendChild</span><span style="color: #009900;" >(</span>e<span style="color: #009900;" >)</span>;</pre></div></div>
<img src="http://feeds.feedburner.com/~r/graysky/~4/EYKsxwhHMQY" height="1" width="1"/>2http://graysky.org/2009/04/dynamically-loading-javascript/mikehttp://graysky.orghttp://graysky.org/?p=7702009-03-11T19:00:25Z2009-03-11T18:54:33Z<p>Last night I gave a talk at the <a href="http://bostonrb.org/" >Boston Ruby Group</a> on lessons learned working to internationalization our Rails application. I don’t claim to be a i18n (or Iñtërnâtiônàlizætiøn) guru, but have done my time in the trenches in Java-land and now in Rails. The good news is that the <a href="http://guides.rubyonrails.org/i18n.html" >i18n story has gotten much better with Rails 2.2</a>, but there still are pitfalls and pain points. I gave an overview of i18n concerns, how Rails supports i18n and, of course, plugged my plugin, <a href="/2009/03/translator-rails-i18n/" >Translator</a> that aims to make it a little simpler.</p>
<p>The slides from the talk are below, <a href="http://www.slideshare.net/graysky/rails-internationalization" >on slideshare</a> or <a href="/public/rails_i18n_talk.pdf" >in pdf format</a>.</p>
<div class="slideshare-container" >
<div class="slideshare" id="__ss_1130834" style="width:425px;width:425px;"><a href="http://www.slideshare.net/graysky/rails-internationalization?type=presentation" title="Rails Internationalization" >Rails Internationalization</a><br/>
<object style="margin:0px" width="425" height="355" ><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=i18ntalk-090311080557-phpapp02&rel=0&stripped_title=rails-internationalization" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=i18ntalk-090311080557-phpapp02&rel=0&stripped_title=rails-internationalization" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355" ></embed></object></div>
</div>
<img src="http://feeds.feedburner.com/~r/graysky/~4/IBbAKXpZjaY" height="1" width="1"/>1http://graysky.org/2009/03/rails-internationalization-bostonrb/mikehttp://graysky.orghttp://graysky.org/?p=7212009-03-24T14:15:35Z2009-03-09T13:45:13Z<p>Internationalization (<a href="http://en.wikipedia.org/wiki/Internationalization" >i18n</a>) is one of those potentially necessary but not exactly thrilling tasks, so it is best when it is as simple as possible (related: I gave a <a href="/2009/03/rails-internationalization-bostonrb/" >recent talk at the Boston Ruby group on Rails i18n</a>.) To that end I’ve made <a href="http://github.com/graysky/translator/" >Translator</a>, a Rails plugin to simplify the i18n process. It is an extraction from what we’ve learned as we’ve been working to internationalize <a href="http://www.snapmylife.com/" >our Rails application</a>. </p>
<p>So what does it do?</p>
<h5>Automatic Scoping, or Keep Your Keys DRY</h5>
<p>The first thing it does is make the process of finding keys in localized bundles easier. The <a href=" http://api.rubyonrails.org/classes/I18n.html" >I18n module</a> introduced in Rails 2.2 is a great help but it hasn’t (yet) been incorporated in a very <em>Rails-y</em> way. Translator defines a convention for keys that follows a similar layout to a Rails project’s <tt>app</tt> folder. The benefit is that the code stays <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" >DRY</a> when fetching localized strings, saving precious typing. (Rails 2.3 recently added some <a href=" http://guides.rubyonrails.org/2_3_release_notes.html#partial-scopingfor-translations" >partial scoping for views</a>.) An example, starting with the <tt>en.yml</tt> that contains the strings for a fake blog app:</p>
<div class="wp_syntax" ><div class="code" ><pre class="ruby ruby" style="font-family:Monacofont-family:Monacomonospace;monospace;">en:
blog_posts: <span style="color:#008000; font-style:italic;" ># controller</span>
show: <span style="color:#008000; font-style:italic;" ># action</span>
title: <span style="color:#996600;" >"My Awesome Blog Post"</span></pre></div></div>
<p>The code to fetch the title string in the view is just <tt>t(‘title’)</tt> and Translator determines the implied scoping of <tt>“blog_posts.show”</tt>. It provides the same automatic scoping for mailers, models, controllers and views.</p>
<h5>Testing Help, or The Case of the Missing Key</h5>
<p>When extracting boatloads of strings from view templates, mail templates, flash & validation error messages it is easy to make mistakes. The default handling for for a missing translation in a view is to add a span tag with a “missing translation” error message. A reasonable handling in production, but during development and testing it is better to find any missing translations early. Translator adds a <tt>strict_mode</tt> that will fail any tests that encounter a missing translation, and it can be enabled for manually testing as well. Better to fail fast than find out later there was a typo in a key name.</p>
<p>To help with forgetting to extract strings into locale bundles, Translator adds a <tt>pseudo_translate</tt> mode that will make it obvious which strings did not come from a bundle. In <tt>pseudo_translate</tt> mode every string from a bundle has a marker character prepended and appended to it. This makes it easy to quickly eyeball a page and see if anything isn’t surrounded in brackets, like “[My Blog]“. Also, this can be useful to see how a layout will look if localized to a more verbose language. German, for example, tends to use something like 30% more characters than English, so you could pad each string with 10 characters and see how the layout looks.</p>
<h5>Graceful Locale Fallback, or No Hablo Espanol Hoy</h5>
<p>Translator adds a simple locale fallback mechanism that will first try the set locale, say <tt>:de</tt>, and if a string isn’t found will fallback to the <tt>default_locale</tt> set in I18n (<tt>:en</tt> by default). This can bridge the gap between rolling out new site changes even if all the translations aren’t ready for every language. </p>
<h5>Finally</h5>
<p>We’ve been using <a href="http://github.com/graysky/translator/" >Translator</a> in production so it should be ready for others to use. If you do I’d be interested in feedback and suggestions. The <a href="http://github.com/graysky/translator/" >Github page</a> has more detailed examples, <a href="http://graysky.github.com/translator/rdoc/" >RDocs</a> and how to get started. </p>
<img src="http://feeds.feedburner.com/~r/graysky/~4/ng44dB4wU-0" height="1" width="1"/>1http://graysky.org/2009/03/translator-rails-i18n/mikehttp://graysky.orghttp://graysky.org/?p=6992009-03-08T04:56:57Z2009-03-08T04:56:57Z<p>This here blog just got a facelift. The design had been feeling too busy and I wanted something cleaner and simpler. It remains to be seen whether this change will lead to me <em>actually</em> posting more often. As part of creating a new theme I decided to setup a copy of my blog on my Mac for easier developing. The live version is hosted on an Ubuntu slice which makes it hard to easily edit, as well as <a href="http://wordpress.org/" >Wordpress</a> only supporting one active theme at a time. And my blog has enough cruft that I wanted to test the new theme with real data, not just <em>lorem ipsum</em> filler. These are the steps I followed to get it working, including a few wrinkles to be worked around:</p>
<ul>
<li>All the assets are stored in Git — source control is your friend, after all. I cloned the git repo to <tt>~/Sites/graysky</tt> where the stock OS X version of Apache will pick it up. To have Apache process the <tt>.htaccess</tt> files that Wordpress typically uses I had to change 2 lines in <tt>httpd.conf</tt>. For both Directory “/” and “/Library/WebServer/Documents” the <tt>AllowOverride None</tt> option needs to be changed to <tt>AllowOverride All</tt>. Next, in the users folder I edited my personal conf file with an entry like this to set up my site to respond to requests for “graysky.test” (more on that next.)
<div class="wp_syntax" ><div class="code" ><pre class="bash bash" style="font-family:Monacofont-family:Monacomonospace;monospace;"><span style="color: #000000; font-weight: bold;" ><</span>VirtualHost <span style="color: #000000; font-weight: bold;" >*</span>:<span style="color: #000000;" >80</span><span style="color: #000000; font-weight: bold;" >></span>
Options FollowSymLinks
ServerName graysky.test
DocumentRoot <span style="color: #000000; font-weight: bold;" >/</span>Users<span style="color: #000000; font-weight: bold;" >/</span>mchampion<span style="color: #000000; font-weight: bold;" >/</span>Sites<span style="color: #000000; font-weight: bold;" >/</span>graysky
<span style="color: #000000; font-weight: bold;" ></</span>VirtualHost<span style="color: #000000; font-weight: bold;" >></span></pre></div></div>
<li>Open <tt>/etc/hosts</tt> and a line to map 127.0.0.1 to “graysky.test”. While it should work through using just an IP, I’ve found Wordpress works better if there is a true domain to match how it is configured. Make sure Apache is restarted through the command line or enabling “Web Sharing” in Preferences. Apache should now be ready to serve Wordpress locally.
<li>Next, on the production site I took a backup of the MySQL database using something like <tt>mysqldump —add-drop-table > blog.sql</tt> and stored the .sql file in git as well for save keeping. Before importing it, I opened it and did a blog replace of “graysky.org” with “graysky.test” for the local environment. While it should be possible to change the domain name from Wordpress itself, I found it was troublesome because it kept redirecting me to the actual “graysky.org” since that is what it thought it was serving. Finally import the sql file into MySQL after creating the correct database and appropriate user with privileges.
<p>The last hurdle was changing <tt>wp-config.php</tt> to handle a difference in where PHP-MySQL searches for the sock file.</p>
<div class="wp_syntax" ><div class="code" ><pre class="php php" style="font-family:Monacofont-family:Monacomonospace;monospace;"><span style="color: #666666; font-style: italic;" >// For OSX (development)</span>
<span style="color: #b1b100;" >if</span> <span style="color: #009900;" >(</span><span style="" >'graysky.test'</span> <span style="color: #339933;" >==</span> <span style="color: #000088;" >$_SERVER</span><span style="color: #009900;" >[</span><span style="" >'SERVER_NAME'</span><span style="color: #009900;" >]</span><span style="color: #009900;" >)</span> <span style="color: #009900;" >{</span>
<span style="color: #990000;" >define</span><span style="color: #009900;" >(</span><span style="" >'DB_HOST'</span><span style="color: #339933;" >,</span> <span style="" >'localhost:/var/run/mysqld/mysqld.sock'</span><span style="color: #009900;" >)</span>;
<span style="color: #009900;" >}</span>
<span style="color: #b1b100;" >else</span> <span style="color: #009900;" >{</span>
<span style="color: #666666; font-style: italic;" >// Normal linux install (production)</span>
<span style="color: #990000;" >define</span><span style="color: #009900;" >(</span><span style="" >'DB_HOST'</span><span style="color: #339933;" >,</span> <span style="" >'localhost'</span><span style="color: #009900;" >)</span>;
<span style="color: #009900;" >}</span></pre></div></div>
<li>After I tweaked fonts and color schemes, I checked in my new theme to git and it was just a matter of <tt>git push</tt> from my Mac, a <tt>git pull</tt> on Linux and activating the theme. And voilà, the blog has a new look!
</ul>
<img src="http://feeds.feedburner.com/~r/graysky/~4/LceukyI7jTE" height="1" width="1"/>1http://graysky.org/2009/03/wordpress-mac-os-x/