How can I set ios application supported languages?
e.g I use NSDate to get current day. If the device language is other than my supported languages NSDateFormatter returns "day" in device's language but I want to get in English if I don't support that language.
I know there is a way to get day in specific language using NSLocal but I don't want to do that way because I need to convert other strings as well.
The Apple documentation covers this pretty clearly. I know all you need is the word "day", but the following will help you include any word for any language if you do as follows:
1) You need to place all of the words (Strings) in your application into a single .swift file. Each word should be returned in a function that converts this string into the localized string per the device's NSLocal set in the device settings:
struct Localization {
static let all: String = {
return getLocalized("All")
}()
static let allMedia: String = {
return getLocalized("All Media")
}()
static let back: String = {
return getLocalized("Back")
}()
// ...and do this for each string
}
2) This file should also contain a static function that will convert the string:
static func getLocalized(_ string: String) -> String {
return NSLocalizedString(string, comment: "")
}
Here, the NSLocalizedString( method will do all of the heavy lifting for you. If will look into the .XLIFF file (we will get to that) in your project and grab the correct string per the device NSLocale. This method also includes a "comment" to tell the language translator what to do with the "string" parameter you passed along with it.
3) Reviewing all of the strings that you placed in your .swift file, you need to include each of those into an .XLIFF file. This is the file that a language expert will need to go over and include the proper translated word per string in the .XLIFF. As I stated before, this is the file that once included inside your project, the NSLocalizedString( method will search this file and grab the correct translated string for you.
And that's it!
Related
#State var selectedSpace : FreeSpace = .Big_Bag
Picker("", selection: $selectedSpace) {
ForEach(FreeSpace.allCases) { FreeSpace in
Text(FreeSpace.rawValue.capitalized)
}
}.environment(\.locale, Locale.init(identifier: "az-Arab"))
.foregroundColor(Color("Color"))
.padding(.trailing)
Knowing that the pickerValues
enum FreeSpace: String, CaseIterable, Identifiable {
case Big_Bag, Small_Bag
var id: Self { self }
}
i'm trying to convert what is inside the picker to arabic and can't find a solution it is always displayed in english.
From apple doc :
If you intialize a text view with a variable value, the view uses the init(:) initializer, which doesn’t localize the string. However, you can request localization by creating a LocalizedStringKey instance first, which triggers the init(:tableName:bundle:comment:) initializer instead:
// Don't localize a string variable...
Text(writingImplement)
// ...unless you explicitly convert it to a localized string key.
Text(LocalizedStringKey(writingImplement))
That means that you must use :
Text(LocalizedStringKey(FreeSpace.rawValue.capitalized))
I think you misunderstood the concept of iOS localization. In you app you need to provide localizable strings file (usually it is named Localizable.strings), which holds localization values for your supported languages.
So basically in your project settings, you need to enable desired languages (English and Arabic on the screenshot).
Then you create Localizable.strings file and add it as a resource of your app. Then just make it localizable by clicking localize in File Inspector.
This will let you choose what language you want to use for the current file. Once you make it localizable you can tick what languages to use and you can switch them in Project Navigator.
Since now you will put localized texts in its appropriate Localizable file and use its key to access it.
Then if you use Text(String(localized: "key").uppercased()) you should be fine.
On Xcode (Swift) I want to load data stored on the app based on information provided by the user.
For example, the user gives the input of "Xcode":
var userInput = "Xcode"
With this information, I want to display the a stored string with the exact same name that is already on the app:
let Xcode = "Xcode is a development tool."
This is what I get when I print:
print ("Print: ", userInput) -> Print: Xcode
But I want to print the result from the string value stored from the app instead. The result I'm looking for is this:
print ("Print: ", userInput) -> Print: Xcode is a development tool.
I have to associate the input to the string stored, how can I do this without manually associating thousands of words to the strings I want to show? What is the best approach to get this result?
Thanks!
My approach where I have to do one by one is this:
switch userInput {
case Xcode: // This is the info provided by the user.
userInput = Xcode // This is the string stored on the app.
break
}
But once I have thousands of strings this approach is terrible, but works:
print ("Print: ", userInput) -> Print: Xcode is a development tool.
You have to define a data model for your information. If you have too much data, I suggest to create a JSON file where each key is the userInput with the associated value. Then you can parse the JSON file into a dictionary where you can easily retrieve the key-related value.
At this point you can define your own print method that prints the value associated with the key passed as parameter simply using object(forKey:) method.
I can't exactly understand your question. But what I've understood is to do this with Dictionary data type. Here is the sample code for this.
var str = "Hello, playground"
var responseMessages : [String : String] = ["" : ""]
if responseMessages[str] == nil
{
responseMessages[str] = str;
}
print(responseMessages[str]) // Output : Optional("Hello, playground")
You know better to remove optional keyword from string values by casting them to String data type.
I want create an iOS app for my school.
This App will show Week schledule and when I tap on Cell with Subject, it will show me detail info about subject...
My problem:
Our teachers use shotcuts for their names, but I want show their full name... I created the file "ucitele.h" with definitions of their names, but I don't know, how to use it 😕.
This is how that file looks:
//
// ucitele.h
//
#define Li #"RNDr. Dan---vá"
#define He #"Mgr. Ja---hl"
#define Sm #"Ing. Mich---rek"
#define Ks #"Mgr. Svat---á"
I get the shortcut of Teacher from previous view from "self.ucitel" and I maybe want compare the contents of the "self.ucitel" with definitions and set the "ucitelFull" string from the definitions? I don't know how to say it 😕.
when the content of the self.ucitel will be #"Sm", than I want parse "ucitelFull" as #"Ing. Mich---rek"
Answers in Objective-C only please
Okay, sounds like your trying to map a short identifier to a full name:
-(NSString*)fullNameFromShortName:(NSString*)short {
NSDictionary * names = #{#"Li" : #"RNDr. Dan---vá",
#"He" : #"Mgr. Ja---hl", ... };
return [names objectForKey:short];
}
Use like:
self.ucitelFull = [self fullNameFromShortName:self.ucitel];
This is a dictionary that has the short name as a key and the full name as the value.
Some further suggestions:
try using lowercase keys and comparing lowercaseString's, incase the user doesn't enter the value with the correct case.
You can move the dictionary definition into a json file and read it from your bundle, to eliminate the hardcoding
So, I'm localizing an app from japanese to english.
In japanese, there is no distinction between (say) "Mr." and "Ms."(/"Mrs."), so I need to do something like this:
/* Salutation format for user (male) */
"%#様" = "Mr. %#";
/* Salutation format for user (female) */
"%#様" = "Ms. %#";
As you can see, the Japanese localization uses the same string in both cases. I was under the impression that, when the strings file contains more than one entry with the same 'source' (i.e., left side) string, the 'comment' was used to determine which one was employed. It turns out I was wrong, and the comment parameter is just an aid for human translators, totally ignored by NSLocalizedString().
So if I run the app, both of the code paths below produce the same string, regardless of the user's gender:
NSString* userName;
BOOL userIsMale;
/* userName and userIsMale are set... */
NSString* format;
if(userIsMale){
// MALE
format = NSLocalizedString(#"%#様",
#"Salutation format for user (male)");
}
else{
// FEMALE
format = NSLocalizedString(#"%#様",
#"Salutation format for user (female)");
}
NSString* salutation = [NSString stringWithFormat:format, userName];
So, how should I deal with a case like this?
Well, actually “left side” of the NSLocalizedString is a key. So you could do something like:
NSLocalizedString(#"SalutForUserMale", #"Salutation format for user (male)");
NSLocalizedString(#"SalutForUserFemale", #"Salutation format for user (female)");
Then in your base *.strings file (Japanese I presume) you would have:
"SalutForUserMale" = "%#様";
"SalutForUserFemale" = "%#様";
And in your English *.strings file you would have:
"SalutForUserMale" = "Mr. %#";
"SalutForUserFemale" = "Ms. %#";
The Localizable.strings files are nothing more than key value lists. You are using the Japanese phrases as keys which is unusual but I guess it works. I assume this is because the original app was developed in Japanese(?). I usually use English phrases keys, but whatever.
The point is that if you want two different phrases in even just one translation you have to have two different keys in all your translations. If there is something in your base language that is not distinguished but in the translations it is, then you can just "split" an existing key in two new ones. Just change it slightly or add a number, see below:
/* english .strings file */
"hello_world_key" = "Hello World";
"Yes1" = "Yes"; // same in english but different values in german
"Yes2" = "Yes";
/* german .strings file */
"hello_world_key" = "Hallo Welt";
"Yes1" = "Ja";
"Yes2" = "Jawohl";
How can we internationalize the placeholder property's value of a UITextField in interface builder-attribute inspector?
You can easily change it without writing any code.
here is the example in your localized strings file set your placeholder as follows
"itw-s8-fkt.placeholder" = "YOUR TEXT";
You do the same localization as usual:
myTextField.placeholder = NSLocalizedString(#"emptyUsername",
#"userNameTextFieldPlaceholder");
Then you enter the according string in your localizable strings file.
The question has been discussed here, too:
How to use NSLocalizedString in IB [iPhone SDK]?
Describing an alternative, using several xib files.
What I've done, to minimise the amount of localisation boilerplate, is follow the model outlined here (GitHub here): create Interface Builder-friendly helper extensions (#IBInspectable vars, in a single file for convenience) for all the types of controls I want localised, including one for UITextField placeholders. I can then centralise all localisations to a single .strings file for each language and hook them up via IB. The only downside is remembering to add the keys when I create the controls. Localisation debugging (set by editing the Run scheme; I run the app in a non-base language by default) helps spot these early.
I have a single Excel spreadsheet containing keys and translations that gets passed to local translators to update, and a script that (re)generates the .strings files from the .csv prior to release.
With reference to the linked tutorial, my UITextField extension looks like this:
extension UITextField: XIBLocalizable {
#IBInspectable var xibLocKey: String? {
get { return nil }
set(key) {
text = key?.localized
}
}
#IBInspectable var xibPlaceholder: String? {
get { return nil }
set(key) {
placeholder = key?.localized
}
}
}
(The linked GitHub has an almost identical version I've only just spotted). Worth noting that when adding a new localisation I have to manually delete the contents of the XCode autogenerated .strings file, while leaving the file in place, to ensure the extensions get called.