FlineDev/BartyCrouch

[Feat] Tip: How to localize LocalizedStringResource types with bartycrouch

mman opened this issue ยท 3 comments

mman commented

Problem Statement

I use bartycrouch successfully for years to help me manage localizations for base localized .storyboard files and regular .m and .swift files using NSLocalizedString.

Since working with iOS 16 AppIntents framework and possibly with SwiftUI type of localization, localized strings are not annotated anymore, but simply derived with the help of the compiler when a property of type LocalizedStringResource is encountered.

Sample code from AppIntents framework for example references the following:

struct ExportAllTransactionsIntent: AppIntent {
    static var title: LocalizedStringResource = "Export all transactions"
    
    static var description =
        IntentDescription("Exports your transaction history as CSV data.")
}

In the code above, both strings are correctly exported via Xcode -> Product -> Export Localization, loaded during runtime from Localizable.strings, but ignored by default when using bartycrouch update.

Solution

After much playing and tweaking I found out that integrating bartycrouch is as simple as this:

In .bartycrouch.toml:

[update.code]
...
customFunction = "LocalizedStringResource"

And in code:

struct ExportAllTransactionsIntent: AppIntent {
    static var title = LocalizedStringResource("Export all transactions", comment: "")
    
    static var description =
        IntentDescription(LocalizedStringResource("Exports your transaction history as CSV data.", comment: ""))
}

To summarize: all strings that need to be picked up by bartycrouch need to be wrapped with call to:

LocalizedStringResource("key", comment: "comment")

When you omit the comment: parameter, the code will compile, but bartycrouch update will fail the step xcrun extractLocStrings with the famous error "Argument is not a string literal" as it is expecting the comment: to be present.

Bonus point: xcrun extractLocStrings uses the -s argument to specify customFunction, confused people would expect that only strings annotated with the function are actually extracted, but deep in the legacy genstrings manpage is actually specified that any -s function is parsed in addition to NSLocalizedString and CFCopyLocalizedString methods...

So specifying customFunction in .bartycrouch.toml actually does not break the historical stuff and is purely additive.

Additional Considerations

I should probably open a PR against bartycrouch documentation to save others time I spent investigating this, I am putting it here for now for a google to find it should anybody suffer with this.

@mman Thank you for sharing this (even while I was live working on another issue ๐Ÿ˜† ). If it's true that the -s option only adds another function to the existing ones, I think we could add the LocalizedStringResource option there by default if no other option is specified in the config file. I would love to review & merge a PR which does this and documents that behavior in the README so people can discover this even within the README itself and don't need to search through the issues. :)

mman commented

From my limited testing it appears true and would be a nice addition... here is an excerpt from the genstrings(1) manpage:

     -s routine [-s routine ...]
                 Recognizes routine() as equivalent to NSLocalizedString().  For example, -s MyLocalString will catch calls to MyLocalString(),
                 MyLocalStringFromTable(), and so on.

                 This flag may be passed any number of times.

                 Note Specifying routine names to treat as equivalent to NSLocalizedString() does not prevent either NSLocalizedString() or
                 CFCopyLocalizedString() or any of their variants from being recognized.

Note that it can also be repeated multiple times. I will see if I can get a PR open during this week...

mman commented

@Jeehut I have tried to update the README and customFunction default value via #266. Let me know what you think...