[英]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
}
}
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.