I thought I read this somewhere but can't find it here or on the web. Was I dreaming?
When testing auto layouts and localizations, is there a way in XCode to add an argument to a scheme for it to change the English text to longer text for testing purposes to make sure the layouts adjust to longer languages?
Go to Product->Scheme->Edit scheme.
Choose Run section on the left and add to "Arguments Passed On Launch" this (for example):
-AppleLanguages "(Italian)"
To make it more relevant, here is helpful post on NSHipster:
http://nshipster.com/launch-arguments-and-environment-variables/
Abizern has the correct answer, but a typo. The correct key is NSDoubleLocalizedStrings (note the ending "s"). Add this as an argument passed on launch, like
-NSDoubleLocalizedStrings YES
You weren't dreaming, it was demonstrated in one of the WWDC13 videos. The key you are looking for is:
NSDoubleLocalizedStrings
which doubles the localised strings that your application uses, which means that UI elements that load these strings will be enlarged and you can see that your auto layouts can handle the newly constrained objects.
Related
Does Xcode or Swift have a list of predefined localized words (e.g. "Delete", "Edit" etc.) that I can use in my app and to be sure that it localized properly?
If you have a Navigationview and you use a Navigationlink, you will see, that the back button will be localized automatically (at lest for german in my app). So all buttons that get generated for you, could be localized for some languages.
But as far as I know, there is no set of predefined localizations you could access to use. Though it is very easy in SwiftUI to make localizations, just have a look at:
https://phrase.com/blog/posts/swiftui-tutorial-localization/
If you have a string file with your localizations you can use the definitions of those strings directly in the text parameters of the SwiftUI Views and they will automatically be changed with the localized version, no need to even cast the identifier of the string in the strings file to a LocalizedStringKey.
Seriously, if you were to rely on some automatic translation for your UI, then I can promise you that people will complain, because most will find an automatic translation into their own language harder to read than good English.
TLDR: Xcode generated storyboards for each language, however I want the "old"(?) *.strings files. How?
I am currently in the process of localising my storyboards. After I enabled everything, Xcode generated another storyboard alongside the original (english) one for me to localise. I was surprised, I expected a Localizable.strings file, like the apple documentation still states as of April 3, 2021:
For storyboard and XIB interfaces, select the user interface files (files with a .storyboard or .xib filename extension). Xcode adds a strings file to the localization folder that contains the text to translate, as well as comments that describe the user interface components. For example, if you add German to an iOS app that uses storyboards, LaunchScreen.storyboard becomes a group containing a LaunchScreen.storyboard (Base) and LaunchScreen.strings (German) file.
I searched around the internet, in apple developer forums, watched both WWDC18 and 19 talks about localisation in Xcode, but did not find a single mention of translated storyboards.
After the initial translation, which works great due to the simplicity of just filling everything in, it gets frustrating however, since every layout change needs to be repeated for every language. This can't be intended, there must be a better way, right? Sadly, I didn't find anything. Even a hint to a piece of documentation regarding these storyboard copies would be greatly appreciated. Thanks!
There are some screenshots of the possibility to convert these two formats via a dropdown, like the third picture in this post. However for me, there is no dropdown next to the language item when I click the storyboard, neither on the group, nor individual base or localised ones:
Is this a bug or am I missing something here? I am using macOS Big Sur 11.2.3 with Xcode 12.4 (12D4e).
Turns out, you need to use the Base Localization feature, the dropdown then appears and you can convert existing storyboards to *.strings files.
I am facing a very obscure issue.
I've got an app that needs to be localized in three Languages, English, French, German. There's multiple localization files as I've got multiple storyboards ( each storyboard has one for each language).
Everything works great and things translate properly except for ONE file in ONE storyboard in ONE language. So this specific storyboard I call "Authentication" works for all languages except for the German one.
I've checked. the file is:
included in all targets
is also found in Build Phases copy phase
has the correct name.
has the correct formatting (in fact i am not allowed to build at all if the formatting is not correct in this version of Xcode.)
I am out of ideas and resorting to asking here to see if theres anything i might be missing in my series of checks.
Thanks all
SOLVED.
The answer lies within my third point
has the correct formatting (in fact i am not allowed to build at all
if the formatting is not correct in this version of Xcode.)
Beware everyone. This might seem like it is the case but it does not apply to everything. If there's a syntactic error in the Localizable.strings file, xcode will let you know and refuse to build.
HOWEVER if there's a syntax error in the YourStoryboard.strings file, the process of building will go on UNHINDERED.
Since an issue in syntax was halting everything for Localizable.strings i was wrongfully assuming that such a check would take place for all translation files. It doesnt!
Hope this saves someone in the future
I'd like to easily test my app with different selections of system text size, including accessibility sizes. These can be set in the Settings app (Display & Brightness => Text Size or General => Accessibility => Larger Text).
The only way I can find to currently do this is to go into Settings and change the value with the UI (edit: partial solution described below). This is slow and cumbersome. I suspect there's a way to dynamically alter it using private APIs, but I can't figure out how. Since my goal is to only use this for debugging, private API use and swizzling is fine (this code won't be making its way to production).
To try to find a private API to do this, I looked at some reverse engineering resources. I'm new to disassemblers, symbol tables, class dumps, and finding private APIs I can use, but this is what I've tried so far:
I successfully swizzled -[UIApplication preferredContentSizeCategory] (other posts said this worked in the past), but this doesn't affect the result returned from +[UIFont preferredFontForTextStyle:].
Using the disassembler IDA I discovered that +[UIFont preferredFontForTextStyle:] is in the private framework UIFoundation.framework. (-[UIApplication preferredContentSizeCategory] is in UIKit.framework but the disassembly didn't look at all useful).
Just as I started writing this question (it always happens that way), I discovered a partial solution. One can set a launch argument in the scheme to set the value on launch. This is useful, but not what I'm after.
Through the above answer, I found the value for the user's preference is apparently stored in "the com.apple.UIKit.plist file located in the Simulator's data/Library/Preferences directory". The value we're after can be set from the command line utility plutil. This is also an improvement! But I'd like to dynamically alter it at runtime.
More on my results from IDA:
I don't really know how to read disassembly, but +[UIFont preferredFontForTextStyle:] seems to point to a symbol called ___UIFontForTextStyle which seems to point to some interesting-sounding symbols called _getUIContentSizeCategoryUnspecified and _getUIContentSizeCategoryPreferenceClass
I also found these symbols using the command-line utility nm on UIFoundation.framework. They were marked with the lowercase letter "s" meaning, apparently, "The symbol is in an uninitialized data section for small objects.". I have no idea what this means (all I've gathered is that they're not a class or method).
Searching the web for the _getUIContentSizeCategory... symbols yields nothing, but nearby there's another symbol _getUIApplicationClass. I searched for that one since it sounded a bit more general, and found something similar in some WebKit source. Could be nothing, but maybe it's an internal Apple convention. Regardless, the example doesn't really help me solve the problem.
Anyway thanks for reading so far. If you're still here, my question is:
I'd like to be able to dynamically mock the value for the dynamic type size preference. These disassembly symbols might help, but maybe I'm on the wrong track. It feels like the solution is close but I just can't put all the pieces together.
Setting this value as a launch argument is nice, but doesn't fully solve my problem. Similarly, modifying the Simulator's value in the plist is also nice for automation, but doesn't solve my problem.
Is there a way to dynamically alter this value at runtime?
How embarrassing! I was looking at some out-of-date iOS 9.x documentation and missed that UITraitCollection gained init(preferredContentSizeCategory: UIContentSizeCategory) and var preferredContentSizeCategory: UIContentSizeCategory in iOS 10, which was helpfully pointed out to me by Brandon Williams. This addresses my needs perfectly.
One easy way is to write a wrapper around UIFontMetrics and route all UIContentSizeCategoryDidChange notifications through that. It allows for unit/UI testing various Dynamic Type settings. I wrote about it here.
I was wondering if somebody could explain in the details how I can localize an iOS app using only 1 storyboard. I know how to localize by creating several storyboards(one storyboard for each used language), however I'd like to find out another solution.
Thanks.
The tutorial on raywenderlich.com uses two forms of localization together. The reason is he also checks the storyboard when turning on localisation in image 3:
.
So then what?
NSLocalizedString is very useful, any text set programatically can (and should) be localised using this method. Ray's tutorial is still very useful.
However, it's not very desirable to create a clone of the storyboard(s) to do translation, it's just not very maintainable in the long run.
And what about storyboards?
The magic happens using the Base Localization feature. Base localization uses the generated objectId's to 'map' different languages to the storyboard.
Do note that this feature is only available using SDK 6.0 and above. Running the app on a lower iOS version will not cause any errors, it'll simply won't work.
Go to your project, and select Base Localization, then add any other language.
Open your storyboard file and check the new language as well. Note the icon is not a storyboard icon, but a simple text file icon. That's a good thing; it won't copy the whole storyboard this time :).
Note how there is now another file 'under' the storyboard. Xcode automatically generates a file for every language you select.
You can se Localization feature for this. You need to add the Localizable.strings file for each supported language and use it for locaization.
You need to use : NSLocalizedString() for fetcing data corresponding to each key.
Check this tutorial for details.