leopardgeckoのブログ

Macの関連事項など

GeekToolでディスク容量を整理して表示する。

2019/1/31 追記: これは古い情報です。改定版は下のリンクから。

leopardgecko.hatenablog.com

 

GeekToolでハードディスクなどの容量を表示するために普通使われているスクリプト

df -hl

のようなものでしょう。これはこんな感じの表示になります。

f:id:leopardgecko:20161101110104p:plain

ご覧の通りかなりゴチャゴチャしており場所も取ってしまうので、もっとシンプルに見やすく整理したくなるのが人情というものだろうと思います。

内蔵ディスクのみを表示するならばFilesystemを決め打ちして必要なフィールドだけ取り出すというシンプルな技が使えるのですが、外付けドライブやSDカードやネットワーク経由でマウントしているものなども表示させたい場合には少々の工夫が必要になります。

 

情報をトータル容量と使用容量と空き容量とディスク名に絞り、外付けドライブやネットワーク経由のマウントも表示させるスクリプトは以下の通りです。フォントは等幅のものを指定してください。

df -h | grep 'Filesystem\|/dev/\|/Volumes/' | awk '{for(i=2;i<=4;i++){gsub("Ti","TB",$i);gsub("Gi","GB",$i);gsub("Mi","MB",$i)};printf " %5s  %5s  %5s  %8s  ",$2,$3,$4,$5;for(i=9;i<=NF;i++)printf $i" ";print ""}'

例えば二つの外付けディスクを使用している場合には以下のような表示になります。

f:id:leopardgecko:20161031211403p:plain

だいぶスッキリした感じになりました。

 

ここで終わりにしても良いのですが、さらに一歩進んでこんな感じの表示にしてみます。

f:id:leopardgecko:20161031230235p:plain

一番上の行に下線をつけて、ドライブ名をFinderでの一般的な表示にして左側に移し、使用量の割合にグラフを追加しています。

このgeekletにはちょっとしたトリックがあります。日本語などのマルチバイト文字が含まれるときれいに桁合わせができなくなってしまうので、ディスクドライブの名称のみを表示するgeekletとディスク容量を表示するgeekletの二つを作り、その二つを同じ座標で重ねて表示しています。

 

まず、ディスク名を表示するスクリプトは以下の通りです。起動ドライブの名称は「df」から取得すると名無しになってしまうので「Macintosh HD」に決め打ちしています。他の名前に変えたい場合はスクリプトの該当部分を書き換えてください。その他のディスク名はFinderで表示されている名前と同じものになるはずです。

echo
df -h | grep '/dev/\|/Volumes/' | awk -F"/Volumes/" '{printf "%.15s",$2;print""}' | sed -e 's/^$/Macintosh HD/'

 

 

次に容量とグラフを表示するスクリプトです。グラフ表示のため少々複雑な処理になっています。「df」で取得したデータを一行ずつ配列変数に代入して、for文で一行ずつ処理していくという方法でなんとか整形しています。

echo "\033[4mDrive             Size   Used  Avail         Capacity\033[0m"
diskdata=(`df -h | grep '/dev/\|/Volumes/' | awk 'BEGIN{OFS=","}{print $2,$3,$4,$5}' | sed -e 's/Mi/MB/g' -e 's/Gi/GB/g' -e 's/Ti/TB/g' -e 's/\%//g'`)
for (( i = 0; i < ${#diskdata[@]}; ++i ))
do
    diskcapa[$i]=`echo ${diskdata[$i]} | awk -F, '{print $4}'`
    printf "                "
    echo ${diskdata[$i]} | awk -F, '{printf(" %5s  %5s  %5s  ",$1,$2,$3)}'
    typeset -i b=9
    while [ $b -lt ${diskcapa[$i]} ]
    do
        echo "\033[0;37m▇\033[0m\c"
   	b=`expr $b + 10`
    done
    while [ $b -lt 100 ]
    do
        echo "\033[0;30m▇\033[0m\c"
        b=`expr $b + 10`
    done
    printf " %3s%%\n" ${diskcapa[$i]}
done

この二つのgeekletを全く同じ座標に置けば提示した画像のような表示になります。

 

今回紹介したスクリプトは新たにSDカードなどをマウントして表示をリフレッシュさせた時には表示行数がその分だけ増えますので、geekletの表示サイズは縦に少し余裕を持たせていた方が良いでしょう。

 

今回紹介したスクリプトを使ったgeekletは下記からダウンロードできます。

[Geekletのダウンロード]

GeekToolで稼働時間をスマートに表示する。

GeekToolで稼働時間を表示するためには、uptimeの出力からawkを使って必要なフィールドを拾ってくるスクリプトが一般的だろうと思います。

例えばこういうものです。

uptime | awk '{print "UPTIME: " $3 " " $4 " " $5}'

このシンプルなスクリプトでは稼働時間が1日以上経過している場合は時間だけ表示できるのですが、それ未満の場合では余計なものまで表示してしまいます。例えば稼働時間が1時間31分の場合は以下のようになってしまいます。

UPTIME: 1:31, 2 users,

上の表示はまだ許容範囲かもしれませんが、1時間未満の場合はさらに表示が崩れて意味不明となってしまいます。

UPTIME: 21 mins, 2 

そのくらいは気にしないというならばこのままでも良いのですが、きれいに時間だけ表示させてスッキリしたいというニーズもあろうかと思い素人ながらに頭をひねってみました。

 

uptimeをそのまま出力すると24時間未満では以下のような感じ。

12:11  up 1:31, 2 users, load averages: 1.38 1.41 1.44
11:02  up 21 mins, 2 users, load averages: 1.32 1.56 2.09

1日以上経過している場合は以下のようなフォーマットになります。

10:09  up 3 days,  14:28, 2 users, load averages: 1.34 1.50 1.48

フィールド数が違う上にスペースが入るパターンも違うので、単純に3〜5番目のフィールドを抜き出すと最後のパターン以外の時は表示が崩れてしまうことがお分かりになるだろうと思います。 

 

余計なものが混じらないようにするスクリプトの流れを考えてみます。

uptimeで最初に出力される現在時刻と「up 」という文字は不要なので、まずawkで「up 」を区切り文字に指定して、そこから先のフィールドを抜き出します。問題はその次で、時間表示のフォーマットがバラバラである上にコンマの後に来るものがユーザー数だったり時間だったりします。とりあえずawkでコンマ区切りのフィールドとして最初の二つを取得しておいて、二つ目のフィールドに「user」という文字列が含まれる場合はフィールドごと削除してしまうという動作にしてみます。

それをスクリプトで書いてみるとこんな感じになります。

uptime | awk -F'up ' '{print $2}' | awk -F, '{if($2 ~ /user/)$2="";print "Uptime: "$1 $2}'
UPTIME: 1:31
UPTIME: 21 mins
UPTIME: 3 days  14:28

Terminalにそのままコピペしても使えますので試してみてください。

(2016年12月12日 追記:当初は最初のフィールドの抜き出しにcutを使っていたが、uptimeのスペースの数は一定ではないようなのでawkで区切り文字を指定する方法に変更)

HomebrewでRictyを入れた後にRicty Discordを追加する。

Rictyというとても見やすいプログラミング用フォントがあります。プログラミング以外にもTerminalでの表示など等幅フォントを使うときにRictyの視認性の良さは重宝します。等幅フォント前回の記事のようにGeekToolで表示がずれないようにするのにも便利なものです。

しかしRictyはライセンスの関係でフォントそのものは配布できないとのことで、いくつかの材料を集めて自分で生成しなければなりません。サイトにある指示通りにすれば良いのですが、それが面倒な場合はHomebrewを使ってコマンド一発で入れることができます。Homebrewが入っていれば、やるべきことはTerminalを立ち上げて

brew tap sanemat/font
brew install ricty

と打つだけです。必要なファイルは全て自動で集めてフォントの生成からインストールまでやってくれます。

ただしこれでは普通のRictyがインストールできるだけで、どういうわけか同時にインストールされるはずの派生フォントであるRicty Discordが生成されません。Ricty Discordがどういうものであるかは公式サイトで確認していただくとして、ここではHomebrewでRictyを入れた後にRicty Discordを追加する方法を紹介します。

 

上述のコマンドでRictyをインストールした後に、Rictyの公式サイトから「ricty_generator.sh」と「ricty_discord_converter.pe」をダウンロードして、/usr/local/Cellar/ricty/4.0.1/share/fonts/に置きます。Terminalでそのディレクトリに移動して、

chmod +x ricty_generator.sh
./ricty_generator.sh auto

と入力すると同じディレクトリに「RictyDiscord-Regular.ttf」と「RictyDiscord-Bold.ttf」が新たに生成されるので、

cp -f RictyDiscord*.ttf ~/Library/Fonts/
fc-cache -vf

と入力するとRicty Discordがインストールされて使用できるようになります。

 

※これはあくまで現時点での情報で、将来Rictyがバージョンアップされれば記事中の「4.0.1」という部分は変更になるはずなので適宜置き換えてください。

GeekToolでお天気表示

注:ここの記事は新たに書き直しました。
GeekToolでお天気表示 改訂版を参照してください。

追記:
2016年12月12日:天気の表示に「&」が含まれていると表示がおかしくなる問題を修正。
2017年 7月26日:httpsを指定しないと表示できなくなったようなのでスクリプトを修正。プロキシについての記述追加。

Mac用デスクトップカスタマイズソフトのGeekToolスクリプト次第でほぼ何でもできる優れものです。ただしスクリプトをいちいち書かなければいけないという難点があります。単純なものであれば良いのですが、例えば天気を表示しようと思えば天気予報サイトをソースから解析しなければなりませんし、せっかくスクリプトを書いても仕様が変更されればまた解析からやり直さなければなりません。

それを自分で一から全てやるのは結構な手間ですから、今回は天気予報サイトのAccuWeatherから取得した天気を表示させるスクリプトをいくつかご紹介します。

例えば下の画像のような感じで表示させるとします。上段が本日の最高・最低気温と現在の気温・天気です。中段が時間単位の天気予報でとりあえず16時間後まで表示。下段が明日と週末の天気予報です。

f:id:leopardgecko:20161025133927p:plain

 

現在の気温と天気を表示してリアルな画像の天気アイコンを取得するスクリプトは以下の通りです。GeelToolの「Shell」をデスクトップの好きなところに貼り付けて「Command」にコピペしてください。スクリプトの「https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230」の部分は、https://www.accuweather.com/en/jp/japan-weatherにアクセスしてお住いの市や区の名前をローマ字で検索し、出てきたURLに変更してください。この例では東京都江東区の天気が表示されます。また、ここでの「koto-ku」と「221230」にあたる文字と数値は他のスクリプトの書き換えにも使いますので記録しておいてください。

天気アイコンの画像は「/tmp/weather_now.png」に保存されるので、GeekToolの「Image」でURLを「file://localhost/private/tmp/weather_now.png」と指定してください。

画像をリアルではなく他と同じシンプルなものにしたい場合は、スクリプトの最後の方の「https://vortex.accuweather.com/adc2010/images/icons-numbered/」のところを「https://vortex.accuweather.com/adc2010/images/slate/icons/」に変えてください。 

社内での使用などでプロキシを指定する必要がある場合は、「curl」の後に「--proxy http://hogehoge:8080」のような形で指定してください。例えば「# 元データ取得」のところであれば、「weather_data=`curl --proxy http://hogehoge:8080 --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"`」のような記述になります。一番最後の行で「curl」が出てくるところも同じように記述を追加してください。他のスクリプトでも「curl」のところは全て追加が必要です。

# 現在の天気
# 元データ取得 weather_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"` # 現在の温度と天気を取得して表示 echo "$weather_data" | grep -A 8 'Current Weather' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " " # 天気アイコンのナンバーを取得し二桁でゼロパディングする icon_cur=`echo "$weather_data" | grep -A 2 'Current Weather' | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789' | awk '{printf "%02d", $1}'` # 天気アイコンナンバーをURLに変換して画像を保存 echo "https://vortex.accuweather.com/adc2010/images/icons-numbered/"$icon_cur"-xl.png" | xargs curl --silent -o /tmp/weather_now.png

 

最高気温と最低気温の表示は以下の通りです。AccuWeatherでは夜になると最低気温のみの表示に変わるのですが、それにも対応させてあります。

「koto-ku」と「221230」と書いてあるところは上と同じ要領でお住いの地域に適宜変更してください。以下のスクリプトも同様です。

# 最高気温と最低気温
# 元データ取得 weather_today=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/daily-weather-forecast/221230?day=1"` # 今日の最高温度と最低温度を取得して表示 echo "$weather_today" | grep -A 6 'Today\|Tonight' | grep -e 'large-temp\|small-temp\|temp-label tonight selected' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "

 

 以下は現在時刻から8時間後までと、9時間後から16時間後までのスクリプトです。これは等幅フォントを指定しないと表示がずれますのでご注意を。(上の画像ではRicty Discordというプログラミング用の等幅フォントを使っています)

天気アイコンの画像は「/tmp/weather_hour_0.png」から連番で「/tmp/weather_hour_7.png」まで保存されるので、上の応用で画像を一つずつ貼り付けて並べてください。

視認性を上げるためにamとpmの色を変えていますが、色を変えたくない場合は「時刻を左揃え8桁で表示」のところの「 | sed -e s/am/`echo "\033[0;31mam\033[0m"`/g -e s/pm/`echo "\033[0;34mpm\033[0m"`/g」をごそっと削除してください。(「printf "%-8s" ${current_time[*]}」だけ残す)

まず一つ目、現在時刻から8時間後までのスクリプトはこんな感じです。

# 現在時刻から8時間後までの天気
# 元データ取得 my_hour=`date +%H` curl_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/hourly-weather-forecast/221230?hour=$my_hour"` # 8時間分の時刻を取得(後で配列変数として使う。以下同様) current_time=(`echo "$curl_data" | grep -A 37 "overview-hourly" | grep -A 29 "first-col" | sed -e 's/<[^>]*>//g' -e 's/^ *//' | tr -d "\r"`) # 8時間分の天気を取得(スペースを含んだデータをIFSを使って配列に格納) _IFS="$IFS";IFS="_" current_weather=(`echo "$curl_data" | grep -A 67 "overview-hourly" | grep -A 23 "Forecast" | sed -e 's/<[^>]*>//g' -e 's/^ *//' -e '1,2d' -e 's/ \&amp;/\&/g' | tr -s '\r\n' '_'`) IFS="$_IFS" # 8時間分の天気アイコンのナンバーを取得 current_icon=(`echo "$curl_data" | grep -A 38 "overview-hourly" | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789\n'`) # 時刻を左揃え8桁で表示 printf "%-8s" ${current_time[*]} | sed -e s/am/`echo "\033[0;31mam\033[0m"`/g -e s/pm/`echo "\033[0;34mpm\033[0m"`/g # 天気を左揃え8桁かつ2段で表示 for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $1}' done echo for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $2}' done # 天気アイコンを取得して保存(URLに使うアイコンのナンバーはゼロパディングする) for (( i=0; i < ${#current_icon[@]}; ++i)) do current_icon[$i]=`printf "%02d" ${current_icon[$i]}` echo "https://vortex.accuweather.com/adc2010/images/slate/icons/${current_icon[$i]}-s.png" | xargs curl --silent -o /tmp/weather_hour_$i.png done

 

9時間後から16時間後まではこんな感じ。上のスクリプトの応用ですから内容はほとんど同じです。「later=」の後の数値を「16」にすれば17時間後から24時間後の表示にすることもできます。天気アイコンの画像は「/tmp/weather_hour_8.png」から連番で「/tmp/weather_hour_15.png」まで保存されます。

# 9時間後から16時間後までの天気
# 何時間後? later=8 # 元データ取得 my_hour=`date +%H` ; my_hour=`expr $my_hour + $later` curl_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/hourly-weather-forecast/221230?hour=$my_hour"` # 時刻を取得 current_time=(`echo "$curl_data" | grep -A 37 "overview-hourly" | grep -A 29 "first-col" | sed -e 's/<[^>]*>//g' -e 's/^ *//' | tr -d "\r"`) # 天気を取得(スペースを含んだデータをIFSを使って配列に格納) _IFS="$IFS";IFS="_" current_weather=(`echo "$curl_data" | grep -A 67 "overview-hourly" | grep -A 23 "Forecast" | sed -e 's/<[^>]*>//g' -e 's/^ *//' -e '1,2d' -e 's/ \&amp;/\&/g' | tr -s '\r\n' '_'`) IFS="$_IFS" # 天気アイコンのナンバーを取得 current_icon=(`echo "$curl_data" | grep -A 38 "overview-hourly" | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789\n'`) # 時刻を左揃え8桁で表示 printf "%-8s" ${current_time[*]} | sed -e s/am/`echo "\033[0;31mam\033[0m"`/g -e s/pm/`echo "\033[0;34mpm\033[0m"`/g # 天気を左揃え8桁かつ2段で表示 for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $1}' done echo for (( i=0; i < ${#current_weather[@]}; ++i)) do echo "${current_weather[$i]}" | awk '{printf "%-8s", $2}' done # 天気アイコンを取得して保存(取得するアイコンのナンバーはゼロパディングする) for (( i=0; i < ${#current_icon[@]}; ++i)) do current_icon[$i]=`printf "%02d" ${current_icon[$i]}` echo "https://vortex.accuweather.com/adc2010/images/slate/icons/${current_icon[$i]}-s.png" | xargs curl --silent -o /tmp/weather_hour_`expr $i + $later`.png done

 

明日の天気は以下の通り。AccuWeatherでは深夜を過ぎるとその日の早朝の天気に表示が変わりますが、それにも対応させてあります。天気アイコンは「/tmp/weather_tomorrow.png」に保存されます。

# 明日の天気取得・表示
weather_data=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weather-forecast/221230"`

echo "$weather_data" | grep -e 'Tomorrow\|Early' | sed -e 's/<[^>]*>//g' -e 's/^ *//' 
echo "$weather_data" | grep -A 9 'Tomorrow\|Early' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "

# 明日の天気アイコンのナンバーを取得しゼロパディングする
icon_data=`echo "$weather_data" | grep -A 2 'Tomorrow\|Early' | grep 'icon' | sed -e 's/[^"]*"\([^"]*\)".*/\1/' | tr -cd '0123456789' | awk '{printf "%02d", $1}'`

# 天気アイコン保存 echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_data"-l.png" | xargs curl --silent -o /tmp/weather_tomorrow.png

 

週末の天気は以下の通り。天気アイコンの場所は土曜日が「/tmp/weather_sat.png」、日曜日が「/tmp/weather_sun.png」です。

# 土日の天気取得・表示
weather_weekend=`curl --silent "https://www.accuweather.com/en/jp/koto-ku/221230/weekend-weather/221230"`

echo "\033[0;34mSaturday\033[0m"
echo "$weather_weekend" | grep -A 9 'Saturday' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "
echo "\n\033[0;31mSunday\033[0m"
echo "$weather_weekend" | grep -A 9 'Sunday' | grep -e 'large-temp\|cond' | sed -e 's/<[^>]*>//g' | sed -e 's/&deg;/°/g' -e 's/^ *//' | tr "\r\n" " "

# 土日の天気アイコン取得
icon_sat=`echo "$weather_weekend" | grep -A 2 'Saturday' | grep 'icon' | sed -e 's/^ *//' -e s/'<div class=\"icon '//g -e s/' \"><\/div>'//g -e s/i-//g -e 's/\([0-9]*\).*/\1/' | tr -d '\n' | tr -d '\r'`
icon_sat=`printf "%.2d\n" $icon_sat`
icon_sun=`echo "$weather_weekend" | grep -A 2 'Sunday' | grep 'icon' | sed -e 's/^ *//' -e s/'<div class=\"icon '//g -e s/' \"><\/div>'//g -e s/i-//g -e 's/\([0-9]*\).*/\1/' | tr -d '\n' | tr -d '\r'`
icon_sun=`printf "%.2d\n" $icon_sun`

# 天気アイコン保存 echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_sat"-l.png" | xargs curl --silent -o /tmp/weather_sat.png echo "https://vortex.accuweather.com/adc2010/images/slate/icons/"$icon_sun"-l.png" | xargs curl --silent -o /tmp/weather_sun.png

 

他にもAccuWeatherには色々な予報がありますので、これまでに挙げたスクリプトの仕組みがわかれば様々な応用が可能でしょう。要はHTMLソースの中から欲しい情報をゲットするためのキーワードを拾ってHTMLタグを除去してテキストを整形しているだけですから、キーワードを確実に拾えるパターンを見つけさえすればOKです。

MacネイティブのInkscape

オフィシャルのMacInkscapeはXQuartzが必要とされます。そのために、ショートカットで使うキーがMacでお馴染みのコマンドキーではなくコントロールキーになってしまったり、普通の設定でコピペをするとビットマップでペーストされてしまったり、日本語が直接入力できないなどの難点がいくつかあります。

その解決策の一つとして、macOSネイティブのInkscapeを使うという方法があります。コピー&ペーストはMac標準のショートカットでできる上にデータがビットマップに勝手に変換されたりしませんし、日本語入力も一応可能です。ただしこれは正式版のアプリではありませんし、日本語入力が可能とはいえども変換が確定されるまでインライン表示されないという独特の癖がある点に留意する必要はあります。

今のところの最新版は

https://inkscape.org/en/~su_v/%E2%98%85inkscape-osxmenu-r12922-gtk2

のようです。

これも本家と同様にメニュー表示のバグがそのまま残っていますのでそのままでは日本語メニューが表示できませんが、前回記事の応用で修正が可能です。

上記のサイトからダウンロードしてきた「Inkscape.app」を右クリックして「パッケージの内容を表示」を選び、Contents→MacOSとフォルダをたどります。「MacOS」フォルダの中に「inkscape」というファイルがあるので、それをテキスト編集ができるエディタ(前回同様にこれもCotEditorがオススメ)で開き、321行目の

tail -n1 | sed 's/\./ /' | awk '{print $2}'`"

とあるところを

tail -n1 | awk '{print $2}' | awk -F. '{print $1}'`"

に書き換えます。

これでデフォルトで日本語で表示されるようになります。英語など他国語表記が必要な場合は設定から言語を変更すれば表示も変更されます。

修正の内容自体は前回の記事と全く同じなので、理屈を知りたい方はそちらを参照してください。

Mac版Inkscapeの正しい日本語化

はじめに

MacInkscapeを起動するとメニューが英語で表示され、設定から日本語を選ぶとアプリが異常終了するようになってしまいます。これは何年も前から指摘されているバグなのですが、未だに修正されていません。

いくつかのサイトで対応策が紹介されていますが、どういうわけかそのほとんどが強制的に日本語を表示させているだけという不完全な対応(よく見かけるのは「export LANG="ja_JP.UTF-8"」に書き換えたり挿入したりする方法)であり、これはInkscapeの本来あるべき動作とは違うものです。Inkscapeはもともと多言語に対応しているので、日本語のシステムではメニューがデフォルトで日本語で表示され、さらに設定で他の言語に切り替えることもできるのが本来意図されている動作です。

どうして未だに間違った方法だけが広まっているのか不思議なのですが、ちょっと検索してみた限りでは正常に動作させるための修正方法を記載しているサイトは未だにないようです。この記事ではバグをごまかすのではなく、本来の動作ができるように完全に修正する方法を紹介します。といっても実際の作業は簡単で、以下の通りに設定ファイルを一行書き換えるだけです。

修正方法

アプリ本体のInkscape.appを右クリックして、「パッケージの内容を表示」を選びます。そこからContents→Resources→binとフォルダをたどっていき、「bin」フォルダの中にある「inkscape」というファイルをテキストを編集できるアプリ(個人的にはCotEditorがオススメ)で開きます。

inkscape」を開いたら、その143行目の

tail -n1 | sed 's/\./ /' | awk '{print $2}'`"

というところを

tail -n1 | awk '{print $2}' | awk -F. '{print $1}'`"

に書き換えます。

これでバグが修正されてデフォルトで日本語表示されるようになり、設定で他の言語を選ぶとその言語で表示することも可能になります。例えば海外サイトのチュートリアルを参考にしたい場合には英語メニューに切り替えた方がわかりやすい時もあるでしょう。そういう時に簡単に表示を変更することができます。

解説

これで一件落着ですが、どうしてこの書き換えが必要になるのかを説明しておきます。使えればそれで良いという人は以下は読まなくても大丈夫です。

Inkscapeは表示言語の設定の際に「/usr/share/locale/locale.aliase」というファイルから各国語の設定用の文字列を抜き出す動作をしています。

「/usr/share/locale/locale.aliase」の一部を抜粋するとこんな感じのファイルです。

icelandic       is_IS.ISO-8859-1
italian it_IT.ISO-8859-1
japanese ja_JP.eucJP
japanese.euc ja_JP.eucJP
ja_JP ja_JP.eucJP
ja_JP.ujis ja_JP.eucJP
japanese.sjis ja_JP.SJIS
korean ko_KR.eucKR
korean.euc ko_KR.eucKR
ko_KR ko_KR.eucKR
lithuanian lt_LT.ISO-8859-13

Inkscapeはこの中から、日本語であれば「ja_」という文字列を検索してマッチした中から最後の行を取り出し、sedでピリオドをスペースに置換し、awkで二番目のフィールドを取り出して、その語尾に「.UTF-8」をくっつけて環境変数LANGとしてexportするという作業を行なっています。

他の言語ではこの動作で正しい文字列を取り出すことができます。例えば日本語の上にあるアイスランド語(icelandic)とイタリア語(italian)ではそれぞれ「is_IS」と「it_IT」を取り出せます。しかし日本語の場合は、最後の行の一番目のフィールドが「japanese.sjis」とフィールドの中にピリオドが入っているので、sedでピリオドをスペースに変換すると「sjis」が二番目のフィールドとなってしまい、本来取り出したい「ja_JP」ではなく「sjis」を取り出してしまいます。これがエラーの原因となっています。

日本語でも他の言語でも同じように狙った文字列を取り出すためには、まず最初に最後の行から2番目のフィールドを取り出しておいて、そこからピリオドの前の文字列を抜き出すという動作に書き換える必要があります。

「tail -n1 | awk '{print $2}' | awk -F. '{print $1}'」という記述はそのためのものです。