ホームページ>開発ツール>Xojo / Real Studio Trial and Error・CocoaのDeclareで書体を含めたフォント名をセットする・日本語対策編
Xojo / Real Studio Trial and Error
目次
CocoaのDeclareで書体を含めたフォント名をセットする・日本語対策編
はじめに
以下は、Xojo Cocoaビルドについての話題です。
フォントのコレクション名のうち、「"com.apple.AllFonts""com.apple.UserFonts""com.apple.Favorites""com.apple.Recents"」のローカライズ(日本語化)について、考えてみました。
なお検証には、Xojo 2014 Release 2を用いています。(Mac mini + OS X 10.9.5 Mavericks)
方針
調査を始めて、まず以下のサイトがヒットしました。
どうも「com.apple.UserFonts」はロケールから取得するものらしい、ということです。
参考サイト(1):Re: Leopard's Font Collection based on user's language
が、それ以外の項目については触れられていない(というか、"com.apple.AllFonts"で検索しても、絶望的な程ヒットしない)ため、更に角度を変えて調べた結果、フォントパネルは独自のリソースでローカライズしていることが分かりました。
(/System/Library/Frameworks/AppKit.framework/Resources/Japanese.lproj/FontManager.strings)
中身(bplist形式なので、(コピーを作成した上で)拡張子をplistに変えてやるとXcodeで開ける)を見てみると、「"All Fonts" = "すべてのフォント" "Favorites" = "よく使う項目" "Recently Used" = "最近使った項目"」といった項目があります。
(なるほど、「com.apple.UserFonts」に該当する項目はない。)
なので、以下の通り取得する方向でいくことにしました。
- 「com.apple.UserFonts」はロケールから取得
- 残りの項目はAppKit.frameworkのリソースから取得
Xojoでの実装
- 前回トピックのLocalizedCollectionNameメソッドを以下の通り書き換え
メソッド名: LocalizedCollectionName 引数: str As String 戻り値型: String select case str case "com.apple.AllFonts" str = CollectionNameFromFontpanel("All Fonts") if str = "" then return "すべてのフォント" else return str end if case "com.apple.UserFonts" str = LanguageFromLocale(0) // 現在の言語名をセット if str = "" then return "日本語" else return str end if case "com.apple.Favorites" str = CollectionNameFromFontpanel("Favorites") if str = "" then return "よく使う項目" else return str end if case "com.apple.Recents" str = CollectionNameFromFontpanel("Recently Used") if str = "" then return "最近使った項目" else return str end if else return str end select
- 以下をWindow1のメソッドに追加(注:ファイルから文字列を読み出すだけなので、Declareを使わずとも書けないことはないが、使った方が多分楽。)
メソッド名: CollectionNameFromFontpanel 引数: key As String 戻り値型: String // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr Dim pnt1 As Ptr Dim nB As Ptr = NSClassFromString("NSBundle") // クラスメソッドなので、まずNSBundleクラスを取得 Declare Function bundleWithIdentifier Lib "Cocoa" Selector "bundleWithIdentifier:" (receiver As Ptr, aName as CFStringRef) As Ptr // Return NSData* pnt1 = bundleWithIdentifier(nB,"com.apple.AppKit") Dim str1 As String Declare Function pathForResource lib "Cocoa" selector "pathForResource:ofType:inDirectory:forLocalization:" (receiver as Ptr, aRsrc as CFStringRef, aType as CFStringRef, aDir as CFStringRef, aLocal as CFStringRef) As CFStringRef // Return NSString* str1 = pathForResource(pnt1,"FontManager","strings",nil,LanguageFromLocale(1)) // どのlprojを参照するかをロケールから判定する Dim pnt2 As Ptr Dim nD As Ptr = NSClassFromString("NSData") // クラスメソッドなので、まずNSDataクラスを取得 Declare Function dataWithContentsOfFile Lib "Cocoa" Selector "dataWithContentsOfFile:" (receiver As Ptr, aPath as CFStringRef) As Ptr // Return NSData* pnt2 = dataWithContentsOfFile(nD,str1) if pnt2 = nil then 'msgBox "File not Found." return "" end if Dim pnt3 As Ptr Dim nP As Ptr = NSClassFromString("NSPropertyListSerialization") // クラスメソッドなので、まずNSPropertyListSerializationクラスを取得 Declare Function propertyListWithData Lib "Cocoa" Selector "propertyListWithData:options:format:error:" (receiver As Ptr, aData as Ptr, aOption as CFStringRef, aFormat as Ptr, aErr as Ptr) As Ptr // Return NSDictionary* pnt3 = propertyListWithData(nP,pnt2,"NSPropertyListImmutable",nil,nil) Dim str2 As String Declare Function objectForKey lib "Cocoa" selector "objectForKey:" (receiver as Ptr, aKey as CFStringRef) As CFStringRef // Return NSString* str2 = objectForKey(pnt3,key) return str2
- 以下をWindow1のメソッドに追加
メソッド名: LanguageFromLocale 引数: mode As Integer 戻り値型: String // mode=0:現在のロケールの言語名をそのロケールの表記で返す mode=1:現在のロケールの言語名を英語表記で返す // 文字列を指定してクラスオブジェクトを取得する。最初に一回宣言しておけばよい。 Declare Function NSClassFromString Lib "Cocoa" (aClassName As CFStringRef) As Ptr Dim pnt1 As Ptr Dim nL As Ptr = NSClassFromString("NSLocale") // クラスメソッドなので、まずNSLocaleクラスを取得 Declare Function preferredLanguages Lib "Cocoa" Selector "preferredLanguages" (receiver As Ptr) As Ptr // Return NSArray* pnt1 = preferredLanguages(nL) Dim str1 As String Declare Function ObjectAtIndex lib "Cocoa" selector "objectAtIndex:" (receiver as Ptr, idx as Integer) As CFStringRef // Return NSString* str1 = objectAtIndex(pnt1,0) Dim str2, str3 As String if mode = 0 then str2 = str1 str3 = "kCFLocaleLanguageCodeKey" // = NSLocaleLanguageCode else str2 = "en_US" str3 = "kCFLocaleIdentifierKey" // = NSLocaleIdentifier end if Dim pnt2 As Ptr Declare Function alloc Lib "Cocoa" Selector "alloc" (receiver As Ptr) As Ptr // Return NSLocale* pnt2 = alloc(nL) Declare Function initWithLocaleIdentifier lib "Cocoa" selector "initWithLocaleIdentifier:" (receiver as Ptr, identifier as CFStringRef) As Ptr // Return NSLocale* pnt2 = initWithLocaleIdentifier(pnt2,str2) Dim str4 As String Declare Function displayNameForKey lib "Cocoa" selector "displayNameForKey:value:" (receiver as Ptr, aKey as CFStringRef, aValue as CFStringRef) As CFStringRef // Return NSString* str4 = displayNameForKey(pnt2,str3,str1) Declare Sub release Lib "Cocoa" Selector "release" (receiver As Ptr) release(pnt2) return str4
おわりに
当初は、NSFontのDisplayNameのようなローカライズのためのAPIが存在するのかと思っていたのですが、そういったものは見つけられませんでした。
とりあえず、多言語への対応は出来るようにはなりましたが、対症療法的であるという点では大差ないとも言えます。それなら、(日本語対応だけでよければ)最初のシンプルな方式でもいいのかなぁ、という気がしないでもありません。
いずれにせよ、機会があればもう少し調べてみたいとは思います。
お世話になったサイト
貴重な情報をご提供頂いている皆様に、お礼申し上げます。(以下、順不同)
参考サイト(1):Re: Leopard's Font Collection based on user's language
更新履歴
2014.11.02 新規作成
[Home] [MacSoft] [Donation] [History] [Privacy Policy] [Affiliate Policy]