diff --git a/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift b/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift index 952ac9cc8..d1016b78e 100644 --- a/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift +++ b/Sources/SwiftDocC/Model/Rendering/RenderNodeTranslator.swift @@ -1852,21 +1852,30 @@ public struct RenderNodeTranslator: SemanticVisitor { private func variants(for documentationNode: DocumentationNode) -> [RenderNode.Variant] { let generator = PresentationURLGenerator(context: context, baseURL: bundle.baseURL) - var allVariants: [SourceLanguage: [ResolvedTopicReference]] = Dictionary(uniqueKeysWithValues: documentationNode.availableSourceLanguages.map { ($0, [identifier]) }) + func mapSourceLanguageToVariants(identifier: ResolvedTopicReference, sourceLanguages: Set) -> [(SourceLanguage, [ResolvedTopicReference])] { + sourceLanguages.map { ($0, [identifier]) } + } + + var allVariants: [SourceLanguage: [ResolvedTopicReference]] = Dictionary( + mapSourceLanguageToVariants(identifier: identifier, sourceLanguages: documentationNode.availableSourceLanguages) + ) { value1, value2 in value1 + value2 } // Apply alternate representations - documentationNode.metadata?.alternateRepresentations.forEach { alternateRepresentation in - // Only counterparts which were able to be resolved to a reference should be included as an alternate representation. - // Unresolved counterparts can be ignored, as they would have been reported during link resolution. - guard case .resolved(.success(let counterpartReference)) = alternateRepresentation.reference else { - return - } + if let alternateRepresentations = documentationNode.metadata?.alternateRepresentations { + for alternateRepresentation in alternateRepresentations { + // Only alternate representations which were able to be resolved to a reference should be included as an alternate representation. + // Unresolved alternate representations can be ignored, as they would have been reported during link resolution. + guard case .resolved(.success(let alternateRepresentationReference)) = alternateRepresentation.reference else { + continue + } - // Add all of the variants of the counterpart as additional variants for the current symbol - // If the current symbol and its counterpart share source languages, the list of variants for that language will contain multiple symbol references. - // Only the first symbol reference will be respected by Swift-DocC Render. - counterpartReference.sourceLanguages.forEach { - allVariants[$0, default: []].append(counterpartReference) + // Add the language representations of the alternate symbol as additional variants for the current symbol. + // Symbols can only specify custom alternate language representations for languages that the documented symbol doesn't already have a representation for. + // If the current symbol and its custom alternate representation share language representations, the custom language representation is ignored. + allVariants.merge(mapSourceLanguageToVariants( + identifier: alternateRepresentationReference, + sourceLanguages: alternateRepresentationReference.sourceLanguages + )) { value1, value2 in value1 } } }