如何使用依赖自动语法协议的字符串使用插值?

发布于 2025-01-23 03:20:13 字数 3206 浏览 0 评论 0原文

我正在尝试解决一个看似简单的问题:在SwiftUi 文本视图中向用户显示免费试用条款。我有一个单元字符串设置为“ Week”value,我可以从1切换到2。要处理复数,我会利用自动语法协议iOS 15。我在interizable.strings.strings文件中准备好了一个字符串:

"Subscription period: %lld %@" = "^[%lld ^[%@](grammar: { partOfSpeech: \"noun\" })](inflect: true)";

要构建字符串,i 需要使用字符串插值来添加'free' 。我知道,添加字符串文件中的单词可以解决问题,但我不想这样做。我想普遍使用该字符串,不一定与免费试验有关。我不明白为什么我不能称呼某些初始化,将其传递给钥匙,然后将我可以按照自己的意愿插入的纯字符串。我尝试了许多在附加的代码段中显示的方式。找不到字符串,或者未应用自动语法协议。似乎有string.localizationValue.StringInterPolation struct,但由于没有任何文档,我不知道如何使用它。我在做什么错?感谢任何帮助!

struct ContentView: View {
    /// This value mimics what **StoreKit 2** returns for `Product.SubscriptionPeriod.Unit` in its `localizedDescription` on iOS 15.4.
    let unit = "Week"
    
    @State var value = 1
    
    var key: LocalizedStringKey {
        "Subscription period: \(value) \(unit)"
    }
    
    var plainStringKey: String {
        "Subscription period: \(value) \(unit)"
    }
    
    var body: some View {
        Form {
            Section {
                // Works fine without string interpolation.
                Text(key)
                    .foregroundColor(.green)
                
                // `NSLocalizedString` doesn't work and it shouldn't as per its docs.
                Text("\(NSLocalizedString(plainStringKey, comment: "")) free")
                    .foregroundColor(.red)
                
                // Doesn't see the string.
                Text("\(String(localized: String.LocalizationValue(stringLiteral: plainStringKey))) free")
                    .foregroundColor(.red)
                
                // This way also doesn't see the string, which is strange, because it should be just like the following way, which does see the string.
                Text("\(String(localized: String.LocalizationValue.init(plainStringKey))) free")
                    .foregroundColor(.red)
                
                // Sees the string (only if I pass literal, not the plainStringKey property), but doesn't apply automatic grammar agreement.
                Text("\(String(localized: String.LocalizationValue("Subscription period: \(value) \(unit)"))) free")
                    .foregroundColor(.red)
                
                
                // MARK: Bad solution:
                /*
                 - Doesn't work with Dynamic Type properly
                 - You have to approximate horizontal spacing
                 */
                
                HStack(spacing: 3) {
                    Text("Subscription period: \(value) \(unit)")
                        .textCase(.lowercase)
                    Text("free")
                }
                .foregroundColor(.orange)
            }
            
            Section {
                Stepper(value: $value, in: 1...2) {
                    Text("Value: \(value)")
                }
            }
        }
    }
}

=“ 500” height =“ 649” title = “ “>在这里。

I'm trying to solve a seemingly simple issue: display free trial terms to the user in SwiftUI Text view. I have a unit string set to "Week" and a value that I can switch from 1 to 2. To handle plurals, I'm taking advantage of automatic grammar agreement on iOS 15. I have a string ready in my Localizable.strings file like so:

"Subscription period: %lld %@" = "^[%lld ^[%@](grammar: { partOfSpeech: \"noun\" })](inflect: true)";

To build out the string, I need to use string interpolation to add the word 'free'. I know that adding the word inside strings file will solve the issue, but I don't want to do that. I want to use that string universally, not necessarily pertaining to free trials. I don't understand why I can't call some init, pass it a key, and get a plain string back that I can interpolate as I wish. I've tried a lot of ways that are showcased in the code snippet attached. Either the string is not found, or the automatic grammar agreement is not applied. There appears to be String.LocalizationValue.StringInterpolation struct, but I can't figure out how to use it since there is no documentation whatsoever. What am I doing wrong? I would appreciate any help!

struct ContentView: View {
    /// This value mimics what **StoreKit 2** returns for `Product.SubscriptionPeriod.Unit` in its `localizedDescription` on iOS 15.4.
    let unit = "Week"
    
    @State var value = 1
    
    var key: LocalizedStringKey {
        "Subscription period: \(value) \(unit)"
    }
    
    var plainStringKey: String {
        "Subscription period: \(value) \(unit)"
    }
    
    var body: some View {
        Form {
            Section {
                // Works fine without string interpolation.
                Text(key)
                    .foregroundColor(.green)
                
                // `NSLocalizedString` doesn't work and it shouldn't as per its docs.
                Text("\(NSLocalizedString(plainStringKey, comment: "")) free")
                    .foregroundColor(.red)
                
                // Doesn't see the string.
                Text("\(String(localized: String.LocalizationValue(stringLiteral: plainStringKey))) free")
                    .foregroundColor(.red)
                
                // This way also doesn't see the string, which is strange, because it should be just like the following way, which does see the string.
                Text("\(String(localized: String.LocalizationValue.init(plainStringKey))) free")
                    .foregroundColor(.red)
                
                // Sees the string (only if I pass literal, not the plainStringKey property), but doesn't apply automatic grammar agreement.
                Text("\(String(localized: String.LocalizationValue("Subscription period: \(value) \(unit)"))) free")
                    .foregroundColor(.red)
                
                
                // MARK: Bad solution:
                /*
                 - Doesn't work with Dynamic Type properly
                 - You have to approximate horizontal spacing
                 */
                
                HStack(spacing: 3) {
                    Text("Subscription period: \(value) \(unit)")
                        .textCase(.lowercase)
                    Text("free")
                }
                .foregroundColor(.orange)
            }
            
            Section {
                Stepper(value: $value, in: 1...2) {
                    Text("Value: \(value)")
                }
            }
        }
    }
}

You can download the sample project here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盗梦空间 2025-01-30 03:20:13

实际上,我对此代码非常接近:

Text("\(String(localized: String.LocalizationValue("Subscription period: \(value) \(unit)"))) free")

但是使用String(本地化:)不正确。我想这是因为自动语法协议使用Markdown,这是属于属性的特权。我们应该使用属性string(本地化:)。但是即使那样,它也不会发生变化,因为显然基础上有一个错误。但是一旦修补了,它将像魅力一样工作。

这是正确的解决方案:

func freeTrialDuration() -> Text {
    // Use plain string.
    let duration: String = "^[\(value) ^[\(unit.lowercased())](grammar: { partOfSpeech: \"noun\" })](inflect: true)"
    // Use the following way to get the localized string.
    let localizedDuration = AttributedString(localized: String.LocalizationValue(duration))
    
    return Text("\(localizedDuration) free")
}

I was actually very close with this piece of code:

Text("\(String(localized: String.LocalizationValue("Subscription period: \(value) \(unit)"))) free")

But using String(localized:) isn't correct. I guess it's because automatic grammar agreement uses markdown, which is the prerogative of AttributedString. We should use AttributedString(localized:). But even then, it's not going to inflect because apparently there is a bug in Foundation. But once it gets patched, it will work like a charm.

Here is the correct solution:

func freeTrialDuration() -> Text {
    // Use plain string.
    let duration: String = "^[\(value) ^[\(unit.lowercased())](grammar: { partOfSpeech: \"noun\" })](inflect: true)"
    // Use the following way to get the localized string.
    let localizedDuration = AttributedString(localized: String.LocalizationValue(duration))
    
    return Text("\(localizedDuration) free")
}
执手闯天涯 2025-01-30 03:20:13

我遇到了与自动语法协议有关的相同问题。我尝试了你的答案,但就像你提到的

,但即使那样,它也不会发生变化,因为显然基础上有一个错误。但是一旦修补了,它将像魅力一样工作。

现在是2024年,但仍未修补(可悲的是)。所以我最终做出了这一决定,

func description(for property: SubscriptionProperties) -> Text {
    switch property {
    case .subscription:
        let localizedStringKey = LocalizedStringKey("^[\(subscription) workout](inflect: true)")

        return Text(localizedStringKey)
    ....
}

这解决了我的问题!希望它也能帮助您!

I had the same problem related to automatic grammar agreement. I tried your answer, but like you mentioned

But even then, it's not going to inflect because apparently there is a bug in Foundation. But once it gets patched, it will work like a charm.

Right now it is 2024 and it is still not patched(sadly). So i ended up with that decision

func description(for property: SubscriptionProperties) -> Text {
    switch property {
    case .subscription:
        let localizedStringKey = LocalizedStringKey("^[\(subscription) workout](inflect: true)")

        return Text(localizedStringKey)
    ....
}

This fixed my problem! Hope it helps you too!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文