2718.us blog » sh http://2718.us/blog Miscellaneous Technological Geekery Tue, 18 May 2010 02:42:55 +0000 en hourly 1 http://wordpress.org/?v=3.0.4 Simplifying the Assembly of Localizations in Xcode http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/ http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/#comments Thu, 22 Apr 2010 20:11:51 +0000 2718.us http://2718.us/blog/?p=254 A comment on a bitbucket fork of Murky led me to “Automatically localize your nibs when building“, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode–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.

My one complaint with the setup described is that the script for the “Run Script” build phase described there is a maintenance headache that I could do without.  Here’s my solution:  Create two new build targets, both of the “Shell Script” type–these are targets that just run a shell script, so they are created with only a “Run Script” build phase.  I called my two new targets “Create/Update English .strings files” and “Create/Update l10n XIBs” but you can call them whatever you want.

In the “Create/Update English .strings files” target’s “Run Script” phase, the script is:

# Create/Update English .strings files
  1. for xibFile in "$PROJECT_DIR/English.lproj/"*.xib; do
  2.  ibtool –generate-strings-file "${xibFile}.strings" "$xibFile"
  3. done
  4. exit 0

This uses ibtool to create a strings file for every XIB in the English localization (from foo.xib, foo.xib.strings will be created).

In the “Create/Update l10n XIBs” target’s “Run Script” phase, the script is:

# Create/Update l10n XIBs
  1. originalResourceDirectory="$PROJECT_DIR/English.lproj"
  2. for localizedDirectory in "$PROJECT_DIR/"*.lproj; do
  3.  if [ localizedDirectory != originalResourceDirectory ]; then
  4.   for xibFile in "${originalResourceDirectory}/"*.xib; do
  5.    xibBaseName=$(basename "${xibFile}")
  6.    ibtool –strings-file "${localizedDirectory}/${xibBaseName}.strings" \
  7.     –write "${localizedDirectory}/${xibBaseName}" \
  8.     "$xibFile"
  9.   done
  10.  fi
  11. done
  12. exit 0

This goes through every .lproj directory except English.lproj and uses ibtool to apply the .xib.strings files in those localizations to the XIB files in English.lproj.

By having these as two separate targets, they aren’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.

]]>
http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/feed/ 0
Simple Weather in Asterisk with Minimal Tools http://2718.us/blog/2008/07/20/simple-weather-in-asterisk-with-minimal-tools/ http://2718.us/blog/2008/07/20/simple-weather-in-asterisk-with-minimal-tools/#comments Sun, 20 Jul 2008 12:02:20 +0000 2718.us http://2718.us/blog/?p=54 I’ve been fiddling around with Asterisk on a slug box.  It’s working pretty well, but since I don’t want to deal with compiling things for the slug, I’m limited to the Asterisk modules that are available as binaries (not many).  I’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.

First, the dialplan.

  1. exten => s,1,Set(defaultWeatherZip=10001)
  2. exten => s,n,Playback(please-enter-your&zip-code)
  3. exten => s,n,Read(zip||5)
  4. exten => s,n,GotoIf($[${LEN(${zip})} = 5]?getweather)
  5. exten => s,n,Set(zip=${defaultWeatherZip})
  6. exten => s,n(getweather),System(get_weather.sh ${zip} > /tmp/weather-${UNIQUEID}.tmp)
  7. exten => s,n,Readfile(weather=/tmp/weather-${UNIQUEID}.tmp,300)
  8. exten => s,n,Playback(weather&for&zip-code)
  9. exten => s,n,SayDigits(${zip})
  10. exten => s,n,Playback(silence/1&${weather}&silence/1)
  11. exten => s,n,System(rm /tmp/weather-${UNIQUEID}.tmp)

If you’ve got a text-to-speech engine and can create smoother strings of spoken words than what I’ve strung together here, you’re better off (on my Asterisk box, I’m actually using files I made with Cepstral’s Allison-8k running on my Mac).  With my limited command set, there’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.

That dialplan called a shellscript, get_weather.sh:

#!/bin/sh
  1. echo -n
  2.  `curl –silent http://weather.yahooapis.com/forecastrss?p=$1
  3.   | sed -n -f /opt/var/lib/asterisk/yahoo_weather_to_asterisk.sed
  4.   | sed -e 'N;s/(.*)n(.*)/1&silence/2&2/'`

This uses curl to get the weather from Yahoo, runs it through a complicated sed program which yields two lines of forecast (as &-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 “echo -n `…`” 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’t).

Finally, the sed program that processes the output from Yahoo:

  1. /^<yweather :forecast/{
  2.  # replace days with sound files
  3.  s/Mon/day-1/
  4.  s/Tue/day-2/
  5.  s/Wed/day-3/
  6.  s/Thu/day-4/
  7.  s/Fri/day-5/
  8.  s/Sat/day-6/
  9.  s/Sun/day-0/
  10.  
  11.  # replace months with sound files
  12.  s/Jan/mon-0/
  13.  s/Feb/mon-1/
  14.  s/Mar/mon-2/
  15.  s/Apr/mon-3/
  16.  s/May/mon-4/
  17.  s/Jun/mon-5/
  18.  s/Jul/mon-6/
  19.  s/Aug/mon-7/
  20.  s/Sep/mon-8/
  21.  s/Oct/mon-9/
  22.  s/Nov/mon-10/
  23.  s/Dec/mon-11/
  24.  
  25.  # rearrange forecast lines
  26.  s/^<yweather:forecast day="(day-[0-6])" date="([0-9]*) (mon-[0-9]*) ([0-9]*)" low="([0-9]*)" high="([0-9]*)" .*/>/digits/1&digits/3&DATE-2&silence/1&high&TEMP-6&silence/1&low&TEMP-5/
  27.  
  28.  # replace the date with proper ordinal sound files
  29.  # thirty + one is a special case
  30.  s/DATE-31/digits/30&digits/h-1/
  31.  # twenty + [1-9]
  32.  s/DATE-2([1-9])/digits/20&digits/h-1/
  33.  # 1-20,30 all have their own files
  34.  s/DATE-([0-9]*)/digits/h-1/
  35.  
  36.  # negative temps
  37.  s/TEMP–/minus&TEMP-/g
  38.  
  39.  # 100 is a special case
  40.  s/TEMP-100/digits/1&digits/hundred/g
  41.  # 10?
  42.  s/TEMP-10([1-9])/digits/1&digits/hundred&digits/1/g
  43.  # 11?
  44.  s/TEMP-11([0-9])/digits/1&digits/hundred&digits/11/g
  45.  # 1?0
  46.  s/TEMP-1([2-9])0/digits/1&digits/hundred&digits/10/g
  47.  # 1??
  48.  s/TEMP-1([2-9])([1-9])/digits/1&digits/hundred&digits/10&digits/2/g
  49.  # 1?
  50.  s/TEMP-1([0-9])/digits/11/g
  51.  # ?0
  52.  s/TEMP-([2-9])0/digits/10/g
  53.  # ??
  54.  s/TEMP-([2-9])([1-9])/digits/10&digits/2/g
  55.  # ?
  56.  s/TEMP-([0-9])/digits/1/g
  57.  
  58.  p
  59. }

The “rearrange” 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. [Note: 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.]

]]>
http://2718.us/blog/2008/07/20/simple-weather-in-asterisk-with-minimal-tools/feed/ 0