きりかノート 3冊め

おあそびプログラミング

nibtool の辞書ファイルを ibtool 用に変換する

どうやら nibtool がなくなって ibtool になったようだ。man ibtool(1) を見た感じでは、オプションの書きかたが違うだけで、機能的にはほぼ同じもののようだ。あんまり使ってなかったけれど、ローカライズにちょっと使っていたりした。その辞書ファイルの形式が変わっているのだ。

たとえば nibtool では

 /* NSMenuItem : <title:Copy> (oid:290) */
"Copy" = "コピー";

となっていたものが、

 /* Class = "NSMenuItem"; title = "Copy"; ObjectID = "290"; */
"290.title" = "Copy";

となっていて、表記から ObjectID に対象の特定方法が変わったようだ。「まあ、もとのファイルの oid もあるし、変換すりゃいいか」とやってみたものの、一部の項目でエラーとなる。

  • テーブルビューの列ヘッダは title でなく、headerCell.title
  • NSTextField は NSTextFieldCell に

など、単純には変換できないものがある。特に後者は ObjectID が変わるし、nibtool のときには存在しないので追っかけようがない。

仕方ないので、一度 ibtool で生成した辞書を元に、表記基準で一致するものを差し替えていくようにしてみた。Ruby で UTF16 を BOM 付きで出力する方法がわからなかったので無理やり。手元では使えたけれど、あんま複雑な nib がないので、ヨソでも大丈夫かはわからん。つーか、標準のツールがあるような気がしてしかたがない…

コピペするのがめんどうなひとはこちらから nibstrmerge.rb.txt

(2007/10/31 追記:少し進化 nib2ibstr.rb

 #!/usr/bin/ruby
#
# Usage:
# 1. generate ibtool string
# ibtool --generate-stringsfile ibtool-orig.strings MyNibFile.nib
# 2. merge nibtool strings into ibtool strings
# nibstrmerge.rb nibtool.strings ibtool-orig.strings > ibtool-new.strings
#
# $Id: nibstrmerge.rb 601 2007-10-29 13:38:56Z kimuraw $
require 'iconv'
FILE_ENC = 'UTF-16'
FILE_ENC_O = 'UTF-16LE'
WORK_ENC = 'UTF-8'
$KCODE = 'u' # utf8

# READ NIB STRINGS
NibItem = Struct.new(:klass, :attr, :key, :oid, :key2, :string)
class NibItem
NIBLINE_1 = '/\* (\S+) (\(.+\) )?: <(\S+):(.+)> \(oid:(\d+)\) \*/' + "\n"
NIBLINE_2 = '"(.+)" = "(.*)";' + "\n"
class <<self
def read(path)
pattern = Regexp.new(NIBLINE_1 + NIBLINE_2)
input = Iconv.conv(WORK_ENC, FILE_ENC, File.open(path).read)
dict = {}
while input.slice!(pattern) do
item = NibItem.new($1, $3, $4, $5, $6, $7)
dict[item.key2] = item
end
dict
end
end
end

# READ TEMPLATE IB STRINGS and REPLACE LOCALIZED STRING
class IbItem
IBLINE_1 = '/\* Class = "(\S+)"; (\S+) = "(.*)"; ObjectID = "(\d+)"; \*/' + "\n"
IBLINE_2 = '"(\d+)\.(\S+)" = "(.*)";' + "\n"
class <<self
def convert(path, dict, out=$stdout)
input = Iconv.conv(WORK_ENC, FILE_ENC, File.open(path).read)
pattern = Regexp.new(IBLINE_1 + IBLINE_2)
result = ""
while input.slice!(pattern) do
str = if item = dict[$3]
then item.string
else $3
end
result <<
%Q!/* Class = "#{$1}"; #{$2} = "#{$3}"; ObjectID = "#{$4}"; */\n! <<
%Q!"#{$5}.#{$6}" = "#{str}";\n! <<
"\n"
end
out <<
"\xff\xfe" <<
"\x0a\00" <<
Iconv.conv(FILE_ENC_O, WORK_ENC, result)
end
end
end

dict = NibItem.read(ARGV[0])
IbItem.convert(ARGV[1], dict)