iT邦幫忙

2021 iThome 鐵人賽

DAY 17
1
Mobile Development

轉職App開發打怪雜記系列 第 17

本地化APP(變更APP語言)

  • 分享至 

  • xImage
  •  

緣由:

若客戶端使用者不只單一國家,就會需要有變更app語言的功能,
之前查了一些資訊都是需要退出後才能變更語言包,
然後我有找到網路神人Roman Sorochak寫的範例,不用退出app就能變更語言包,覺得超棒的

實作:

前置作業:

將所有元件先與viewcontroller連結好,且將所有元件的String都設定好
續前篇的佈局,加上一個變更語言的按鈕,因為想區別一下與Storyboard上是不同語言所以會以英文、日文、韓文作為變更語言的示範

示範:

@IBOutlet weak var infoTextView: UITextView!
 override func viewDidLoad() {
      super.viewDidLoad()
      infoTextView.text = "Please enter your basic information"
  }

本地化Localizable檔案

創建Localizable.strings的新檔案
https://ithelp.ithome.com.tw/upload/images/20210917/20130757w2FVp9Fdnj.png
https://ithelp.ithome.com.tw/upload/images/20210917/20130757PoyaIyGkft.png

點擊Localizable按鈕
https://ithelp.ithome.com.tw/upload/images/20210917/20130757j3Fr34gTow.png

接著到Project Navigator中的Project下的info
可以在紅框處添加新的語言包,如下圖
https://ithelp.ithome.com.tw/upload/images/20210917/20130757D54qhQpcCn.png
https://ithelp.ithome.com.tw/upload/images/20210917/201307578gBBBH3IDx.png
https://ithelp.ithome.com.tw/upload/images/20210917/20130757ts0rWTz6f4.png
各種語言都可以以此方式創建語言包

Extension String 與 Bundle

import UIKit

extension String {
    //在String後添加.localized即可以轉用設定之本地化字串
    var localized: String {
        return Bundle.localizedBundle.localizedString(forKey: self, value: nil, table: nil)
    }
    
    //在圖片檔名後添加.localizedImage即可以使用該語言包內相應檔名的圖片
    var localizedImage: UIImage? {
        return localizedImage()
            ?? localizedImage(type: ".png")
            ?? localizedImage(type: ".jpg")
            ?? localizedImage(type: ".jpeg")
            ?? UIImage(named: self)
    }
    
    private func localizedImage(type: String = "") -> UIImage? {
        guard let imagePath = Bundle.localizedBundle.path(forResource: self, ofType: type) else {
            return nil
        }
        return UIImage(contentsOfFile: imagePath)
    }
}

extension Bundle {
    static var localizedBundle: Bundle {
        let languageCode = Language.language.rawValue
        guard let path = Bundle.main.path(forResource: languageCode, ofType: "lproj") else {
            return Bundle.main
        }
        return Bundle(path: path)!
    }
}

列舉要更換的語言包

private let appleLanguagesKey = "AppleLanguages"

enum Language: String {
    
    case english = "en"
    case Japanese = "ja"
    case Korean = "ko"       
    
    static var language: Language {
        get {
            if let languageCode = UserDefaults.standard.string(forKey: appleLanguagesKey),
                let language = Language(rawValue: languageCode) {
                return language
            } else {
		//獲取偏好語言第一順位的字段
                let preferredLanguage = NSLocale.preferredLanguages[0] as String
                let index = preferredLanguage.index(
                    preferredLanguage.startIndex,
                    offsetBy: 2
                )
		//本地化語言包中若有與偏好語言第一順位相符的語言包,則顯示該語言包,若無相符,一律顯示英文
                guard let localization = Language(
                    rawValue: preferredLanguage.substring(to: index)
                    ) else {
                        return Language.english
                }
                
                return localization
            }
        }
        set {
            guard language != newValue else {
                return
            }
	    //變更app內中的語言
            UserDefaults.standard.set([newValue.rawValue], forKey: appleLanguagesKey)
	    //要執行synchronize()才會真的寫入資料中
            UserDefaults.standard.synchronize()
            UIApplication.shared.windows[0].rootViewController = UIStoryboard(
                name: "Main",
                bundle: nil
                ).instantiateInitialViewController()
        }
    }
}

Viewcontroller中的本地化範例:

將前置作業中設定好的字串後面加上.localized

示範:
infoTextView.text = "Please enter your basic information".localized

然後將變更語言的按鈕”Touch up inside”連結至viewcontroller中,使用彈窗功能將各語言選項放進彈窗中,
點擊該語言按鈕後,即可以更換語言包

示範:

@IBAction func changeLanguage(_ sender: Any) {
        let alert = UIAlertController(
            title: "alert_change_language_title".localized,
            message: nil,
            preferredStyle: .actionSheet
        )
        
        func addActionLanguage(language: Language) {
            alert.addAction(
                UIAlertAction(
                    title: language.rawValue.localized,
                    style: UIAlertAction.Style.default,
                    handler: { _ in
                        Language.language = language
                })
            )
        }
        addActionLanguage(language: Language.english)
        addActionLanguage(language: Language.Japanese)
        addActionLanguage(language: Language.Korean)
        
        alert.addAction(
            UIAlertAction(
                title: "alert_cancel".localized,
                style: UIAlertAction.Style.cancel,
                handler: nil
            )
        )
        present(alert, animated: true, completion: nil)
    }

Localizable.strings的本地化字串設定

將要本地化的字串列好(XXXXX.localized中的XXXXX),然後更新切換成該語言包時要顯示的字串

示範:
英文
"Please enter your basic information" = "Please enter your basic information";
日文
"Please enter your basic information" = "基本情報を入力してください";
韓文
"Please enter your basic information" = "기본정보를 입력해주세요";

以上變更語言的功能完成!


上一篇
隱藏&顯示畫面中間的某區塊
下一篇
分版本Target
系列文
轉職App開發打怪雜記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言