i am currently doing an app that has language change feature. However,for every string that i wish to have changes made to when a different language is selected, i have to implement the following code
"Hello world".localize()
However, as the app gets bigger, the code become very messy in the way that all the strings in their respective view controllers have this .localize() append to it.
Is there a way where i can do this .localize() thing in one central place?
EDIT: I tried to create a Strings.swift file and put all the strings inside. I did something like this.
static let relevantString = "hello world".localize()
and then in the view controllers i call
let myString = relevantString
However, this does not well. The strings will only change after i terminate the app and restart it.
Your attempt to use static let fails to produce the dynamic behaviour you want simply because you used a constant. You could use a read only computed property instead, something like:
var relevantString : String { return "Hello World".localize() }
As an alternative, as you seem to be more concerned over the clutter, you could define a simple prefix or postfix unary operator which called localize() on its argument. Swift allows a number of symbols to be used as operators so the operator can just be a single character. For example you could define, say, § so that §"Hello World" produced a localised string.
HTH
Related
why
-(void)addSimpleListener:(id<XXSimpleListener>)listener
convert to swift look like this:
func add(_ listener: XXSimpleListener?) {
}
but change the method to this
-(void)addSimpleListener:(id<XXSimpleListening>)listener
and it will convert to this
func addSimpleListener(_ listener: XXSimpleListening?){
}
Xcode (or whatever tool you are using to do the conversion) is merely following Swift API guidelines. Specifically:
Omit needless words. Every word in a name should convey salient information at the use site.
More words may be needed to clarify intent or disambiguate meaning, but those that are redundant with information the reader already possesses should be omitted. In particular, omit words that merely repeat type information.
In the first case, the words SimpleListener in addSimpleListener is repeating the type of the parameter, so they are removed from the method name. However, in the second case, SimpleListener and SimpleListening does not look the same to whatever tool you are using, so it thinks that SimpleListener should be kept.
In my (human) opinion though, I think the method should be named addListener, because:
Occasionally, repeating type information is necessary to avoid ambiguity, but in general it is better to use a word that describes a parameter’s role rather than its type.
Listener is the role of the parameter.
I have an Objective C++ program used to handle the setup of our different applications. Is there a way to use preprocessor defines to create text to be substituted in the strings used by NSTextFieldCell, NSButtonCell?
FOR EXAMPLE, instead of have an NSTextField that says "Options for setting up Foo", there would be a preprocessor macro (GCC_PREPROCESSOR_DEFINITIONS):
MY_PROGRAM_NAME=Bar
and then the text for NSTextField would be:
"Options for setting up $(MY_PROGRAM_NAME)"
Which would then have the desired result: "Options for setting up Bar"
NOTE 1: obviously, I could do the substitution programmatically in code.
Note 2: this is for Xcode 7, so perhaps there isn't a feature like this?
In a word, no. The Xcode nib compiler doesn't perform any kind of variable substitution and—once encoded—all archived property values are static.
However, if this is a "thing" for you application, and there aren't too many view classes involved (say, just NSTextField), it wouldn't be hard to roll your own solution.
I'd consider this approach:
Concoct a simple-to-substitute syntax, a la "Some string {VAR_NAME}".
Define your variables as key/value pairs in a dictionary. Store the
dictionary as an XML file / dictionary in the app bundle.
At app startup, load the dictionary and make it public by putting it in
a global variable or adding it to -[NSUserDefaults registerDefaults:]
Subclass NSTextField (as an example). Override either
-initWithCoder: or -awakeFromNib. In the override, get the string
value of the view object, scan it for substitutions using the public
variable dictionary, and update the string property as appropriate.
In IB, change the class of any NSTextField that needs this feature to
your custom subclass.
Another possible approach would be to have multiple targets in your project and a separate Localizable.strings file for each of these. This of course assumes, that you use Localizable.strings, even if you may support only one language.
From this document:
To use a reserved word as an identifier, put a backtick (`) before and after it.
I'm curious about the practical application of this. When would you actually want to name something `class`, `self`, etc.?
Or, relatedly, why did the designers of Swift allow this, rather than just forbidding us from using reserved words as identifiers?
The most important usage is the interaction with other languages that have different keywords.
From Swift you can call C and Obj-C functions.
Now, consider for example that you need to call a C function called guard. However, that's a keyword in Swift, therefore you have to tell the compiler that you don't want to use it as a keyword but as an identifier, e.g.:
`guard`()
There are multiple keywords in Swift that are widely used as method/function names, e.g. get and set. For many contexts Swift is able to figure out the difference but not always.
In some cases using guard give us nice example for this purpose.In such scenario I need check self variable life time if not exist anymore (current controller deallocated) I don't want to execute rest of code.
guard let `self` = self else {
return
}
I have been searching for hours and I have not been able to find an answer. I'm making an app which uses multiple languages which the user can change during runtime, this is necessary for the product. Now I have been able to change the language with the following code:
userDefaults.setObject(["\(cc)"], forKey: "AppleLanguages")
userDefaults.synchronize()
This code works great. If I change the language setting from Dutch to English it does actually change. The underlying code that is. My app makes use of a server and when I try to logon to the english or dutch service with different credentials it recognises them and lets me login. However the view does not change until after a restart. I tried making it change with this:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
check.text = NSLocalizedString("currentLangauge", comment: "Just a check")
}
And the check label has been declared as:
#IBOutlet weak var check: UILabel!
After a restart it updates just fine but not during runtime and I know it should be possible because I have seen apps do it. I found some examples in Objective-C that use NSBundle but I am not familiar with Objective-C and I do not know how to convert this to Swift.
One of the examples in Objective-C: iOS Change app Language doesn't take effect
Does anybody has any experience with this?
You need to manually manage the process unfortunately. You'll need to write your own replacement of NSLocalizedString class, that checks user defaults and reads the language, then loads the string from the correct strings file.
You'll also need a mechanism to notify labels / text views / buttons that they should re-render their titles when the user changes language, as when the setting is changed, it's likely there will be a fair few views displaying text in memory. A crude solution is to subclass the foundation classes, initialise them with a string key, with which they perform their own text lookup. Then have them respond to a language changed notification that you fire when the user changes language. They can then perform another string lookup with your NSLocalizedString replacement class.
It's actually not as much effort as it sounds, but it is an effort. It's probably worth understanding string localisation as much as possible. Here are a couple of good resources.
http://nshipster.com/nslocalizedstring/
http://www.objc.io/issue-9/index.html
Eventhough "P-double" gave a very good suggestion on how to work around this. I couldn't really figure out a way to really implement this so I went with a different solution that may just take a tad bit more. Instead of just using the "Localizable.strings" file, I decided to just make a new strings file for each langauge and call them by the language identification (eg. mexico = es-MX, english = en).
Instead of rewriting NSLocalizedString, I opted to add the "tableName" option which can then default to the right .strings file. So when I change language now I do it like so:
cc = currentCell.langString
userDefaults.setObject(api, forKey: "api")
userDefaults.setObject(["\(cc)"], forKey: "AppleLanguages")
defaultTable = cc
userDefaults.synchronize()
And when I ask for a localized string I do it simply like so:
check.text = NSLocalizedString("currentLangauge", tableName: defaultTable, comment: "Just a check")
I can use this for everything that I can show on my storyboard, the only thing I have to do extra is really define every single object that is on the storyboard so I can adjust the text. With this "solution" you do not need to localize your storyboard anymore. Only the code.
I've recently been trying to learn the Object-Oriented aspects of F#, and have become curious about how to restrict access to types/modules in the language.
More specifically, I want to know the difference between writing this:
Example.fsi
module Stack =
val foo : string
Example.fs
module Stack =
let foo = "foo"
let bar = "bar"
and alternatively this:
module Stack =
let foo = "foo"
let private bar = "bar"
Do they not accomplish exactly the same thing in the end? Coming from a C# background, I'm much inclined just to use the access modifiers over signature (FSI) files. They seem to be more versatile (can apply to modules/types in namespaces, for example), whereas I don't any situation in which signature files offer something that access modifiers don't.
They accomplish almost the same thing. (Note that you can use an .fsi file for types in namespaces too, was unsure what your comment about that meant.)
A signature file has a couple advantages:
You can make entities public for the duration of the file, but then private to the subsequent files of the project.
You can have just your short summary in the signature file, so the public interface is easy to read without having to scan tons of code.
The first bullet is not to be trifled with - within-assembly encapsulation like this is actually a pretty huge feature for very large projects. Being able to define a few types which are public to one another within File1.fs, but then only have a subset of those types/methods be public to the rest (File2.fs, File3.fs, etc.) is quite useful (a little bit like 'friend' in C++).