要讓 App 邁向國際,多語系是一定要做的。透過 angular-translate 可以輕鬆讓 App 做到 i18n 的服務。內容搞定了,那 App 名稱呢,也能依據語系而且不同的名稱嗎?答案是肯定的。
在官方文件 裡面就有提到支援多語系的做法,處理方式很簡單,只要在特定的資料夾下建立對應的檔案就 OK了。
以下是以 Cordova 專案為例。
假設我們有兩種語系,分別要有不同的 App 名稱
步驟一 首先要到專案目錄下的 platforms 資料夾地下找到 res 資料夾,這是個存放 Android 資源的地方,我們要建立不同語系的 App 名稱設定檔就是要在這個資料夾底下。
步驟二 在 res 資料夾底下,依照你需要的語系建立不同名稱的資料夾
專案預設就有 values,我們用來存放預設是英文的設定檔,而 values-zh 用來存放中文的設定檔。
這裡資料夾的命名是有規則的,新增對應語系的資料夾必須是 values- 加上二字元的 ISO 639-1 codes 語系代碼,常用的如下:
Chinese (zh)
English (en)
French (fr)
Japanese (ja)
Korean (ko)
詳細表格請參考:Wiki - List of ISO 639-1 codes
其中有一點比較尷尬,就是這個語系代碼中,中文是沒有分簡、繁體的,所以這部份就自行斟酌了。
步驟三 在對應語系的資料夾中,各別新增一個 string.xml 的檔案並增加 XML 程式碼,範例如下:
1 2 3 4 5 6 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <resources > <string name ="app_name" > 哈囉世界</string > <string name ="launcher_name" > @string/app_name</string > <string name ="activity_name" > @string/launcher_name</string > </resources >
很明顯的可以找到 name="app_name" 的屬性,把這個屬性值修改成你要的名稱,例如:哈囉世界。
最後 對應的語系資料建立完成之後,在 Android 執行的時候,會去針對裝置的語系設定,去讀取 App 特定位置的設定檔,這樣就達成依據語系的不同,顯示不一樣的 App 名稱。
自動化 如果每次重建專案,都要手動去資加這些資料夾和檔案了話,其實也滿累人的。
因此我寫了段程式,利用 Crodova Hook 在 after_compile 階段,自動去產生所需要的檔案,這樣之後就會在編譯完成後,自動加入寫死的設定,有興趣的可以參考下面的完整程式碼 。
這段程式碼是 Android 專用的,而且希望在最後在做 release 的時後才執行,所以執行指令要下 cordova build android --release 才能觸發這段程序。
samplecode poychang/addAndroidResource.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 #!/usr/bin/env node var fs = require ('fs' );var xml2js = require ('xml2js' );var cliCommand = process.env .CORDOVA_CMDLINE ;var isRelease = (cliCommand.indexOf ('--release' ) > -1 );var isBuildAndroid = (cliCommand.indexOf ('build' ) > -1 ) && (cliCommand.indexOf ('android' ) > -1 );if (!isRelease) { return ; } run ();function run ( ) { if (isBuildAndroid) addAndroidResource (); } function addAndroidResource ( ) { var files = [{ folder : 'platforms/android/res/values-zh/' , file : 'string.xml' , data : ` <?xml version='1.0' encoding='utf-8'?> <resources> <string name="app_name">App Name</string> <string name="launcher_name">@string/app_name</string> <string name="activity_name">@string/launcher_name</string> </resources> ` }]; files.forEach (function (obj ) { var path = obj.folder + obj.file ; console .log (path); if (checkDirectory (obj.folder )) { xml2js.parseString (obj.data , function (err, result ) { var builder = new xml2js.Builder (); var xml = builder.buildObject (result); fs.writeFile (path, xml, function (err ) { if (err) throw err; console .log ('Save ' + path); }); }); } else { console .log ('Faild to check directory.' ); } }, this ); } function checkDirectory (path ) { if (isDirectoryExists (path)) return true ; try { fs.mkdirSync (path); return true ; } catch (err) { return false ; } } function isDirectoryExists (path ) { try { return fs.statSync (path).isDirectory (); } catch (err) { return false ; } }
參考資料: