mirror of
https://github.com/Finb/Bark.git
synced 2025-12-08 21:36:01 +00:00
优化查找未使用翻译的脚本
This commit is contained in:
parent
1e340c6578
commit
df9e971fba
@ -140,7 +140,6 @@
|
||||
06C2CF232685B88D0034B127 /* TextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C2CF222685B88D0034B127 /* TextCell.swift */; };
|
||||
06C2CF252685BDB80034B127 /* SpacerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C2CF242685BDB80034B127 /* SpacerCell.swift */; };
|
||||
06C5952D2480E3F8006B98F3 /* LabelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5952C2480E3F8006B98F3 /* LabelCell.swift */; };
|
||||
06C5952F248107F5006B98F3 /* iCloudStatusCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */; };
|
||||
06C5953124811392006B98F3 /* ArchiveSettingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5953024811392006B98F3 /* ArchiveSettingCell.swift */; };
|
||||
06C595362481160F006B98F3 /* BKLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C595352481160F006B98F3 /* BKLabel.swift */; };
|
||||
06CF784721C7A50300A052D7 /* NotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 06CF784021C7A50300A052D7 /* NotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
@ -380,7 +379,6 @@
|
||||
06C2CF222685B88D0034B127 /* TextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextCell.swift; sourceTree = "<group>"; };
|
||||
06C2CF242685BDB80034B127 /* SpacerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpacerCell.swift; sourceTree = "<group>"; };
|
||||
06C5952C2480E3F8006B98F3 /* LabelCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCell.swift; sourceTree = "<group>"; };
|
||||
06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iCloudStatusCell.swift; sourceTree = "<group>"; };
|
||||
06C5953024811392006B98F3 /* ArchiveSettingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveSettingCell.swift; sourceTree = "<group>"; };
|
||||
06C5953224811505006B98F3 /* ArchiveSettingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveSettingManager.swift; sourceTree = "<group>"; };
|
||||
06C595352481160F006B98F3 /* BKLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BKLabel.swift; sourceTree = "<group>"; };
|
||||
@ -505,7 +503,6 @@
|
||||
0603706820E1F89500F4CA05 /* PreviewCardCell.swift */,
|
||||
064CAB9D256BE9090018155C /* PreviewCardCellViewModel.swift */,
|
||||
06C5952C2480E3F8006B98F3 /* LabelCell.swift */,
|
||||
06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */,
|
||||
06C5953024811392006B98F3 /* ArchiveSettingCell.swift */,
|
||||
06BBB8BB2567B3AD0076F63E /* ArchiveSettingCellViewModel.swift */,
|
||||
060481EF250F51CA00BC9799 /* SoundCell.swift */,
|
||||
@ -1279,7 +1276,6 @@
|
||||
064CABA6256BE9510018155C /* PreviewModel.swift in Sources */,
|
||||
0637FA7E20E0969800E80174 /* Client.swift in Sources */,
|
||||
0661A545204FDA4100965E4E /* HomeViewController.swift in Sources */,
|
||||
06C5952F248107F5006B98F3 /* iCloudStatusCell.swift in Sources */,
|
||||
06BBB88725650C6C0076F63E /* ArchiveSettingManager.swift in Sources */,
|
||||
065BE44B2563D8E1002A8CA4 /* Reusable.swift in Sources */,
|
||||
0637FA8620E0AB6600E80174 /* UIColor+Extension.swift in Sources */,
|
||||
|
||||
@ -291,35 +291,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"available" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Enabled"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "有効"
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Etkin"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "已开启"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"badge" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@ -929,35 +900,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyCrashLog" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Copy Crash Log"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "クラッシュログをコピー"
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Copy Crash Log"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "复制闪退日志"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"copyExample" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@ -1016,64 +958,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"crashContent" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "You need to restart the app! \n\nIf the problem persists, you can try to check the FAQ to see if there is a solution.\nhttps://bark.day.app/#/en-us/faq\n\nBark will not upload any logs! If you need help (or wish to help the developer fix the crash), you can also send the crash log to me, and I will contact you as soon as possible.\n\nEmail: to@day.app\nTelegram: https://t.me/joinchat/OsCbLzovUAE0YjY1\nGithub Issue: https://github.com/Finb/Bark/issues\n"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "問題が解決しない場合は、FAQを確認して解決策があるかどうかを確認できます。 \nhttps://bark.day.app/#/en-us/faq \n\nBarkはログをアップロードしません!助けが必要な場合(または開発者がクラッシュを修正するのを手伝いたい場合)、クラッシュログを私に送ってください。できるだけ早く連絡します。 \n\nメール: to@day.app \nTelegram: https://t.me/joinchat/OsCbLzovUAE0YjY1 \nGithub Issue: https://github.com/Finb/Bark/issues "
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Uygulamayı yeniden başlatmanız gerekiyor!\n\nSorun devam ederse bir çözüm olup olmadığını görmek için SSS'yi kontrol etmeyi deneyebilirsiniz.\nhttps://bark.day.app/#/en-us/faq\n\nBark herhangi bir günlük yüklemeyecek! Yardıma ihtiyacınız varsa (veya geliştiricinin çökmeyi düzeltmesine yardım etmek istiyorsanız), kilitlenme günlüğünü bana da gönderebilirsiniz; mümkün olan en kısa sürede sizinle iletişime geçeceğim.\n\nE-posta: to@day.app\nTelgraf: https://t.me/joinchat/OsCbLzovUAE0YjY1\nGithub Sorunları: https://github.com/Finb/Bark/issues"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "您需要重启APP!\n\n如还是提示闪退,可以尝试查看FAQ看是否有解决办法\nhttps://bark.day.app/#/faq\n\nBark 不会上传任何日志!如您需帮助(或帮助作者修复闪退),可以将闪退日志手动复制发送给我,我会尽快与您联系。\n\n邮箱: to@day.app\nTelegram: https://t.me/joinchat/OsCbLzov\nGithub Issue: https://github.com/Finb/Bark/issues\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"crashed" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Crashed!"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "クラッシュしました!"
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "düştü!"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "好像闪退了!"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"criticalAlert" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@ -2001,35 +1885,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"iCloudSatatus" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "iCloud Sync"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "iCloud同期"
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "iCloud Senkronizasyonu"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "iCloud 同步"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"imageParameter" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
@ -3132,35 +2987,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"restricted" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Disabled"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "無効"
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Devre Dışı"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "未开启"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ringtone" : {
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
|
||||
@ -58,7 +58,7 @@ class MessageListViewController: BaseViewController<MessageListViewModel> {
|
||||
btn.setImage(UIImage(named: "group_collapse")?.withRenderingMode(.alwaysTemplate), for: .selected)
|
||||
btn.imageView?.tintColor = BKColor.black
|
||||
btn.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
|
||||
btn.accessibilityLabel = "toggle"
|
||||
btn.accessibilityLabel = "toggle".localized
|
||||
return UIBarButtonItem(customView: btn)
|
||||
}()
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ class MessageSettingsViewController: BaseViewController<MessageSettingsViewModel
|
||||
tableView.separatorColor = BKColor.grey.lighten3
|
||||
tableView.backgroundColor = BKColor.background.primary
|
||||
tableView.register(LabelCell.self, forCellReuseIdentifier: "\(LabelCell.self)")
|
||||
tableView.register(iCloudStatusCell.self, forCellReuseIdentifier: "\(iCloudStatusCell.self)")
|
||||
tableView.register(ArchiveSettingCell.self, forCellReuseIdentifier: "\(ArchiveSettingCell.self)")
|
||||
tableView.register(DetailTextCell.self, forCellReuseIdentifier: "\(DetailTextCell.self)")
|
||||
tableView.register(MutableTextCell.self, forCellReuseIdentifier: "\(MutableTextCell.self)")
|
||||
@ -178,10 +177,6 @@ class MessageSettingsViewController: BaseViewController<MessageSettingsViewModel
|
||||
cell.textLabel?.text = text
|
||||
return cell
|
||||
}
|
||||
case .iCloudStatus:
|
||||
if let cell = tableView.dequeueReusableCell(withIdentifier: "\(iCloudStatusCell.self)") {
|
||||
return cell
|
||||
}
|
||||
case .backup(let viewModel):
|
||||
if let cell = tableView.dequeueReusableCell(withIdentifier: "\(MutableTextCell.self)") as? MutableTextCell {
|
||||
cell.textLabel?.textColor = BKColor.blue.darken1
|
||||
|
||||
@ -227,8 +227,6 @@ class MessageSettingsViewModel: ViewModel, ViewModelType {
|
||||
enum MessageSettingItem {
|
||||
// 普通标题标签
|
||||
case label(text: String)
|
||||
// iCloud 状态
|
||||
case iCloudStatus
|
||||
// 默认保存
|
||||
case archiveSetting(viewModel: ArchiveSettingCellViewModel)
|
||||
// 带 详细按钮的 文本cell
|
||||
|
||||
@ -18,7 +18,7 @@ class PreviewCardCell: BaseTableViewCell<PreviewCardCellViewModel> {
|
||||
|
||||
let copyButton: IconButton = {
|
||||
let button = IconButton(image: UIImage(named: "baseline_file_copy_white_24pt"), tintColor: BKColor.grey.base)
|
||||
button.accessibilityLabel = "copy".localized
|
||||
button.accessibilityLabel = "Copy".localized
|
||||
return button
|
||||
}()
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ import UIKit
|
||||
class SoundCell: BaseTableViewCell<SoundCellViewModel> {
|
||||
let copyButton: IconButton = {
|
||||
let button = IconButton(image: UIImage(named: "baseline_file_copy_white_24pt"), tintColor: BKColor.grey.base)
|
||||
button.accessibilityLabel = "copy".localized
|
||||
button.accessibilityLabel = "Copy".localized
|
||||
return button
|
||||
}()
|
||||
|
||||
|
||||
@ -1,40 +0,0 @@
|
||||
//
|
||||
// iCloudStatusCell.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/5/29.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import CloudKit
|
||||
import UIKit
|
||||
|
||||
class iCloudStatusCell: UITableViewCell {
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: .value1, reuseIdentifier: reuseIdentifier)
|
||||
self.selectionStyle = .none
|
||||
self.backgroundColor = BKColor.background.secondary
|
||||
self.textLabel?.text = "iCloudStatus".localized
|
||||
self.detailTextLabel?.text = ""
|
||||
self.detailTextLabel?.textColor = BKColor.grey.darken2
|
||||
CKContainer.default().accountStatus { status, _ in
|
||||
dispatch_sync_safely_main_queue {
|
||||
switch status {
|
||||
case .available:
|
||||
self.detailTextLabel?.text = "available".localized
|
||||
case .noAccount, .restricted, .temporarilyUnavailable:
|
||||
self.detailTextLabel?.text = "restricted".localized
|
||||
case .couldNotDetermine:
|
||||
self.detailTextLabel?.text = "unknown".localized
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,9 @@
|
||||
Bark项目本地化字符串分析工具
|
||||
|
||||
这个脚本会扫描整个Bark项目,找出 Localizable.xcstrings 中未使用的翻译key。
|
||||
检测方式:任何在双引号内且在本地化文件中定义的字符串都会被认为是被使用的key。
|
||||
检测方式:
|
||||
1. 任何在双引号内且在本地化文件中定义的字符串都会被认为是被使用的key
|
||||
2. "key".localized 和 "key".localized(with:) 模式
|
||||
|
||||
使用方法:
|
||||
python3 check_unused_translations.py
|
||||
@ -45,7 +47,7 @@ class BarkLocalizationAnalyzer:
|
||||
def extract_used_keys_from_file(self, file_path, all_defined_keys):
|
||||
"""从Swift文件中提取使用的本地化key"""
|
||||
used_keys = set()
|
||||
nslocalizedstring_keys = set() # 新增:专门收集NSLocalizedString中的key
|
||||
localized_keys = set() # 收集.localized中的key
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
@ -61,26 +63,27 @@ class BarkLocalizationAnalyzer:
|
||||
if quoted_string and quoted_string in all_defined_keys:
|
||||
used_keys.add(quoted_string)
|
||||
|
||||
# 方法2: 专门查找 NSLocalizedString("key") 模式
|
||||
nslocalizedstring_patterns = [
|
||||
r'NSLocalizedString\s*\(\s*"([^"]+)"\s*\)', # NSLocalizedString("key")
|
||||
r'NSLocalizedString\s*\(\s*\'([^\']+)\'\s*\)', # NSLocalizedString('key')
|
||||
r'NSLocalizedString\s*\(\s*@"([^"]+)"\s*\)', # NSLocalizedString(@"key")
|
||||
# 方法2: 查找 "key".localized 和 "key".localized(with:) 模式
|
||||
localized_patterns = [
|
||||
r'"([^"]+)"\s*\.\s*localized\b', # "key".localized
|
||||
r'"([^"]+)"\s*\.\s*localized\s*\(\s*with:', # "key".localized(with:
|
||||
r'\'([^\']+)\'\s*\.\s*localized\b', # 'key'.localized
|
||||
r'\'([^\']+)\'\s*\.\s*localized\s*\(\s*with:', # 'key'.localized(with:
|
||||
]
|
||||
|
||||
for pattern in nslocalizedstring_patterns:
|
||||
for pattern in localized_patterns:
|
||||
matches = re.findall(pattern, content, re.MULTILINE | re.DOTALL)
|
||||
for match in matches:
|
||||
match = match.strip()
|
||||
if match:
|
||||
nslocalizedstring_keys.add(match) # 收集所有NSLocalizedString中的key
|
||||
localized_keys.add(match) # 收集所有.localized中的key
|
||||
if match in all_defined_keys:
|
||||
used_keys.add(match)
|
||||
|
||||
except Exception as e:
|
||||
print(f"⚠️ 读取文件失败 {file_path}: {e}")
|
||||
|
||||
return used_keys, nslocalizedstring_keys
|
||||
return used_keys, localized_keys
|
||||
|
||||
def find_all_used_keys(self, all_defined_keys):
|
||||
"""在整个项目中查找所有使用的本地化 key"""
|
||||
@ -90,20 +93,20 @@ class BarkLocalizationAnalyzer:
|
||||
|
||||
# 提取使用的key
|
||||
used_keys = set()
|
||||
all_nslocalizedstring_keys = set() # 新增:收集所有NSLocalizedString中的key
|
||||
all_localized_keys = set() # 收集所有.localized中的key
|
||||
files_with_keys = 0
|
||||
|
||||
for file_path in swift_files:
|
||||
file_keys, nsl_keys = self.extract_used_keys_from_file(file_path, all_defined_keys)
|
||||
file_keys, localized_keys = self.extract_used_keys_from_file(file_path, all_defined_keys)
|
||||
if file_keys:
|
||||
files_with_keys += 1
|
||||
used_keys.update(file_keys)
|
||||
all_nslocalizedstring_keys.update(nsl_keys)
|
||||
all_localized_keys.update(localized_keys)
|
||||
|
||||
print(f"🔑 在 {files_with_keys} 个文件中找到 {len(used_keys)} 个使用的key")
|
||||
|
||||
# 计算在NSLocalizedString中使用但未在本地化文件中定义的key
|
||||
missing_in_localization = all_nslocalizedstring_keys - all_defined_keys
|
||||
# 计算在代码中使用但未在本地化文件中定义的key
|
||||
missing_in_localization = all_localized_keys - all_defined_keys
|
||||
|
||||
return used_keys, files_with_keys, missing_in_localization
|
||||
|
||||
@ -160,7 +163,7 @@ class BarkLocalizationAnalyzer:
|
||||
print(f"使用中的key数量: {result['used_keys']}")
|
||||
print(f"未使用的key数量: {result['unused_keys']}")
|
||||
print(f"缺失的key数量: {result['missing_keys']} (代码中使用但未定义)")
|
||||
print(f"NSLocalizedString中缺失的key: {result['missing_in_localization']} 个")
|
||||
print(f"代码中缺失的key: {result['missing_in_localization']} 个")
|
||||
|
||||
if result['unused_keys_list']:
|
||||
print(f"\n🗑️ 未使用的翻译key ({result['unused_keys']} 个):")
|
||||
@ -173,7 +176,7 @@ class BarkLocalizationAnalyzer:
|
||||
print(f" {i:2d}. {key}")
|
||||
|
||||
if result['missing_in_localization_list']:
|
||||
print(f"\n❌ NSLocalizedString中使用但未在Localizable.xcstrings中定义的key ({result['missing_in_localization']} 个):")
|
||||
print(f"\n❌ 代码中使用但未在Localizable.xcstrings中定义的key ({result['missing_in_localization']} 个):")
|
||||
for i, key in enumerate(result['missing_in_localization_list'], 1):
|
||||
print(f" {i:2d}. {key}")
|
||||
|
||||
@ -210,7 +213,7 @@ def main():
|
||||
if result['missing_keys'] > 0:
|
||||
print(f" - 为 {result['missing_keys']} 个缺失的key添加翻译")
|
||||
if result['missing_in_localization'] > 0:
|
||||
print(f" - 为 {result['missing_in_localization']} 个NSLocalizedString中的key添加本地化定义")
|
||||
print(f" - 为 {result['missing_in_localization']} 个代码中使用的key添加本地化定义")
|
||||
|
||||
print(" - 检查是否有动态构建的key名称(脚本可能无法检测)")
|
||||
print(" - 手动检查Storyboard/XIB文件中的硬编码字符串")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user