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

多Target的Xcode项目如何实现Localizable.xcstrings本地化继承?

实现多Target本地化继承机制(无需修改现有代码)

核心思路

通过扩展Bundle并重写默认字符串查找逻辑,让系统优先读取Target专属的LocalizableTargetX.xcstrings,未找到时自动 fallback 到通用Localizable.xcstrings,全程不需要修改原有Text()或String(localized:)的调用代码。

具体实现

1. 配置Target专属本地化文件

  • 为每个Target创建对应的本地化文件,比如LocalizableTarget1.xcstrings、LocalizableTarget2.xcstrings,在Xcode的File Inspector中仅勾选对应Target的Membership。
  • 通用的Localizable.xcstrings勾选所有Target,作为全局兜底翻译源。

2. 扩展Bundle重写字符串查找逻辑

创建一个所有Target都包含的Swift文件,添加以下代码:

import Foundation

extension Bundle {
    private static var targetSpecificBundle: Bundle {
        // 根据当前Target名称生成专属本地化表名,可根据实际命名规则调整
        let targetName = Bundle.main.infoDictionary?["CFBundleName"] as? String ?? ""
        let targetTable = "Localizable\(targetName)"
        
        // 尝试加载Target专属本地化文件
        if let path = Bundle.main.path(forResource: targetTable, ofType: "xcstrings"),
           let bundle = Bundle(path: path) {
            return bundle
        }
        // 加载失败则返回主Bundle(使用通用Localizable.xcstrings)
        return Bundle.main
    }
    
    // 重写默认本地化字符串查找方法
    open override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
        // 仅处理默认Localizable表的调用(不修改原有显式指定table的逻辑)
        guard tableName == nil || tableName == "Localizable" else {
            return super.localizedString(forKey: key, value: value, table: tableName)
        }
        
        // 优先查找Target专属翻译
        let targetTranslation = Bundle.targetSpecificBundle.localizedString(forKey: key, value: nil, table: nil)
        if targetTranslation != key {
            return targetTranslation
        }
        
        // 未找到则使用通用翻译
        return super.localizedString(forKey: key, value: value, table: tableName)
    }
}

3. 适配SwiftUI的Text视图

如果项目使用SwiftUI的Text("key")语法,添加以下扩展确保逻辑一致:

import SwiftUI

extension LocalizedStringKey {
    private var rawKey: String {
        String(describing: self).components(separatedBy: "key: \"").last?.replacingOccurrences(of: "\",", with: "") ?? ""
    }
    
    func resolved() -> String {
        Bundle.main.localizedString(forKey: rawKey, value: nil, table: nil)
    }
}

extension Text {
    init(_ key: LocalizedStringKey) {
        self.init(key.resolved())
    }
}

注意事项

  • 确保Target的CFBundleName和专属本地化表的后缀匹配,若命名规则不同,修改targetTable的生成逻辑即可。
  • 切换不同Target运行测试,验证专属翻译优先、通用翻译兜底的逻辑是否生效。
  • 对于显式指定table参数的本地化调用,代码会保留原有系统逻辑,不影响特殊场景的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:43:14