@@ -8,6 +8,7 @@ import Cocoa
88import CSV
99import FileKit
1010import UniformTypeIdentifiers
11+ import LocalizableStringsTools
1112
1213private let localizableFileName = " Localizable.strings "
1314private let keyTitles = [ " key " , " Key " , " KEY " ]
@@ -21,10 +22,18 @@ class HomeController: NSViewController {
2122 @IBOutlet weak var selectCSVButton : NSButton !
2223 @IBOutlet weak var setStorageButton : NSButton !
2324
24- @IBOutlet weak var preViewButton : NSButton !
2525 @IBOutlet weak var parseButton : NSButton !
2626
27+ // 自动插入
28+
29+ @IBOutlet weak var projectTextField : NSTextField !
30+
31+ @IBOutlet weak var stringsFileNameTextField : NSTextField !
32+ @IBOutlet weak var insertKeyTextField : NSTextField !
33+
34+
2735 var localPath : URL ?
36+ let csvHelper : CSVHelper = CSVHelper ( )
2837
2938 override func viewDidLoad( ) {
3039 super. viewDidLoad ( )
@@ -100,6 +109,127 @@ class HomeController: NSViewController {
100109 localPath = url
101110 savePathField. stringValue = url. absoluteString. urlDecoded ( ) . removeFileHeader ( )
102111 }
112+ @IBAction func parseAutoInsertButtonTapped( _ sender: NSButton ) {
113+ // 解析 excel 自动插入到对应语种的 strings 文件中
114+ do {
115+ let stringsFilePaths = try findPaths ( )
116+
117+ } catch let error as HandleError {
118+ showAlert ( title: " 自动导入异常 " , msg: error. message)
119+ } catch {
120+
121+ }
122+ }
123+ @IBAction func TestButtonTapped( _ sender: NSButton ) {
124+ // 临时测试
125+ let path = " /Users/pandaeye/Documents/SupportFramwork/Translator/Translator/Resources/en.lproj/Test.strings "
126+ let key = " key4 " ;
127+ guard let url = openPanel. url else {
128+ showAlert ( title: Localized . failedToOpenFile)
129+ return
130+ }
131+ do {
132+ let csvReader = try csvHelper. csvReader ( url: url)
133+ let result = try csvHelper. parseCSVFile ( reader: csvReader)
134+ if !result. errorInfo. isEmpty {
135+ Log . shared. error ( result. errorInfo. writable. componentsJoined ( by: " \n " ) )
136+ }
137+ if result. models. isEmpty {
138+ showAlert ( title: " 读取CSV成功,但未解析都符合数据 " )
139+ } else {
140+ // TODO: 匹配对应语种
141+ let isSuccess = insertOtherStrings ( result. models. last!, to: path, after: key)
142+ }
143+ } catch let error as HandleError {
144+ showAlert ( title: " 读取CSV文件失败 error: \( error. message) " )
145+ } catch {
146+ showAlert ( title: " 读取CSV文件失败 " )
147+ }
148+
149+ }
150+ func insertOtherStrings( _ stringsFileModel: LanguageFileModel , to filePath: String , after key: String ) -> Bool {
151+ guard !stringsFileModel. items. isEmpty, !filePath. isEmpty, !key. isEmpty else {
152+ return false
153+ }
154+ // 插入指定位置
155+ guard let text = try ? String ( contentsOfFile: filePath, encoding: . utf8) else {
156+ Log . shared. error ( " 自动插入,读取文件失败 " )
157+ return false
158+ }
159+ // 从路径读取 strings 文件并解析
160+ let result = LocalizableStringsParser . parse ( string: text, locale: filePath)
161+ let filter = result. localizableStrings. filter { $0. key == key }
162+ guard filter. count == 1 , let first = filter. first else {
163+ Log . shared. error ( " 自动插入,找不到key,或者找到多个key, keyCount: \( filter. count) " )
164+ return false
165+ }
166+ // 检查是否包含这个 key,
167+ var textHaveKey = false
168+ for item in stringsFileModel. items {
169+ let key = item. key
170+ let filterKey = result. localizableStrings. filter { temp in
171+ temp. key == key
172+ }
173+ if filterKey. isEmpty {
174+ textHaveKey = true
175+ }
176+ }
177+ if ( textHaveKey) {
178+ Log . shared. error ( " 自动插入,将要插入的文件已经包含该 相同的key \( stringsFileModel. items) " )
179+ return false
180+ }
181+ // 找到原来strings 匹配的 的key value 组合值, 必须要按照这个格式才能匹配。
182+ let subStr = " \" \( first. key) \" = \" \( first. value) \" ; "
183+ // 找到插入位置
184+
185+ if #available( macOS 13 . 0 , * ) {
186+ do {
187+ let indexResult = try LocalizableStringsUtils . findInsertIndex ( allStrings: text , subStr: subStr)
188+ // 替换到指定位置之后 \n + 需要插入的内容。
189+ guard let index = indexResult. index else {
190+ Log . shared. error ( " 自动插入,找不到插入点 " )
191+ return false
192+ }
193+ let insertIndexHave2EmptyLine = indexResult. insertIndexHave2EmptyLine
194+ var willInsertText = " \n "
195+ for item in stringsFileModel. items {
196+ if let desc = item. desc, !desc. isEmpty {
197+ willInsertText += " \n // \( desc) "
198+ }
199+ willInsertText += " \n \" \( item. key) \" = \" \( item. value) \" ; "
200+ }
201+ if !insertIndexHave2EmptyLine {
202+ willInsertText = willInsertText + " \n \n "
203+ }
204+ var allStrings = text
205+ allStrings. insert ( contentsOf: willInsertText, at: index)
206+ // 删除文件,重新写入
207+ do {
208+ try FileManager . default. removeItem ( atPath: filePath)
209+ try allStrings. write ( toFile: filePath, atomically: true , encoding: . utf8)
210+ return true
211+ } catch let error {
212+ Log . shared. error ( " 自动插入,文件删除或者写入失败: \( error) " )
213+ return false
214+ }
215+ } catch let error as LocalizableStringsFindInsertIndexError {
216+ switch error {
217+ case . multipleMatches:
218+ Log . shared. error ( " 自动插入,匹配到多个,无法自动插入 subxStr: \( subStr) " )
219+ case . noMatch:
220+ Log . shared. error ( " 自动插入,找不到匹配项,无法自动插入 subxStr: \( subStr) " )
221+ case . multiLineComment:
222+ Log . shared. error ( " 自动插入,插入点后存在多行注释 \\ * \n */,无法自动插入 subxStr: \( subStr) " )
223+ }
224+ return false
225+ } catch {
226+ return false
227+ }
228+ } else {
229+ Log . shared. error ( " 自动插入,macOS 版本不支持, 应该大于 13.0 " )
230+ return false
231+ }
232+ }
103233
104234 /// MARK: - Lazy
105235 lazy var openPanel : NSOpenPanel = {
@@ -180,6 +310,8 @@ extension HomeController {
180310 return
181311 }
182312 paths. append ( localizablePath)
313+ var fileModel = LanguageFileModel ( )
314+ fileModel. languageName = title. removeBraces ( ) ?? " "
183315 }
184316
185317 try " struct Localized { \n " |>> swiftFile
@@ -385,7 +517,7 @@ extension HomeController {
385517 if #available( macOS 13 . 0 , * ) {
386518 pathStr = item. replacing ( " / \( localizableFileName) " , with: " " , maxReplacements: 1 )
387519 } else {
388-
520+ showAlert ( title : " macOS 版本过低,应该大于 13.0 " )
389521 }
390522 guard !pathStr. isEmpty else {
391523 return
@@ -400,7 +532,35 @@ extension HomeController {
400532 }
401533 }
402534}
403-
535+ // 自动插入
536+ extension HomeController {
537+ func findPaths( ) throws -> [ Path ] {
538+ let projectPath = projectTextField. stringValue. trimmingCharacters ( in: . whitespaces)
539+ let stringsFileName = stringsFileNameTextField. stringValue. trimmingCharacters ( in: . whitespaces)
540+ let path = Path ( projectPath)
541+ let stringsFilePaths = path. children ( ) . compactMap { item in
542+ if item. fileName. contains ( " .lproj " ) { // 判断是否是 lproj 文件夹
543+ let filterFiles = item. children ( ) . filter { path in
544+ // 不是目录,且包含指定问价名
545+ !path. isDirectoryFile && path. fileName. contains ( stringsFileName) ;
546+ }
547+ return filterFiles. first
548+ } else {
549+ return nil
550+ }
551+ }
552+ if projectPath. isEmpty {
553+ throw HandleError ( message: " 路径不能为空 " ) ;
554+ }
555+ if stringsFileName. isEmpty {
556+ throw HandleError ( message: " strings文件名不能为空 " ) ;
557+ }
558+ if stringsFilePaths. isEmpty {
559+ throw HandleError ( message: " 找不目标文件 " ) ;
560+ }
561+ return stringsFilePaths
562+ }
563+ }
404564
405565extension HomeController {
406566
0 commit comments