ホームページ開発ツール>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」に該当する項目はない。)

 なので、以下の通り取得する方向でいくことにしました。
  1. 「com.apple.UserFonts」はロケールから取得
  2. 残りの項目はAppKit.frameworkのリソースから取得

 Xojoでの実装
  1. 前回トピックの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
    
  2. 以下を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
    
  3. 以下を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]