簡體   English   中英

如何在 SwiftUI 中將 LocalizedStringKey 更改為 String

[英]How to change LocalizedStringKey to String in SwiftUI

我正在嘗試使用 SwiftUI 本地化 AppleMapView 中顯示的標記。

但是,MKAnnotation 的標記標題的類型固定為String 而且我不想繼承或創建自定義類,因為它太麻煩了。

我需要的只是將 LocalizedStringKey 轉換為 String來設置標記的標題。 有什么幫助嗎?

編輯:此答案已被編輯一次,以獲得更簡潔的代碼和更好的stringKey性能。

LocalizedStringKey有一個名為key的成員,其中包含與本地化文件中的本地化字符串相對應的密鑰字符串。 不幸的是,我們無法直接訪問密鑰,因此我們需要解決獲取密鑰的方法。

// An Example that won't work:
let localizedKey = LocalizedStringKey.init("SOME_LOCALIZED_KEY_HERE")

localizedKey.key // ERRROOOOORR! `key` is an internal member of `LocalizedStringKey` and you can't access it! 

解決方法擴展,以及它如何工作的示例,以從 LocalizedStringKey 中獲取密鑰:

extension LocalizedStringKey {

    // This will mirror the `LocalizedStringKey` so it can access its 
    // internal `key` property. Mirroring is rather expensive, but it 
    // should be more than fine performance-wise, unless you are  
    // using it too much or doing something out of the norm.
    var stringKey: String? {
        Mirror(reflecting: self).children.first(where: { $0.label == "key" })?.value
    }

// An Example:
let localizedKey = LocalizedStringKey("KEY_HERE")
print(localizedKey.stringkey)
// prints `KEY_HERE`

現在我們將鍵作為字符串,您可以輕松獲取 LocalizedStringKey 的鍵所指向的本地化字符串。

extension String {
    static func localizedString(for key: String,
                                locale: Locale = .current) -> String {
        
        let language = locale.languageCode
        let path = Bundle.main.path(forResource: language, ofType: "lproj")!
        let bundle = Bundle(path: path)!
        let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")
        
        return localizedString
    }
}

要了解這一點,請查看https://stackoverflow.com/a/27879342/11837341

現在您可以輕松地將 LocalizedStringKey 的值轉換為字符串:

extension LocalizedStringKey {
func stringValue(locale: Locale = .current) -> String {
        return .localizedString(for: self.stringKey, locale: locale)
    }
}

TL; 博士(總結)

將這些擴展添加到您的項目中:

extension LocalizedStringKey {
    var stringKey: String? {
        Mirror(reflecting: self).children.first(where: { $0.label == "key" })?.value
    }
}

extension String {
    static func localizedString(for key: String,
                                locale: Locale = .current) -> String {
        
        let language = locale.languageCode
        let path = Bundle.main.path(forResource: language, ofType: "lproj")!
        let bundle = Bundle(path: path)!
        let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")
        
        return localizedString
    }
}

extension LocalizedStringKey {
    func stringValue(locale: Locale = .current) -> String {
        return .localizedString(for: self.stringKey, locale: locale)
    }
}

例子

let localizedKey = LocalizedStringKey("KEY_NAME_HERE")

print(localizedKey.stringKey)
//prints `KEY_NAME_HERE`

print(localizedKey.stringValue())
// prints Localized value of `KEY_NAME_HERE`
// DOESNT print `KEY_NAME_HERE`

您可以使用 NSLocalizedString。

let localizedString = NSLocalizedString("LOCALIZED-STRING-KEY", comment: "Describe what is being localized here")

您可以簡單地使用: String(localized: "YOUR_LOCALIZED_KEY")

Mahdi BM 的解決方案有一個問題,因為即使您使用西班牙語和葡萄牙語等語言的變體,Swift 也只會返回語言代碼。 兩個示例的語言代碼將始終返回 ES 和 PT,但具有本地化鍵的文件夾名稱將不同:PT 可以是“pt-PT”或“pt-BR”,西班牙語可以是“es”或“es” -419'(拉丁美洲),這些情況會導致您的應用程序崩潰。

我修改了在 Xcode14 上編譯的最佳答案,刪除了強制解包並在未找到翻譯時返回密鑰:

extension LocalizedStringKey {
    var stringKey: String? {
        Mirror(reflecting: self).children.first(where: { $0.label == "key" })?.value as? String
    }
    
    func stringValue(locale: Locale = .current) -> String? {
        guard let stringKey = self.stringKey else { return nil }
        let language = locale.languageCode
        guard let path = Bundle.main.path(forResource: language, ofType: "lproj") else { return stringKey }
        guard let bundle = Bundle(path: path) else { return stringKey }
        let localizedString = NSLocalizedString(stringKey, bundle: bundle, comment: "")
        return localizedString
    }
}

2022年

  • 在 macOS 12 及更高版本上運行良好。
  • 大多數情況下適用於 macOS 10.15 及更高版本。
import Foundation
import SwiftUI

@available(macOS 10.15, *)
public extension LocalizedStringKey {
    private var keyStr: String {
        return "\(self)".keyFromLocalizedStringKey
    }
    
    func localizedStr(locale: Locale = .current) -> String {
        if #available(macOS 12, *) {
            return String(localized: "\(self.keyStr)")
        } else {
            return String.localizedString(for: self.keyStr, locale: locale)
        }
    }
}

fileprivate extension String {
    static func localizedString(for key: String, locale: Locale = .current) -> String {
            let language = locale.languageCode
            
            guard let path = Bundle.main.path(forResource: language, ofType: "lproj"),
                  let bundle = Bundle(path: path)
            else { return "Failed To Get Localized String" }
            
            let localizedString = NSLocalizedString(key, bundle: bundle, comment: "")
            
            return localizedString
    }
    
    var keyFromLocalizedStringKey: String {
        let comp2 = self.substring(from: 25).components(separatedBy:"\", hasFormatting")
        
        if comp2.count == 2 {
            return comp2.first!
        }
        
        return "failed to get stringKey"
    }
}

用法:

let lsk = LocalizedStringKey("KEY_NAME_HERE")

let key = lsk.keyStr
let translatedToCurrLocale = lsk.localizedStr()

我目前正在使用它,但我想要一些官方的和有記錄的東西。 部署目標是iOS 14

extension String {
    func slice(start: String, end: String) -> String? {
        (range(of: start)?.upperBound).flatMap { substringFrom in
            (range(of: end, range: substringFrom..<endIndex)?.lowerBound).map { substringTo in
                String(self[substringFrom..<substringTo])
            }
        }
    }
}

extension LocalizedStringKey {
    /// Extracts the string value from LocalizedStringKey.
    var string: String {
        "\(self)".slice(start: "LocalizedStringKey(key: \"", end: "\", hasFormatting") ?? "Bad string"
    }
}

為字符串添加擴展名以讀取本地化語言

extension String {
    func localized() -> String {
        let path = Bundle.main.path(forResource: "your language", ofType: "lproj")!
        if let bundle = Bundle(path: path) {
            let str = bundle.localizedString(forKey: self, value: nil, table: nil)
            return str
        }
        return ""
    }
}

使用 LocalizedStringKey 加載示例代碼

let title: String = "LocalizedStringKey".localized()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM