xcode: How to localize strings in code? - xcode

With localize I mean translate into different languages.
I only found Instructions for localizing the storyboard but I also have strings that I set in Code.
(I'm using Swift)

In short — see the NSLocalizedString function. This is also there in Swift... its declaration looks like this:
func NSLocalizedString(
key: String,
tableName: String? = default,
bundle: NSBundle = default,
value: String = default,
#comment: String) -> String
The third through sixth arguments have default values, so you can call it like this:
NSLocalizedString("foo") // -> Maybe「フー」in your Japanese strings file?
Or like this:
NSLocalizedString("foo", comment: "metasyntactic variable")
Or with any other combination of arguments.
Check out the Internationalization and Localization Guide in Apple's documentation.

Related

Documenting user created type declarations with Sphinx

I'm making a type declaration. For example:
from typing import Tuple
Type1 = Tuple[str, float]
I would like Sphinx to document this declaration like a function declaration. How can I do this? Thanks in advance.
If I bilded documentation and add usual description the result is that the declaration of these types is displayed as a plain text, not something special.
A canonical Python way is to use TypeAlias from PEP-653:
#: Funny type that is mixing strings and floats - sounds like JavaScript programming!
Type1: TypeAlias = Tuple[str, float]
It was added in Python 3.10.
As the writing of this, Sphinx component that does autogenerated documentation, autodoc, does not support TypeAlias yet.

Xcode Breakpoint and LLDB - How do I open a file (e.g. in Preview) from a given fileURL stored in a variable?

I have a variable in Swift code that runs in iOS simulator and contains an existing fileURL. I want to have the file opened in macOS (not the iOS Simulator) when I hit a breakpoint.
I added an action "Shell Command" to the breakpoint to open the file. The file exists because if I copy-paste the file's path to Terminal, it opens in Preview.
However, the Xcode console says the contrary:
The file /"/Users/tomkraina/Library/Developer/CoreSimulator/Devices/FBA16E00-9450-40E8-9650-1489A67E344C/data/Containers/Data/Application/BB97DB72-FF2A-4087-BD42-2934C63D3323/tmp/7E2303B8-0629-475A-862A-2550351FB448/OutlineExport.pdf" does not exist.
First Question: How do I tell Xcode to open a file with provided fileURL in a variable on breakpoint?
Next thing I tried was to open the file using LLDB, but I cannot find out how to evaluate a command parameter in LLDB, because backticks is only for scalars:
(lldb) shell open `temporaryFile.fileURL.path`
The file /105553157711856 does not exist.
Second Question: How to I evaluate argument parameter to get a string in LLDB?
I don't have a good answer for the first question. It would be interesting to check whether the path that is in the Xcode error message is correct - maybe it's getting it from the value incorrectly. If you copy the path from the error message, go to Terminal and try to open it, does that work? Anyway, this sounds to me like a bug in Xcode. It got some kind of path out of your variable and tried to open it, which should have worked. If you want to follow up, it's probably best to file a bug report with the Apple Feedback.
For the second question, you have to know a little about how variables work in lldb. Some variables have obvious values, for instance, in C a pointer has the pointer value, an integer the integer value, etc. Other variables (any kind of Struct being the obvious example) are actually containers of other values and don't really have a "value" themselves.
lldb can show you what a swift string really is using the --raw option:
(lldb) v --raw str1
(Swift.String) str1 = {
_guts = {
_object = {
_countAndFlagsBits = {
_value = -3458764513820540912
}
_object = 0x8000000100003f50 (0x0000000100003f50) strings`symbol stub for: Swift.print(_: Any..., separator: Swift.String, terminator: Swift.String) -> () + 4
}
}
}
That's probably really interesting to people working on the Swift Standard Library and has the virtue of being the truth. But for most purposes, it's not a terribly useful representation.
lldb handles that problem by adding a notion of "Summary Formatters" that generate a string representation for objects based on their type. There's one for "Swift.string" that digs around in the object, finds where the actual string is, and returns that text. If you don't pass --raw and there's a summary formatter, then lldb will show you the summary:
(lldb) v str1
(String) str1 = "some string here"
That is also the value that you want to try and open.
The backtick syntax in lldb gets the value of the entity, not its summary, which is why that didn't work for a swift string. However, you can fetch and act on the summaries for local variables using lldb's Python interpreter and the SB API. So for instance:
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> var = lldb.frame.FindVariable("str1")
>>> var.GetSummary()
'"some string here"'
So then if that was a file path you wanted to open, you can use Python to do that, like:
>>> os.system("open {0}".format(var.GetSummary()))
The file /private/tmp/some string here does not exist.
256
except of course your var has to hold the path to a real file...
If you want to learn more about the lldb Python API's the API docs are here:
https://lldb.llvm.org/python_api.html
and a general tutorial for using Python in lldb is here:
https://lldb.llvm.org/use/python-reference.html
And more information on variable formatting is here:
https://lldb.llvm.org/use/variable.html

Two targets and two Localizable.Strings (one base)

I have a simple problem and I can't figure out how to make it work.
I have two targets:
TargetApp1
TargetApp2
I have two Localizable.strings:
For translation for a second language.
For different names (on both languages), only for TargetApp2.
Example:
I have a button, a text, or something. On each app it should be different.
TargetApp1: en: "Store" - lg: "STORE_"
TargetApp2: en: "Dealer" - lg: "DEALER_"
I tried keeping the first Localizable.strings for both targets and making the second Localizable.strings for the second target only. The problem is that only ONE Localizable.strings is loaded at a time. I wanna know how to make the TargetApp2 make both Localizable.strings complement each other.
If I've understood your problem correctly, you'll need to give your Localizable.strings files different names and then use NSLocalizedStringFromTable, otherwise, as you've discovered, they'll conflict and only one is used at runtime.
e.g.
Leave your Target1's Localizable.strings as it is
Rename Target2's Localizable.strings to Extra.strings
Anywhere that uses a string from the second table, use NSLocalizedStringFromTable(key, #"Extra", comment)
I first encountered this problem when adding the Amazon AWS library which contains its own Localizable.strings which would arbitrarily be used instead of mine. However, because there are only a few strings in that file, it appeared as if localisation just wasn't working. That was a fun 2 days debugging!
Swift
The NSLocalizedStringFromTable doesn't exist with that exact name in Swift. Instead the table is an optional parameter in NSLocalizedString
func NSLocalizedString(
key: String,
tableName: String? = default,
bundle: NSBundle = default,
value: String = default,
#comment: String) -> String
With Swift, you'll just need to change your NSLocalizedString(key: key, comment: "") to NSLocalizedString(key: key, table:"Extra" comment: "") for the affected strings.

Why doesn't com.canon.cr2-raw-image conform to public.camera-raw-image according to UTTypeConformsTo?

I am try to see whether a certain image is a RAW image file by getting the UTI for the file, then using UTTypeConformsTo() to see if the image's UTI conforms to "public.camera-raw-image", but when I try doing so, UTTypeConformsTo() returns false. Here is the code in question:
- (NSNumber*)bw_conformsToUTI:(NSString*)otherString
{
Boolean conformsBoolean = UTTypeConformsTo((CFStringRef)self, (CFStringRef)otherString);
NSNumber* conforms = [NSNumber numberWithBool:conformsBoolean];
return conforms;
}
(the method is written as a category on NSString, and the lines are split apart like that because I was making sure in the debugger that there wasn't anything funny going on with converting from a Boolean to a BOOL and losing bits; conformsBoolean definitely comes back as all 0 bits)
If self is "com.canon.cr2-raw-image" and otherString is "public.camera-raw-image", I would expect this to return YES, but instead it results in NO. I tracked down where the "com.canon.cr2-raw-image" UTI is defined, and found it in /System/Library/CoreServices/CoreTypes.bundle/Contents/Library/RawCameraTypes.bundle/Info.plist where it does indeed specify that com.canon.cr2-raw-image conforms directly to public.camera-raw-image. I did notice that this is declare as an imported UTI and not an exported UTI, but since my application does recognize the declaration (as evidenced that I got that string in the first place via UTTypeCreatePreferredIdentifierForTag()), I don't think that should make a difference.
Is there anything obviously wrong that I'm doing or misunderstanding here?

How to set default language in WebOs

How can I set the dault language of an WebOs project?
The standard way of adding internationalization in WebOS is to use the $L() function, where I can set a key to the translated string. But if the current language ist not specified in the project WebOS displays the key to the user. How can I stopp this behaviour and set a default language, that will be taken instead of the key.
PS: I think the Palm way of taking a real world sentences is not a good way of programming.
Bad example: $L("This should be not a real world sentence!!")
Better example: $L("key.subKey")
You can use a key-value pair to solve this problem (from the Palm documentation):
If the original string is not appropriate as a key, the $L() function can be called with an explicit key:
$L("value":"Done", "key": "done_key");
At run-time, the result of the call to $L() is the translation of the string passed as value. The translations "live" in the /resources/locale/strings.json file.
Example:
content of file app_name/resources/es_us/strings.json:
{
"My text here": "Mi texto aquí",
"done_key": "Listo",
"Some other string": "Some other string's translation"
}

Resources