iOS 程式碼,xib,storyboard全自動國際化

活出騎士風範發表於2019-04-28

iOS國際化完全指南

看完這篇文章你可以解決國際化的絕大部分問題,並且本人重寫了前人的指令碼;可以實現程式碼,xib,storyboard的自動國際化。自動新增,刪除文字,專案中的所有內容,不需要再手動維護,新專案簡單國際化,老專案輕鬆國際化。專案地址

我試圖用XCodeEditor來實現一個mac應用,讓我們的國際化完全不用在專案中操作,單個語言檔案沒問題,但是因為多個國際化語言的檔案引用關係始終不能正確設定,所以沒有成功,如果有mac開發的大佬或者對project.pbxproj 這個檔案工程核心檔案結構有了解的同學;可以聯絡我一起實現這個專案

如果有不清楚的地方,歡迎聯絡我補充。

國際化的基本姿勢

一個專案要國際化,首先要在project 的 build settings 中新增需要的語言:

iOS 程式碼,xib,storyboard全自動國際化
這裡是選擇整個專案要支援的語言,點+號選擇你需要的就好了。

Xib和stroyboard國際化

如果是新專案,我強烈建議你勁量多的使用 xib 和 stroyboard 來構建專案,因為如果你遇到了要支援阿拉伯地區的語言,他們的習慣是從右到左的,也就是系統的RTL(rignt to left)。整個介面都需要映象翻轉,那時候系統提供的方法只支援xib 和stroyboard 。你如果用的純程式碼寫死,那麼會麻煩很多。

xib和SB要國際化,其實很簡單;只需要在相應的檔案中選擇。

iOS 程式碼,xib,storyboard全自動國際化
點選Localization,選擇相應的語言,系統就會自動修改專案的實際檔案結構:

iOS 程式碼,xib,storyboard全自動國際化

會出現以下的專案樣子:

iOS 程式碼,xib,storyboard全自動國際化

這裡要注意下,系統自動生成的檔案中會出現已經在xib或者SB 中使用的字元;但是隻會生成在你點選Localization那一個時刻已經有了的字元,如果你持續開發。又新增刪除了控制元件,那麼不會自動生成。只有取消該部分國際化,然後再把這種語言打鉤,選擇上之後才會生成新的檔案,並且會覆蓋掉你之前已經寫好的國際化檔案。本指令碼已經解決這個問題,不再需要手動維護。解決原理是:

ibtool --generate-stringsfile MyNib.strings MyNib.nib
複製程式碼

ibtool這個小工具,系統自帶。可以自動把xib或者sb 生成一個.stings檔案。

程式碼國際化

程式碼部分的國際化,只有一個辦法就是使用系統的國際化巨集:

NSLocalizedString("這裡是需要國際化的字元",comment: "這裡是註釋")

#define NSLocalizedString(key, comment) \
	    [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]

...
/* Method for retrieving localized strings. */
- (NSString *)localizedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1);


#define NSLocalizedStringFromTable(key, tbl, comment) \
	    [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
	    [bundle localizedStringForKey:(key) value:@"" table:(tbl)]

複製程式碼

NSLocalizedStringFromTable(key, tbl, comment) 這種方式比較少用,因為這個tbl就是tbl.strings的名字,在程式碼部分使用了巨集之後。你還需要生成資原始檔.strings:

iOS 程式碼,xib,storyboard全自動國際化

你生成這個檔案的時候,輸入的檔名如果是 Localizable 那麼你就使用第一個巨集,如果你輸入了別的名字,那麼你就應該使用 NSLocalizedStringFromTable(key, tbl, comment)。其中的tbl就是你輸入的檔名稱。 提示:你可以在每一個.m檔案需要國際化的字元裡這樣寫:

button.titleLabel.text = NSLocalizedString(@"可能性測試", “xxxxx.m”);
複製程式碼

之後在生成的國際化語言中,你會發現這個國際化的註釋會生成。當需要翻譯的文字太多時,方便查詢是哪個頁面的字元。

這裡有一個小技巧,不管你是新老專案;你都可以使用正則匹配來查詢專案中所有沒有國際化的字元:

iOS 程式碼,xib,storyboard全自動國際化
如圖:修改專案搜尋為替換,選擇正則匹配,然後新增

@"[^"]*[\u4E00-\u9FA5]+[^"\n]*?"
NSLocalizedString($0, nil)
複製程式碼

這樣就可以快速查詢專案中使用了@“中文”這樣格式的字元,替換為系統的巨集。一鍵替換全部,然後使用我的指令碼就可以全自動管理程式碼部分的國際化字元。

iOS 程式碼,xib,storyboard全自動國際化

我的python指令碼只支援第一種方式的巨集,只要你實現了這個巨集。那麼我的指令碼就支援全自動匯入,自動新增,刪除。建議在comment部分寫上檔名,如果你有了上千個需要翻譯的文字,那麼檔案很大的時候。方便你定位具體的字元。 我的實現原理是藉助了:

genstrings -o .m en.lproj
複製程式碼

genstrings 系統自帶,可以把一個檔案使用了巨集的字元,生成對應的檔案到 en.lproj 目錄中去。

我的指令碼已經處理了細節問題,不再需要手動維護。國際化只需要填空就好了。

圖片,影視訊國際化

這部分國際化很簡單:

  1. 程式碼部分 和在程式碼的文字部分一樣,只要取好key,然後在不同的語言中寫好相應的名字就可以。
  2. xib和SB部分 在專案中專門建立一個檔案目錄放置圖片。然後和xib,sb一樣。在右側檔案資源監控器中點Localization,然後在專案實際目錄中修改就好了。

圖片,視訊,音訊沒有區別。

系統許可權國際化---InfoPlist

系統許可權部分生成多語言檔案部分和其他的沒有區別,你只需要在生成的檔案中:

NSLocationAlwaysAndWhenInUseUsageDescription = “使用定位的描述”
複製程式碼

查詢對應的許可權名稱,只需要選擇showRaw就會出現:

iOS 程式碼,xib,storyboard全自動國際化

系統資源國際化

比如進入調取相簿頁面,通訊錄頁面,還有複製貼上的系統提示等,這部分是跟著 CFBundleDevelopmentRegion 這個許可權,系統開發語言走的。這個是系統預設語言。當什麼都沒有的時候,它就會是英文。如果你修改了。系統資源頁面會根據你的修改生效。這裡很有意思,有兩種選擇方式:一種是選擇國家,一種是選擇具體的語言範圍。這是兩個概念!!如果你要修改預設開發語言,選擇國際。如果你要修改系統資源頁面,你要選擇語言範圍。比如:zh_CN

伺服器端國際化

這部分沒有什麼特別的好辦法,純粹是兩端協商實現。一般就兩種:

1.後端完全實現相應的語言提示返回給前端。 2.後端不管語言,返回一套自己規定的提示語言編號集合。前端根據這個編號提示相應的內容。

應用內語言選擇

其實在iOS中國際化,就是切換不同的語言資源,顯示不同的檔案資訊。然後系統用了一個Localizable的系統巨集,來維護key/value的關係。系統中每一種語言對應一種bundle資原始檔。當你在切換不同語言的時候,就去找對應的語言包中的資源。所以我們可以利用runtime動態載入不同的bundle來實現語言的切換。在demo中有具體的使用例子。

這個部分一般只有兩種實現方式:

1.微信的方式:切換bundle。

2.微博的方式:傳送語言切換通知。

這部分討論的文章已經非常多,並且很成熟了;我就不過多贅述。

疑難問題解決

1.阿拉伯地區支援RTL 經過實踐,xib,sb系統提供了很好的方法。只需要用masony來修改程式碼部分寫死的佈局,就好了。

2.textView系統不支援 給textview寫一個分類,不難。

3.AttributedString富文字國際化 這一部分有一點定製化的味道,還是隻有自己寫分類。

指令碼使用疑問解答:

  • 如果沒有生效?

    • 請檢查你是否使用了系統的國際化巨集,程式碼部分,只會生成使用了國際化巨集的對應字元。 如:
    button.titleLabel.text = NSLocalizedString(@"可能性測試", nil);
    複製程式碼
    • 請檢查你是否有python3環境,mac系統自帶python2.7環境;我使用的是python3.7。
    • 不要使用壓縮包,直接clone專案,然後取專案中的ZPPScript檔案。 太晚了,之後慢慢更新。

相關文章