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

<channel>
	<title>2718.us blog &#187; sh</title>
	<atom:link href="http://2718.us/blog/tag/sh/feed/" rel="self" type="application/rss+xml" />
	<link>http://2718.us/blog</link>
	<description>Miscellaneous Technological Geekery</description>
	<lastBuildDate>Tue, 18 May 2010 02:42:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Simplifying the Assembly of Localizations in Xcode</title>
		<link>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/</link>
		<comments>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 20:11:51 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[build script]]></category>
		<category><![CDATA[internationalization]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[nib]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[run script]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sh]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[target]]></category>
		<category><![CDATA[xcode]]></category>
		<category><![CDATA[xib]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=254</guid>
		<description><![CDATA[A comment on a bitbucket fork of Murky led me to &#8220;Automatically localize your nibs when building&#8220;, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode&#8211;pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, [...]]]></description>
			<content:encoded><![CDATA[<p>A comment on <a href="https://bitbucket.org/philippec/murky">a bitbucket fork</a> of <a href="http://bitbucket.org/snej/murky/wiki/Home">Murky</a> led me to &#8220;<a href="http://developer.casgrain.com/?p=94">Automatically localize your nibs when building</a>&#8220;, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode&#8211;pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, because I cannot adequately explain the big-picture part of the idea with a short quote.</p>
<p>My one complaint with the setup described is that the script for the &#8220;Run Script&#8221; build phase described there is a maintenance headache that I could do without.  Here&#8217;s my solution:  Create two new build targets, both of the &#8220;Shell Script&#8221; type&#8211;these are targets that just run a shell script, so they are created with only a &#8220;Run Script&#8221; build phase.  I called my two new targets &#8220;Create/Update English .strings files&#8221; and &#8220;Create/Update l10n XIBs&#8221; but you can call them whatever you want.</p>
<p>In the &#8220;Create/Update English .strings files&#8221; target&#8217;s &#8220;Run Script&#8221; phase, the script is:</p>
<div class="geshi no bash">
<div class="head"># Create/Update English .strings files</div>
<ol>
<li class="li1">
<div class="de1"><span class="kw1">for</span> xibFile <span class="kw1">in</span> <span class="st0">&quot;$PROJECT_DIR/English.lproj/&quot;</span><span class="sy0">*</span>.xib; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;ibtool &#8211;generate-strings-<span class="kw2">file</span> <span class="st0">&quot;${xibFile}.strings&quot;</span> <span class="st0">&quot;$xibFile&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">exit</span> <span class="nu0">0</span></div>
</li>
</ol>
</div>
<p>This uses <code>ibtool</code> to create a strings file for every XIB in the English localization (from <code>foo.xib</code>, <code>foo.xib.strings</code> will be created).</p>
<p>In the &#8220;Create/Update l10n XIBs&#8221; target&#8217;s &#8220;Run Script&#8221; phase, the script is:</p>
<div class="geshi no bash">
<div class="head"># Create/Update l10n XIBs</div>
<ol>
<li class="li1">
<div class="de1"><span class="re2">originalResourceDirectory=</span><span class="st0">&quot;$PROJECT_DIR/English.lproj&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">for</span> localizedDirectory <span class="kw1">in</span> <span class="st0">&quot;$PROJECT_DIR/&quot;</span><span class="sy0">*</span>.lproj; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="kw1">if</span> <span class="br0">&#91;</span> localizedDirectory <span class="sy0">!</span>= originalResourceDirectory <span class="br0">&#93;</span>; <span class="kw1">then</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">for</span> xibFile <span class="kw1">in</span> <span class="st0">&quot;${originalResourceDirectory}/&quot;</span><span class="sy0">*</span>.xib; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re2">xibBaseName=</span>$<span class="br0">&#40;</span><span class="kw2">basename</span> <span class="st0">&quot;${xibFile}&quot;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;ibtool &#8211;strings-<span class="kw2">file</span> <span class="st0">&quot;${localizedDirectory}/${xibBaseName}.strings&quot;</span> \</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &#8211;<span class="kw2">write</span> <span class="st0">&quot;${localizedDirectory}/${xibBaseName}&quot;</span> \</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&quot;$xibFile&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="kw1">fi</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">exit</span> <span class="nu0">0</span></div>
</li>
</ol>
</div>
<p>This goes through every <code>.lproj</code> directory except <code>English.lproj</code> and uses <code>ibtool</code> to apply the <code>.xib.strings</code> files in those localizations to the XIB files in <code>English.lproj</code>.</p>
<p>By having these as two separate targets, they aren&#8217;t run every time I build and each part can be run on its own, on demand.  By using the power of shell scripting, I avoid having to alter the scripts for every new localization or XIB.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Weather in Asterisk with Minimal Tools</title>
		<link>http://2718.us/blog/2008/07/20/simple-weather-in-asterisk-with-minimal-tools/</link>
		<comments>http://2718.us/blog/2008/07/20/simple-weather-in-asterisk-with-minimal-tools/#comments</comments>
		<pubDate>Sun, 20 Jul 2008 12:02:20 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Telephony]]></category>
		<category><![CDATA[asterisk]]></category>
		<category><![CDATA[asterisk dialplan]]></category>
		<category><![CDATA[dial plan]]></category>
		<category><![CDATA[dialplan]]></category>
		<category><![CDATA[nslu2]]></category>
		<category><![CDATA[sed]]></category>
		<category><![CDATA[sh]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[slug]]></category>
		<category><![CDATA[weather]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yahoo weather]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=54</guid>
		<description><![CDATA[I&#8217;ve been fiddling around with Asterisk on a slug box.  It&#8217;s working pretty well, but since I don&#8217;t want to deal with compiling things for the slug, I&#8217;m limited to the Asterisk modules that are available as binaries (not many).  I&#8217;m also using the older Asterisk 1.2.  This has led to some interesting hacks to [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been fiddling around with Asterisk on a <a href="http://2718.us/blog/2008/07/13/steps-to-unsling-the-nslu2/">slug box</a>.  It&#8217;s working pretty well, but since I don&#8217;t want to deal with compiling things for the slug, I&#8217;m limited to the Asterisk modules that are available as binaries (not many).  I&#8217;m also using the older Asterisk 1.2.  This has led to some interesting hacks to make things happen.  The end result of a lot of this hacking is a dialplan-shellscript-sed combo to read out some basic weather forecast info acquired from Yahoo.</p>
<p><span id="more-54"></span>First, the dialplan.</p>
<div class="geshi no asterisk">
<ol>
<li class="li1">
<div class="de1">exten =&gt; s,1,Set(defaultWeatherZip=10001)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,Playback(please-enter-your&amp;zip-code)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,Read(zip||5)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,GotoIf($[${LEN(${zip})} = 5]?getweather)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,Set(zip=${defaultWeatherZip})
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n(getweather),System(get_weather.sh ${zip} &gt; /tmp/weather-${UNIQUEID}.tmp)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,Readfile(weather=/tmp/weather-${UNIQUEID}.tmp,300)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,Playback(weather&amp;for&amp;zip-code)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,SayDigits(${zip})
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,Playback(silence/1&amp;${weather}&amp;silence/1)
</div>
</li>
<li class="li1">
<div class="de1">exten =&gt; s,n,System(rm /tmp/weather-${UNIQUEID}.tmp)</div>
</li>
</ol>
</div>
<p>If you&#8217;ve got a text-to-speech engine and can create smoother strings of spoken words than what I&#8217;ve strung together here, you&#8217;re better off (on my Asterisk box, I&#8217;m actually using files I made with Cepstral&#8217;s Allison-8k running on my Mac).  With my limited command set, there&#8217;s no nice way to grab the output of a system command, so I capture it into a temp file, use ReadFile() on the temp file, then delete the temp file.</p>
<p>That dialplan called a shellscript, get_weather.sh:</p>
<div class="geshi no bash">
<div class="head">#!/bin/sh</div>
<ol>
<li class="li1">
<div class="de1"><span class="kw3">echo</span> -n </div>
</li>
<li class="li1">
<div class="de1">&nbsp;`curl &#8211;silent http:<span class="sy0">//</span>weather.yahooapis.com<span class="sy0">/</span>forecastrss?<span class="re2">p=</span>$<span class="nu0">1</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sy0">|</span> <span class="kw2">sed</span> -n -f <span class="sy0">/</span>opt<span class="sy0">/</span>var<span class="sy0">/</span>lib<span class="sy0">/</span>asterisk<span class="sy0">/</span>yahoo_weather_to_asterisk.<span class="kw2">sed</span> </div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="sy0">|</span> <span class="kw2">sed</span> -e <span class="st0">&#39;N;s/(.*)n(.*)/1&amp;silence/2&amp;2/&#39;</span>`</div>
</li>
</ol>
</div>
<p>This uses curl to get the weather from Yahoo, runs it through a complicated sed program which yields two lines of forecast (as &amp;-joined lists of sound files, suitable for running as an argument to Playback() in Asterisk), then joins the two lines with 2 seconds of silence.  The &#8220;echo -n &#96;&#8230;&#96;&#8221; is a trick for stripping the trailing newline from the output of curl/sed (a newline inside the Playback() get interpreted as part of the filename, which it isn&#8217;t).</p>
<p>Finally, the sed program that processes the output from Yahoo:</p>
<div class="geshi no sed">
<ol>
<li class="li1">
<div class="de1">/^&lt;yweather :forecast/{
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# replace days with sound files
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Mon/day-1/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Tue/day-2/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Wed/day-3/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Thu/day-4/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Fri/day-5/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Sat/day-6/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Sun/day-0/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# replace months with sound files
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Jan/mon-0/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Feb/mon-1/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Mar/mon-2/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Apr/mon-3/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/May/mon-4/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Jun/mon-5/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Jul/mon-6/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Aug/mon-7/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Sep/mon-8/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Oct/mon-9/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Nov/mon-10/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/Dec/mon-11/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# rearrange forecast lines
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/^&lt;yweather:forecast day=&quot;(day-[0-6])&quot; date=&quot;([0-9]*) (mon-[0-9]*) ([0-9]*)&quot; low=&quot;([0-9]*)&quot; high=&quot;([0-9]*)&quot; .*/&gt;/digits/1&amp;digits/3&amp;DATE-2&amp;silence/1&amp;high&amp;TEMP-6&amp;silence/1&amp;low&amp;TEMP-5/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# replace the date with proper ordinal sound files
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# thirty + one is a special case
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/DATE-31/digits/30&amp;digits/h-1/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# twenty + [1-9]
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/DATE-2([1-9])/digits/20&amp;digits/h-1/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 1-20,30 all have their own files
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/DATE-([0-9]*)/digits/h-1/
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# negative temps
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP&#8211;/minus&amp;TEMP-/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 100 is a special case
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-100/digits/1&amp;digits/hundred/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 10?
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-10([1-9])/digits/1&amp;digits/hundred&amp;digits/1/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 11?
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-11([0-9])/digits/1&amp;digits/hundred&amp;digits/11/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 1?0
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-1([2-9])0/digits/1&amp;digits/hundred&amp;digits/10/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 1??
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-1([2-9])([1-9])/digits/1&amp;digits/hundred&amp;digits/10&amp;digits/2/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# 1?
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-1([0-9])/digits/11/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# ?0
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-([2-9])0/digits/10/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# ??
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-([2-9])([1-9])/digits/10&amp;digits/2/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;# ?
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;s/TEMP-([0-9])/digits/1/g
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;p
</div>
</li>
<li class="li1">
<div class="de1">}</div>
</li>
</ol>
</div>
<p>The &#8220;rearrange&#8221; line does most of the work of taking apart the last bits of what Yahoo gave us; the rest of the sed program is dominated by converting months/days/numbers into references to the appropriate Asterisk sound files.  [<em>Note</em>: Since I only had today's data with which to work, I made some guesses as to what the shortened forms of most of the months and days would be, as well as how temperatures that weren't two-digit positive numbers would be presented.]</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2008/07/20/simple-weather-in-asterisk-with-minimal-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

