sizzle beam
sizzle beam

Reputation: 605

Is there a way to make `genstrings` work with `LocalizedStringKey`?

Is there a way get Apple's genstrings command line tool to recognize localizable string keys defined from SwiftUI's LocalizedStringKey initializer?

For this input file (testing-genstrings.swift): ...

import UIKit
import SwiftUI

enum L10n {
    static let test0 = NSLocalizedString("TEST0", comment: "")

    static let test1 = LocalizedStringKey("TEST1")

    static func test2(_ parameter: String) -> LocalizedStringKey {
        return LocalizedStringKey("TEST2_\(parameter)")
    }

    static func test3(_ parameter: String) -> String {
        return NSLocalizedString("TEST3_\(parameter)", comment: "")
    }

    static func test4(_ parameter: String) -> String {
        return String.localizedStringWithFormat(NSLocalizedString("TEST4", comment: ""), parameter)
    }
}

let test5 = "TEST5"
let test6 = "TEST6"
let test7 = "TEST7"

struct TestView: View {
    var body: some View {
        VStack {
            Text(L10n.test0)
            Text(L10n.test1)
            Text(L10n.test2("foo"))
            Text(L10n.test3("bar"))
            Text(test5)
            Text(LocalizedStringKey(test6))
            Text(NSLocalizedString(test7, ""))
            Text("TEST8")
            Text("TEST9_\("baz")")
        }
    }
}

...genstrings generates this output:

$ genstrings -SwiftUI -s LocalizedStringKey testing-genstrings.swift && iconv -c -f utf-16 -t utf-8 Localizable.strings
genstrings: error: bad entry in file testing-genstrings.swift (line = 9): Argument is not a literal string.
genstrings: error: bad entry in file testing-genstrings.swift (line = 11): Argument is not a literal string.
genstrings: error: bad entry in file testing-genstrings.swift (line = 12): Argument is not a literal string.
genstrings: error: bad entry in file testing-genstrings.swift (line = 36): Argument is not a literal string.
genstrings: error: bad entry in file testing-genstrings.swift (line = 37): Argument is not a literal string.
genstrings: error: bad entry in file testing-genstrings.swift (line = 37): Argument is not a literal string.
/* No comment provided by engineer. */
"bar" = "bar";

/* No comment provided by engineer. */
"foo" = "foo";

/* No comment provided by engineer. */
"TEST0" = "TEST0";

/* No comment provided by engineer. */
"TEST3_\(parameter)" = "TEST3_\(parameter)";

/* No comment provided by engineer. */
"TEST4" = "TEST4";

/* No comment provided by engineer. */
"TEST8" = "TEST8";

/* No comment provided by engineer. */
"TEST9_%@" = "TEST9_%@";

You can see that it recognizes the keys defined via NSLocalizedString and Text's initializer Text() initializer that uses ExpressibleByStringInterpolation (TEST9_%@ in the example), but fails on all keys defined using LocalizedStringKey.

Upvotes: 3

Views: 857

Answers (1)

Matt Gallagher
Matt Gallagher

Reputation: 14968

genstrings is relatively naive. It is looking for a function with two parameters, the first unnamed, the second named "comment".

If you added the following extension:

public extension LocalizedStringKey {
    init(_ value: String, comment: String) {
        self.init(value)
    }
}

and always used that, you'd be able to use LocalizedStringKey by passing -s LocalizedStringKey to genstrings.

Keep in mind that if you declared LocalizedStringKey as a return type or a variable, that would give a genstrings error, too. So you'd need a separate typealias LocalizedStringKeyResult = LocalizedStringKey that you use when reference LocalizedStringKey but don't want genstrings to complain.

And, of course, you wouldn't get the interpolation you want because genstrings applies that only to Text.

The real answer is... don't use LocalizedStringKey. Use Text when you can (to get interpolation). Use NSLocalizedString when you can't.

Upvotes: 3

Related Questions