diff --git a/Sources/SkipBuild/Commands/SkipstoneCommand.swift b/Sources/SkipBuild/Commands/SkipstoneCommand.swift index e2b07ee5..7729e6d5 100644 --- a/Sources/SkipBuild/Commands/SkipstoneCommand.swift +++ b/Sources/SkipBuild/Commands/SkipstoneCommand.swift @@ -1122,7 +1122,7 @@ struct SkipstoneCommand: BuildPluginOptionsCommand, StreamingCommand { } } - /// Links resources in "process" mode, flattening the hierarchy and performing special processing for .xcstrings and other files + /// Links resources in "process" mode, flattening the hierarchy and performing special processing for .strings, .stringsdict, .xcstrings and other files func linkProcessResources(entry: ResourceEntry, resourcesBasePath: AbsolutePath) throws { for resourceFile in entry.urls.map(\.path).sorted() { let resourceFileCanonical = (resourceFile as NSString).standardizingPath @@ -1148,8 +1148,10 @@ struct SkipstoneCommand: BuildPluginOptionsCommand, StreamingCommand { trace("skipping resource linking for buildSrc/") } else if isCMakeProject { trace("skipping resource linking for CMake project") + } else if sourcePath.extension == "strings" || sourcePath.extension == "stringsdict" { + try copyStrings(resourceSourceURL: resourceSourceURL, sourcePath: sourcePath) } else if sourcePath.extension == "xcstrings" { - try convertStrings(resourceSourceURL: resourceSourceURL, sourcePath: sourcePath) + try convertXCStrings(resourceSourceURL: resourceSourceURL, sourcePath: sourcePath) //} else if sourcePath.extension == "xcassets" { // TODO: convert various assets into Android res/ folder } else { // non-processed resources are just linked directly from the package @@ -1167,7 +1169,23 @@ struct SkipstoneCommand: BuildPluginOptionsCommand, StreamingCommand { } } - func convertStrings(resourceSourceURL: URL, sourcePath: AbsolutePath) throws { + func copyStrings(resourceSourceURL: URL, sourcePath: AbsolutePath) throws { + // process the .strings / .stringsdict in the same way that Xcode does: read the FILE and use the content to synthesize a LANG.lproj/TABLENAME.EXTENSION file + let content = try Data(contentsOf: resourceSourceURL) + + let localeId = sourcePath.parentDirectory.basenameWithoutExt + let lprojFolder = resourcesBasePath.appending(component: localeId + ".lproj") + let locBase = sourcePath.basenameWithoutExt + + try fs.createDirectory(lprojFolder, recursive: true) + + let localizableResource = try RelativePath(validating: locBase + "." + sourcePath.extension!) + let localizableResourcePath = lprojFolder.appending(localizableResource) + info("create \(localizableResource.pathString) from \(sourcePath.pathString)", sourceFile: localizableResourcePath.sourceFile) + try writeChanges(tag: localizableResource.pathString, to: localizableResourcePath, contents: content, readOnly: false) + } + + func convertXCStrings(resourceSourceURL: URL, sourcePath: AbsolutePath) throws { // process the .xcstrings in the same way that Xcode does: parse the JSON and use the localizations keys to synthesize a LANG.lproj/TABLENAME.strings file let xcstrings = try JSONDecoder().decode(LocalizableStringsDictionary.self, from: Data(contentsOf: resourceSourceURL)) let defaultLanguage = xcstrings.sourceLanguage