多語系之App開發









可以使用的方法相當多,例如直接套用 iDevice設定,根據使用者慣用語言來自動調整語系。這邊使用的方法,則是讓使用者可以自己作主,進到App 後,可以自行決定使用何種語系;這邊提供一個簡單的範例,但此方法也可以套用在大型專案上。




如上,進入App 後,使用者馬上會看到挑選語系的Menu,挑選喜歡的語系後,可以看到不同語言的歡迎畫面。






為了實做此專案,我們需要新增MenuScene 以及 LANG_TEXT 的.m 還有.h檔。


MenuScene 拿來負責做場景的轉換,而LANG_TEXT 負責做語系的設定。下面是 MenuScene.m 檔的程式碼內容:
#import "MenuScene.h"
#import "HelloWorldLayer.h"
#import "LANG_TEXT.h"


@implementation MenuScene

+(id)scene
{
    //新增layer
    CCScene *scene = [CCScene node];
    MenuScene *layer = [MenuScene node];
    
    [scene addChild:layer];
    
    return  scene;
}

-(id) init
{
    if((self = [super init]))
    {
        //設定app開啓後的顯示menu
        [CCMenuItemFont setFontName:@"Helvetica"];
        
        CCMenuItem *menuItem1 = [CCMenuItemFont itemFromString:@"Chinese(中文)" target:self selector:@selector(changeTC)];
        CCMenuItem *menuItem2 = [CCMenuItemFont itemFromString:@"English(英文)" target:self selector:@selector(changeEN)];
        
        CCMenu *menu = [CCMenu menuWithItems:menuItem1, menuItem2,nil];
        
        [menu alignItemsVertically];
        
        [menu setPosition:ccp(240, 160)];
        
        [self addChild:menu];
        
    }
    
    return self;
}

-(void) changeTC
{
    [LANG_TEXT setCurrentLang:TC_CHINESE];
    [[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
}

-(void) changeEN
{
    [LANG_TEXT setCurrentLang:ENGLISH];
    [[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]];
}

-(void)dealloc
{
    [super dealloc];
}

@end


接著是 LANG_TEXT.h 的程式碼內容:
#import <Foundation/Foundation.h>

typedef enum
{
    TC_CHINESE = 0,
    ENGLISH    = 1,
}LANG_DEFINE;

@interface LANG_TEXT : NSObject
{
    NSDictionary* NOW_DICTINARY;     
    LANG_DEFINE   currentLANG;      
}

+(NSString*)        TEXT:        (NSString*)   key;
+(void)             setCurrentLang: (LANG_DEFINE) lang; 
-(void)             setLang: (LANG_DEFINE) lang; 

@property (nonatomic,retain) NSDictionary* NOW_DICTINARY;
@property (nonatomic,assign) LANG_DEFINE   currentLANG; 

@end


LANG_TEXT.m 的程式碼內容:
#import "LANG_TEXT.h"

@implementation LANG_TEXT

@synthesize NOW_DICTINARY,currentLANG;

//   取得操作唯一實體                                                           
+(LANG_TEXT*)  shared_LANGTEXT
{
    static LANG_TEXT*  langText = nil;
    
    if ( langText == nil)
    {
        langText = [[LANG_TEXT alloc] init];
    }
    
    return  langText;
}

//   設定當前使用語言                          
+(void) setCurrentLang: (LANG_DEFINE) lang
{
    [[LANG_TEXT shared_LANGTEXT] setLang:lang];
}


//   根據設定取得.string對應字串   
+(NSString*)  TEXT: (NSString*) key
{
    return [[[LANG_TEXT shared_LANGTEXT] NOW_DICTINARY] objectForKey:key];
}


// 設定使用語言    
- (void)  setLang: (LANG_DEFINE) lang
{
    
    [self.NOW_DICTINARY release];   
    
    switch (lang)
    {
        case TC_CHINESE:
        {
            self.NOW_DICTINARY = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:@"zh-Hant"]];
            break;
        }   
          
        case ENGLISH:
        {
            self.NOW_DICTINARY = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings"  inDirectory:nil forLocalization:@"English"]];
            
            break;
        }
    }
}

//物件初始化                              
-(id)  init
{
    self = [super init];
    return self;
}

//資源釋放                                                                                                         
-(void) dealloc
{
    [NOW_DICTINARY release];
    [super dealloc];
}

@end


HelloWorldLayer.m 檔,做一些適當的修改,
首先匯入 LANG_TEXT
#import "LANG_TEXT.h"


接著改 init 內部的程式碼
-(id) init
{
    // always call "super" init
    // Apple recommends to re-assign "self" with the "super" return value
    if( (self=[super init])) {
        
        // create and initialize a Label
        CCLabelTTF *label = [CCLabelTTF labelWithString:[LANG_TEXT TEXT:@"Text_Test"] fontName:@"Marker Felt" fontSize:64];
        // ask director the the window size
        CGSize size = [[CCDirector sharedDirector] winSize];
    
        // position the label on the center of the screen
        label.position =  ccp( size.width /2 , size.height/2 );
        
        // add the label as a child to this Layer
        [self addChild: label];
    }
    return self;
}


最後一個要修改的程式碼在 AppDelegate.m ,我們希望程式一開始的地方,是在我們所建立的語言選單畫面,
所以先匯入 MenuScene
#import "MenuScene.h"


然後到 applicationDidFinishLaunching 中最下面,改成如下的程式碼:
// Run the intro Scene
[[CCDirector sharedDirector] runWithScene: [MenuScene scene]];


程式碼的部份到此完成,但還需要設定語系轉換的『字典』。也就是說,同樣的東西,根據不同的語言會有不同的呈現風貌,我們需要做設定。


在 Xcode 左邊的欄位中找到 Resource,之後右鍵,new file,在iOS 的 Resource 選項中找到 String File。


新增出來的 String 通常是『英文字典』,開始編寫自己的字典吧~
使用類似以下的格式:
"Text_Test"        =   "Hello";
等號左邊欄位可說是代表程式碼中會用到的代號,而等號右邊就是他實際的意義。也就是,我們在程式碼中設定將字串 "Text_Test" 呈現於畫面中,但根據查字典的結果,實際呈現畫面的結果將會是 "Hello"!

將英文字典編好後,看到 Xcode 左邊的 Resource 底下,會多出 Localizable.string 的檔案。


但這只是英文的字典,我們還需要一個中文的。點選 Localizable.string 檔案,然後從 Xcode 的View、Utilities 中,找到 File template,在裡面可以找到 Location 欄位,按下欄位底下的 "+",選擇新增 Chinese 語言。


回到 Resource 底下,可以看見多出 Localizable.string(Chinese) 的檔案,這就是中文的字典,
最後,整個專案的結構應該是會像這樣:




但這本字典是從英文複製過來的,所以需要將它改成中文,如同上面所說的規則,改成這樣:
"Text_Test"        =   "哈囉";

終於大功告成!
以後字典若要擴充,也只要在下面增加就可以了,至於增加其他語言也可以用相同的方法作到!