ヒレガス本 17章 課題

ランダムな直線の描画部分を曲線に変えろとの事。

これは簡単。変更部分は1カ所だけ。

thePoint = [self randomPoint];
[path lineToPoint:thePoint];

[path curveToPoint:[self randomPoint]
     controlPoint1:[self randomPoint]
     controlPoint2:[self randomPoint]];

に変えただけ。

プロジェクトファイルは、 DrawingFun.zip に置いておきます。

注意点

P302の図が説明文とAutosizingの設定が違っている。

../../../_images/image1.png

上記の設定だとNSScrollViewがリサイズされると、StrectViewも同じようにリサイズされてしまう。 P301の説明のように左下隅に固定してリサイズされないようにするには以下のように設定する。

../../../_images/image2.png

違いはAutosizingの中の十字の部分だけ。

ヒレガス本 16章 課題 その2

前回のアップデートスクリプトに加えて、ビルド時のチェックツールも作ってみた。

機能は、

  • 既に存在しないキーで指定された、翻訳文が有れば警告
  • ソースコード中にキーが有るが、*.stringsに存在しないキーがあれば警告
  • マージがコンクリフトしている場所をエラー

とするツールを作った。

#!/bin/sh
#
# *.lproj/Localizable.stringsの内容のチェックを行う

# stringsの拡張子
theStringsExt=".strings"

# ローカライズディレクトリの拡張子
theLocalizeExt=".lproj"

# Localizable.stringのファイル名
theLocalizableStrings="Localizable"$theStringsExt


##########################################################################################
#
# missingなキーワードの警告
#
##########################################################################################
# warningMessage フルパス 行番号 警告メッセージ 警告行のテキスト
function warningMissingKeyWordMessage() {

    local FULL_PATH_FILE_NAME=$1
    local KEYWORD_STRING=$2

    echo $FULL_PATH_FILE_NAME"::: warning:" $KEYWORD_STRING is a missing key word.":" $KEYWORD_STRING
}


##########################################################################################
#
# danglingなキーワードの警告
#
##########################################################################################

function warningDanglingKeyWordMessage() {

    local FULL_PATH_FILE_NAME=$1
    local KEYWORD_STRING=$2

    echo $FULL_PATH_FILE_NAME":"`grep -n $KEYWORD_STRING $FULL_PATH_FILE_NAME | cut -d":" -f1`":0: warning:" $KEYWORD_STRING is a dangling key word.":" `grep $KEYWORD_STRING $FULL_PATH_FILE_NAME`
}





##########################################################################################
#
# エラーメッセージを出力
#
##########################################################################################
# errorMessage フルパス 行番号 エラーメッセージ エラー行のテキスト
function errorConflictMessage() {

    local FULL_PATH_FILE_NAME=$1
    local LINE_NUMBER=$2
    local TEXT_STRING=$3

    echo $FULL_PATH_FILE_NAME":"$LINE_NUMBER":0: error: Merge conflict :" $TEXT_STRING
}

# Base.lprojのフルパス
theBaseLocalizableStrings=`pwd`/Base$theLocalizeExt/$theLocalizableStrings


# キーだけのリストにしてtmpへ保存する
# 一時的な作業フォルダーを作成する
theTempDir="tmp"
if ! [ -d $theTempDir ]; then
    mkdir $theTempDir
fi

# コメントと空白行を削除
cat $theBaseLocalizableStrings | sed -e 's:/\*.*\*/::' | sed -e '/^[<space><tab>]*$/d' | cut -d' ' -f1 > $theTempDir/tmplist.txt

# forループの区切りを改行だけにする
IFS=$'\n'


# Base.lproj/以下以外のLocalizable.stringsを全部ループ
for theIterator in `find \`pwd\` -regex ".*/Base.lproj/.*" -prune -o -regex ".*lproj/Localizable\.strings" -print`
do

    # 右側にだけある項目
    for theWord in `cat $theIterator | sed -e '/^<<<<<<<.*$/d' | sed -e '/^|||||||.*$/d' | sed -e '/^=======.*$/d' | sed -e '/^>>>>>>>.*$/d' |  sed -e 's:/\*.*\*/::' | sed -e '/^[<space><tab>]*$/d' | cut -d' ' -f1 | sort | uniq | comm -13 $theTempDir/tmplist.txt -`
    do
        warningDanglingKeyWordMessage $theIterator $theWord
    done

    # 左側にだけある項目
    for theWord in `cat $theIterator | sed -e 's/^<<<<<<<.*$//' | sed -e 's/^|||||||.*$//' | sed -e 's/^=======.*$//' | sed -e 's/^>>>>>>>.*$//' |  sed -e 's:/\*.*\*/::' | sed -e '/^[<space><tab>]*$/d' | cut -d' ' -f1 | sort | uniq | comm -23 $theTempDir/tmplist.txt -`
    do
        warningMissingKeyWordMessage $theIterator $theWord
    done

    # コンフリクトな行(下の四行など)をコンクリフトだと報告する
    # <<<<<<<
    # |||||||
    # =======
    # >>>>>>>
    for theConflictLine in `cat $theIterator | grep -n '^<<<<<<<\|^=======\|^>>>>>>>\|^|||||||'`
    do
        errorConflictMessage $theIterator `echo $theConflictLine | cut -d':' -f1` `echo $theConflictLine | cut -d':' -f2`
    done
done


# 後片付け
rm -f $theTempDir/tmplist.txt

XCodeに組み込んで使います。

ここに置いて、

../../../_images/filePath.png

こんな風に設定すると。

../../../_images/setting.png

ビルド時に、こんな風に警告が出たりエラーが出ます。

../../../_images/error.png

実用的になるかどうかは不明。 16章はここら辺で見切りを付けて明日からは次の章を行うつもり。

ヒレガス本 16章 課題

16章のローカライズの章には課題は無い。無いので自分で課題を作ってみた。

genstringsを使った文字列のローカライズを支援するツールを作成する。

genstringsが自動でLocalizable.stringを作れるのはよい。楽だ。 開発の最後の段階でローカライズを行い、1回の翻訳で全ての文字列を翻訳できるのならば、問題も無い。

しかし、実際には開発を行いながらローカライズも随時行うのが私のやり方です。面倒だと思ってもユーザーインターフェイスを追加したり削除したりします。 ソースコードもリファクタリングしてアラートの数を減らしたりします。

genstringsはLocalizable.stringを上書きしてしまうので、そのまま使うと翻訳済みのデータが消えてします。

そこで、genstringsとdiff3を組み合わせて、翻訳済みのデータを上書きしないようにシェルスクリプトを書いてみました。 練習でつくってみただけですので、実開発では使っていません。

#!/bin/sh
#
# updateLocalizableStrings
#
#  マージツール

# stringsの拡張子
theStringsExt=".strings"

# ローカライズディレクトリの拡張子
theLocalizeExt=".lproj"

# Localizable.stringのファイル名
theLocalizableStrings="Localizable"$theStringsExt

theTempDir="tmp"
theNewBaseLocalizableStrings=$theTempDir/$theLocalizableStrings


##########################################################################################
#
# 新たに生成されたLocalizable.stringsを"tmp/Localizable8.strings"に用意する
#
##########################################################################################

# 一時的な作業フォルダーを作成する
if ! [ -d $theTempDir ]; then
    mkdir $theTempDir
fi

# ソースコードをなめて、置換えテーブルを作成。作成場所は"./tmp/Localizable.strings"
genstrings -o $theTempDir `find . -name '*.[hcm]'`

# UTF-8に変換
iconv -f UTF-16 -t UTF-8 < $theNewBaseLocalizableStrings > $theNewBaseLocalizableStrings"_tmp"

# 後片付け
mv $theNewBaseLocalizableStrings"_tmp" $theNewBaseLocalizableStrings

##########################################################################################
#
# 古いLocalizable.stringsは"Base.lproj/Localizable.strings"にあると仮定する。なかったら作る
#
##########################################################################################

theOldBaseLocalizableStrings="Base"$theLocalizeExt/$theLocalizableStrings

if ! [ -f $theOldBaseLocalizableStrings ]; then
     cp $theNewBaseLocalizableStrings $theOldBaseLocalizableStrings
fi

##########################################################################################
#
# "Base"ディレクトリ以外の"*.lproj/Localizable.strings"をdiff3でアップデートする
#
##########################################################################################

for theLocaleStringsDir in `find . -name "*.lproj" -print`
do
    if [ $theLocaleStringsDir != "./Base.lproj" ]; then
        theLocaleStringsFile=$theLocaleStringsDir"/Localizable.strings"

        # 無ければ作り、あればdiff3でアップデート
        if ! [ -f $theLocaleStringsFile ]; then
            cp $theNewBaseLocalizableStrings $theLocaleStringsFile
        else
            diff3 -m $theLocaleStringsFile $theOldBaseLocalizableStrings $theNewBaseLocalizableStrings > $theLocaleStringsFile"_tmp"
            mv $theLocaleStringsFile"_tmp" $theLocaleStringsFile
        fi
    fi
done


# 最後に"Base.lproj/Localizable.strings"を更新する
cp $theNewBaseLocalizableStrings $theOldBaseLocalizableStrings

使い方は、 “*.m” や “*.lproj” があるディレクトリで呼出すだけです。 必要に応じて “*.lproj/Localizable.strings” のデータが更新されます。 コンクリフトが発生した場合は、gitやsvnでおなじみの”<<<<<<<<”の文字列が書き込まれますので随時対処してください。

このスクリプトの課題

  1. diffのように行毎に比較して判断するのではなく、”*.strings”をパースするコードを書けばもう少し知的な振る舞いが出来そう。
  2. ibtoolの出力に対してもアップデート出来るコマンドがあると便利かも。
  3. プログラマだけで開発するのならよいけど、翻訳担当にコマンドラインインターフェイスはキツいかも。せめてExcelで編集csvで読込みが出来るようにするべきでは?

ヒレガス本 15章 課題

削除しないが昇給なし(Keep, but no raise)ボタンを追加しろとの事。

これも簡単、KVCで行うと、NSArrayに含まれる全てのオブジェクトのプロパティーにアクセス出来る。 Controller経由でArrayを取得する事で、Undo/Redoにも対応してる。

- (IBAction) KeepButNoRaise:(id)sender
{
    NSArray* theSelectedPeople = [employeeController selectedObjects];

    [theSelectedPeople setValue:[NSNumber numberWithFloat:0.0]
                     forKeyPath:@"expectedRaise"];
}

後は、ボタンのenable/disableはbindingで選択された行数で判定。

../../../_images/binding.png

プロジェクトファイルは、 RaiseMan_AlertPanel に置いておきます。