You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS开发:如何读取Localizable.strings并获取所有翻译键

如何读取Localizable.strings文件的全部内容获取所有翻译键

我来帮你搞定这个问题!你之前的代码找不到目标文件,主要是因为路径的写法不对——Bundle.main.path(forResource:)的第一个参数应该是纯文件名,不能带路径前缀。咱们一步步修正,同时给你两种高效获取所有翻译键的方案:


第一步:正确获取对应语言的Bundle

先确保能拿到目标语言(比如西班牙语es)的语言包Bundle,这是后续操作的基础:

guard let languageBundlePath = Bundle.main.path(forResource: "es", ofType: "lproj"),
      let languageBundle = Bundle(path: languageBundlePath) else {
    // 处理语言包获取失败的情况
    let alert = UIAlertController(title: "Erreur".localized, message: "语言包未找到".localized, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Ok".localized, style: .cancel))
    self.present(alert, animated: true)
    return
}

方案一:直接加载为字典(最简便)

系统提供了localizedStringDictionary属性,可以直接把Localizable.strings转换成键值对字典,不需要自己解析字符串:

if let localizableDict = languageBundle.localizedStringDictionary {
    // 遍历所有翻译键值对
    for (key, translatedValue) in localizableDict {
        print("翻译键:\(key),对应译文:\(translatedValue)")
    }
} else {
    let alert = UIAlertController(title: "Erreur".localized, message: "Localizable.strings加载失败".localized, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Ok".localized, style: .cancel))
    self.present(alert, animated: true)
}

方案二:读取原始文件并解析(适合自定义处理)

如果你需要处理原始的.strings文件内容(比如保留注释、处理特殊格式),可以先读取文件字符串再手动解析:

// 从语言Bundle中获取Localizable.strings的路径
guard let stringsFilePath = languageBundle.path(forResource: "Localizable", ofType: "strings") else {
    let alert = UIAlertController(title: "Erreur".localized, message: "Localizable.strings未找到".localized, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Ok".localized, style: .cancel))
    self.present(alert, animated: true)
    return
}

do {
    // 读取文件内容
    let fileContent = try String(contentsOfFile: stringsFilePath, encoding: .utf8)
    // 按行分割并解析
    let lines = fileContent.components(separatedBy: .newlines)
    let keyValuePairs = lines.compactMap { line -> (key: String, value: String)? in
        let trimmedLine = line.trimmingCharacters(in: .whitespacesAndNewlines)
        // 跳过空行和注释行
        guard !trimmedLine.isEmpty, !trimmedLine.starts(with: "//") else { return nil }
        // 分割键和值(适配"key" = "value";的标准格式)
        let components = trimmedLine.components(separatedBy: " = ")
        guard components.count == 2 else { return nil }
        // 去除引号和分号,处理转义字符
        let key = components[0].trimmingCharacters(in: CharacterSet(charactersIn: "\"")).replacingOccurrences(of: "\\\"", with: "\"")
        let value = components[1].trimmingCharacters(in: CharacterSet(charactersIn: "\";")).replacingOccurrences(of: "\\\"", with: "\"")
        return (key, value)
    }
    
    // 遍历解析后的键值对
    for pair in keyValuePairs {
        print("翻译键:\(pair.key),对应译文:\(pair.value)")
    }
} catch {
    let alert = UIAlertController(title: "Erreur".localized, message: "无法读取文件:\(error.localizedDescription)".localized, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Ok".localized, style: .cancel))
    self.present(alert, animated: true)
}

为什么你的原始代码会失败?

你之前的代码把lproj路径和文件名拼接后传给path(forResource:),但这个方法的设计逻辑是:第一个参数是文件名,第二个参数是文件类型,不需要手动拼接路径。正确的做法是先拿到语言Bundle,再从这个Bundle内部获取目标文件的路径。

内容的提问来源于stack exchange,提问作者PascalS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 20:23:00