CHGenerator/WebsiteGenerator/Content/LanguageContainer.swift
Christoph Hagen 14b935249f First version
2022-08-16 10:39:05 +02:00

120 lines
3.3 KiB
Swift

import Foundation
protocol LanguageIdentifiable {
var languageIdentifier: String { get }
var title: String { get }
}
protocol LanguageContainer {
associatedtype LocalizedContainer: LanguageIdentifiable
var languages: [LocalizedContainer] { get }
}
protocol LocalizedMetadataContainer {
associatedtype MetadataType: LanguageContainer
var metadata: MetadataType { get }
func hasContent(for language: String) -> Bool
}
// MARK: Default implementations
extension LocalizedMetadataContainer {
func hasContent(for language: String) -> Bool {
true
}
}
// MARK: Extensions
extension LocalizedMetadataContainer {
func localized(for language: String) -> MetadataType.LocalizedContainer {
metadata.localized(for: language)
}
/**
The localized title of the element.
This title is used as large text in overview pages, or as the `<h1>` title on pages. If no separate link preview title is specified using a localized `linkPreview.title`, then this value is also used for link previews.
*/
func title(for language: String) -> String {
localized(for: language).title
}
func nextLanguage(for languageIdentifier: String) -> String? {
let langs = metadata.languages.map { $0.languageIdentifier }
guard let index = langs.firstIndex(of: languageIdentifier) else {
return nil
}
for i in 1..<langs.count {
let next = langs[(index + i) % langs.count]
guard hasContent(for: next) else {
continue
}
guard next != languageIdentifier else {
return nil
}
return next
}
return nil
}
}
extension LanguageContainer {
var languageIdentifiers: [String] {
languages.map { $0.languageIdentifier }
}
#warning("Throw better error for missing language")
func localized(for language: String) -> LocalizedContainer {
languages.first { $0.languageIdentifier == language }!
}
/**
The localized title of the element.
This title is used as large text in overview pages, or as the `<h1>` title on pages. If no separate link preview title is specified using a localized `linkPreview.title`, then this value is also used for link previews.
*/
func title(for language: String) -> String {
localized(for: language).title
}
}
extension LocalizedMetadataContainer where Self: SiteElement, Self.MetadataType.LocalizedContainer: LinkPreviewMetadataProvider {
private func linkPreviewImageFileName(for language: String) -> String? {
if let fileName = localized(for: language).linkPreview?.image {
return fileName
}
// Check for the existence of a localized thumbnail
let fileName = Self.thumbnailFileNameLocalized(for: language)
if inputFolder.appendingPathComponent(fileName).exists {
return fileName
}
let defaultThumbnail = Self.defaultThumbnailFileName
if inputFolder.appendingPathComponent(defaultThumbnail).exists {
return defaultThumbnail
}
return nil
}
func linkPreviewImage(for language: String) -> String? {
guard let fileName = linkPreviewImageFileName(for: language) else {
return nil
}
return "/\(path)/\(fileName)"
}
}