Localization is a process of translating the application’s text, resources and user interface into multiple languages. For localization, you need to first internationalize your application. Internationalization is the process of making your app able to adopt different languages, regions, cultures and user interface. In this blog, we will translate our app into the Hebrew language. Hebrew is written from right to left using Hebrew Alphabets. So we just have not to change the text but also have to change direction images and app’s navigation from right to left. Our app will be looked like this:
Let’s get started
First, create a single view application.
Click on the project folder in the project navigator and select project section. Click on the + button under the localizations section.
You will see the following list of applications. Select the language you want to add into your app.
After selecting the language, following popup will be appeared.
In this popup, there will be a list of all storyboards shown with checked. Select the storyboards which you want to localize. Click on the finish button. If we localize with the storyboard, then language changes only reflected when we quit the application. In our demo, changes will reflect within the application’s open state. For that, we will localize our app programmatically.
Go to File > New > File. Then select Strings File from the list.
Give the file name “Localizable.strings”. Click on this file. Then click on Localize button. You will see the below popup. Select your language and then click on Localize button.
You will see English and Hebrew under the localization section. Select Hebrew language also.
Now you can see following file structure.
Now open Main.storyboard. Embed View controller in Navigation controller. Design title, tableView and next button as below.
We will save our selected language in UserDefaults with “Language” key.
Helper Class:
Create one Helper class for global methods. Add the following function for getting localize string.
class AppHelper: NSObject { static func getLocalizeString(str:String) -> String { let string = Bundle.main.path(forResource: UserDefaults.standard.string(forKey: "Language"), ofType: "lproj") let myBundle = Bundle(path: string!) return (myBundle?.localizedString(forKey: str, value: "", table: nil))! } }
This function returns localize string of selected language. If English is selected then app’s navigation should be left to right direction and if Hebrew is selected then app’s navigation should be right to left. This will be done by the following code.
UIView.appearance().semanticContentAttribute = .forceLeftToRight UIView.appearance().semanticContentAttribute = .forceRightToLeft
Write the below code didFinishLaunchingWithOptions method of AppDelegate.
if UserDefaults.standard.object(forKey: "Language") != nil && UserDefaults.standard.object(forKey: "Language") as! String == "he" { UserDefaults.standard.set("he", forKey: "Language") UIView.appearance().semanticContentAttribute = .forceRightToLeft } else { UserDefaults.standard.set("en", forKey: "Language") UIView.appearance().semanticContentAttribute = .forceLeftToRight } return true
For the first time of application install, we haven’t set any language in user defaults. So UserDefaults.standard.object(forKey: “Language”) will return nil. Therefore we set the English language for the first time install.
Write the localize string in Localizable.strings (English) and Localizable.strings (Hebrew) file.
Localizable String:
Localizable.strings (English) file :
“Choose Language” = “Choose Language”;
“English” = “English”;
“Hebrew” = “Hebrew”;
“Next” = “Next”;
“Country List” = “Country List”;
“India” = “India”;
“Australia” = “Australia”;
“Mexico” = “Mexico”;
“Kenya” = “Kenya”;
“China” = “China”;
“Bhutan” = “Bhutan”;
“Canada” = “Canada”;
“Japan” = “Japan”;
“Qatar” = “Qatar”;
“Israel” = “Israel”;”Country Description Here…” = “Country Description Here…”;
Localizable.strings (Hebrew) file:
“Choose Language” = “בחר שפה”;
“English” = “אנגלית”;
“Hebrew” = “עברית”;
“Next” = “הבא”;
“Country List” = “רשימת מדינות”;
“India” = “הודו”;
“Australia” = “אוסטרליה”;
“Mexico” = “מקסיקו”;
“Kenya” = “קניה”;
“China” = “סין”;
“Bhutan” = “בהוטאן”;
“Canada” = “קנדה”;
“Japan” = “יפן”;
“Qatar” = “קטאר”;
“Israel” = “ישראל”;
“Country Description Here…” = “תיאור המדינה כאן …”;
Here, I have written all the strings and its localizable that will use in our project.
Storyboards
Add two storyboard file named CountryListSB.storyboard and CountryDetailSB.storyboard in the project.
Add two ViewController file CountryListViewController.swift and CountryDetailViewController.swift file in the project.
ViewController.swift
Create following variables for storing language dictionary and selected language.
Initialize dictionary in viewDidLoad method.
Write the viewWillAppear method as follow :
var dictLanguage = [String:String]() var selectedLanguage: String = ""
dictLanguage = ["en" : "English", "he":"עברית"]
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.tblLanguage.reloadData() selectedLanguage = dictLanguage[UserDefaults.standard.object(forKey: "Language") as! String]! lblTitle.text = AppHelper.getLocalizeString(str: "Choose Language") btnNext.setTitle(AppHelper.getLocalizeString(str: "Next"), for: .normal) }
Here is table view delegate and data source method:
extension ViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dictLanguage.keys.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let lblLanName = cell.viewWithTag(101) as! UILabel lblLanName.text = Array(dictLanguage)[indexPath.row].value let imgSelect = cell.viewWithTag(102) as! UIImageView if Array(dictLanguage)[indexPath.row].value == selectedLanguage { imgSelect.isHidden = false } else { imgSelect.isHidden = true } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tblLanguage.deselectRow(at: indexPath, animated: false) let cell = tblLanguage.cellForRow(at: indexPath) selectedLanguage = (cell?.viewWithTag(101) as! UILabel).text! tblLanguage.reloadData() } }
Button Click Method:
Write Next button click method as below:
@IBAction func onClickBtnNext(_ sender: Any) { if selectedLanguage != dictLanguage[UserDefaults.standard.object(forKey: "Language") as! String] { if selectedLanguage == "English" { UserDefaults.standard.set("en", forKey: "Language") UIView.appearance().semanticContentAttribute = .forceLeftToRight } else { UserDefaults.standard.set("he", forKey: "Language") UIView.appearance().semanticContentAttribute = .forceRightToLeft } let objStoryboard = UIStoryboard.init(name: "Main", bundle: nil) let rootNav = objStoryboard.instantiateViewController(withIdentifier: "rootNav") as! UINavigationController UIApplication.shared.keyWindow?.rootViewController = rootNav UIApplication.shared.keyWindow?.makeKeyAndVisible() let objListStoryboard = UIStoryboard.init(name: "CountryListSB", bundle: nil) let objListVC = objListStoryboard.instantiateViewController(withIdentifier: "CountryListViewController") as! CountryListViewController rootNav.pushViewController(objListVC, animated: true) } else { let objListStoryboard = UIStoryboard.init(name: "CountryListSB", bundle: nil) let objListVC = objListStoryboard.instantiateViewController(withIdentifier: "CountryListViewController") as! CountryListViewController self.navigationController!.pushViewController(objListVC, animated: true) } }
In the above method, first, we have checked whether the selected language is equal to the previously selected language or not. If the currently selected language is the same as the previously selected language, then no need to change the application’s language. So simply push into the Country List view. Otherwise, check the selected language. If it is English then set it into UserDefaults and set app’s navigation left to right.
If the selected language is Hebrew, then set it into UserDefaults and set app’s navigation right to left. We have to set new rootViewController for getting the effect of newly set semantic. With the previous navigation, it is not possible to get the effect of new semantic so we created new navigation and set it into the application’s rootViewContoller. Then push view to the CountryListViewController. You can see that if the English language is selected then push animation will look from left to right and if Hebrew is selected then push animation will look from right to left.
Now open CountryListSB. Design title and tableview as below.
CountryListViewController.swift
Create a variable arrCountry for storing the country’s name in the selected language. and add data in viewDidLoad method as below:
var arrCountry = [String]() override func viewDidLoad() { super.viewDidLoad() arrCountry = [AppHelper.getLocalizeString(str: "India"), AppHelper.getLocalizeString(str: "Australia"), AppHelper.getLocalizeString(str: "Mexico"), AppHelper.getLocalizeString(str: "Kenya"), AppHelper.getLocalizeString(str: "China"), AppHelper.getLocalizeString(str: "Bhutan"), AppHelper.getLocalizeString(str: "Canada"), AppHelper.getLocalizeString(str: "Japan"), AppHelper.getLocalizeString(str: "Qatar"), AppHelper.getLocalizeString(str: "Israel")] lblTitle.text = AppHelper.getLocalizeString(str: "Country List") if UserDefaults.standard.object(forKey: "Language") as! String == "he" { self.btnBack.imageView!.transform = CGAffineTransform(scaleX: -1, y: 1) } }
Check Selected Language:
Here we have checked the selected language from UserDefaults and if it is Hebrew then rotate the back arrow image 180 degrees because as said before, in Hebrew language direction is right to left. We will rotate all directional images 180 degrees for the Hebrew language.
Write the following function for back button.
@IBAction func onClickBack(_ sender: Any) { _ = self.navigationController?.popViewController(animated: true) }
Here is table view delegate and data source method:
extension CountryListViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return arrCountry.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let lblCountryName = cell.viewWithTag(101) as! UILabel lblCountryName.text = arrCountry[indexPath.row] let imgSelect = cell.viewWithTag(102) as! UIImageView if UserDefaults.standard.object(forKey: "Language") as! String == "he" { imgSelect.transform = CGAffineTransform(scaleX: -1, y: 1) } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let objDetailStoryboard = UIStoryboard.init(name: "CountryDetailSB", bundle: nil) let objDetailVC = objDetailStoryboard.instantiateViewController(withIdentifier: "CountryDetailViewController") as! CountryDetailViewController objDetailVC.countryName = arrCountry[indexPath.row] self.navigationController?.pushViewController(objDetailVC, animated: true) } }
What’s next?
Here we have set arrCountry data in tableview. And on select cell, push the viewController to the country details view. We have passed countryName to the detail view so that it can be set to the title of that view.
Open CountryDetailSB.storyboard. Design title and tableview as below.
Here we have done a simple design with the country name and its description.
CountryDetailViewController.swift
We have created countryName variables and store the value that is passed from CountryListViewController.
Implement viewDidLoad method as below for setting country name and description.
var countryName: String = "" override func viewDidLoad() { super.viewDidLoad() lblTitle.text = AppHelper.getLocalizeString(str: countryName) lblDescription.text = AppHelper.getLocalizeString(str: "Country Description Here...") if UserDefaults.standard.object(forKey: "Language") as! String == "he" { self.btnBack.imageView!.transform = CGAffineTransform(scaleX: -1, y: 1) } }
Implement back button action
@IBAction func onClickBack(_ sender: Any) { _ = self.navigationController?.popViewController(animated: true) }
Our Localization demo is complete. You can localize your app with these methods. Hope you enjoyed this blog.