Added the alternate locales to the Social Card in the Infrastructure package.

This commit is contained in:
2026-09-04 14:36:22 +02:00
parent c8100fd93c
commit f0086ee461
3 changed files with 13 additions and 3 deletions
@@ -7,6 +7,9 @@ public struct SocialCard: Sendable {
// MARK: Properties // MARK: Properties
/// The locales of the card's other language editions, in Open Graph's `language_TERRITORY` form; empty to omit their tags.
public let alternateLocales: [String]
/// The card's share image, or `nil` to omit its tags. /// The card's share image, or `nil` to omit its tags.
public let image: Image? public let image: Image?
@@ -43,6 +46,7 @@ public struct SocialCard: Sendable {
/// - siteName: the name of the site the card belongs to, or `nil` (the default) to omit its tag. /// - siteName: the name of the site the card belongs to, or `nil` (the default) to omit its tag.
/// - locale: the locale of the card's text, ideally in Open Graph's `language_TERRITORY` form (e.g. `en_US`), or `nil` (the default) /// - locale: the locale of the card's text, ideally in Open Graph's `language_TERRITORY` form (e.g. `en_US`), or `nil` (the default)
/// to omit its tag. /// to omit its tag.
/// - alternateLocales: the locales the card's page is also published in, in the same form; empty (the default) to omit their tags.
/// - image: the card's share image, or `nil` (the default) to omit its tags. /// - image: the card's share image, or `nil` (the default) to omit its tags.
/// - type: the Open Graph type of the object the card describes. Defaults to `website`. /// - type: the Open Graph type of the object the card describes. Defaults to `website`.
/// - style: the layout a Twitter card scraper gives the card. Defaults to ``Style/summaryLargeImage``. /// - style: the layout a Twitter card scraper gives the card. Defaults to ``Style/summaryLargeImage``.
@@ -52,10 +56,12 @@ public struct SocialCard: Sendable {
url: String? = nil, url: String? = nil,
siteName: String? = nil, siteName: String? = nil,
locale: String? = nil, locale: String? = nil,
alternateLocales: [String] = [],
image: Image? = nil, image: Image? = nil,
type: String = "website", type: String = "website",
style: Style = .summaryLargeImage style: Style = .summaryLargeImage
) { ) {
self.alternateLocales = alternateLocales
self.image = image self.image = image
self.locale = locale self.locale = locale
self.siteName = siteName self.siteName = siteName
@@ -68,8 +74,8 @@ public struct SocialCard: Sendable {
// MARK: Computed // MARK: Computed
/// The card's meta tags, in a stable order: the Open Graph type, site name, title, description, URL, and locale, then the image group, and /// The card's meta tags, in a stable order: the Open Graph type, site name, title, description, URL, locale, and alternate locales, then the
/// the Twitter card style last. A tag whose fact the card does not carry is left out. /// image group, and the Twitter card style last. A tag whose fact the card does not carry is left out.
public var tags: [Tag] { public var tags: [Tag] {
let tags: [Tag?] = [ let tags: [Tag?] = [
Tag(type, name: .type), Tag(type, name: .type),
@@ -78,7 +84,7 @@ public struct SocialCard: Sendable {
summary.map { Tag($0, name: .description) }, summary.map { Tag($0, name: .description) },
url.map { Tag($0, name: .url) }, url.map { Tag($0, name: .url) },
locale.map { Tag($0, name: .locale) }, locale.map { Tag($0, name: .locale) },
] + (image?.tags ?? []) + [ ] + alternateLocales.map { Tag($0, name: .localeAlternate) } + (image?.tags ?? []) + [
Tag(style.rawValue, name: .twitter), Tag(style.rawValue, name: .twitter),
] ]
@@ -60,6 +60,7 @@ extension SocialCard.Tag {
case imageWidth = "og:image:width" case imageWidth = "og:image:width"
/// The `og:locale` tag, carrying the locale of the card's text. /// The `og:locale` tag, carrying the locale of the card's text.
case locale = "og:locale" case locale = "og:locale"
case localeAlternate = "og:locale:alternate"
/// The `og:site_name` tag, carrying the name of the site the card belongs to. /// The `og:site_name` tag, carrying the name of the site the card belongs to.
case siteName = "og:site_name" case siteName = "og:site_name"
/// The `og:title` tag, carrying the card's title. /// The `og:title` tag, carrying the card's title.
@@ -18,6 +18,7 @@ struct SocialCardTests {
url: "https://site.example/", url: "https://site.example/",
siteName: "A Site", siteName: "A Site",
locale: "en", locale: "en",
alternateLocales: ["nl_NL", "de_DE"],
image: .init( image: .init(
url: "https://site.example/img/card.png", url: "https://site.example/img/card.png",
width: 2400, width: 2400,
@@ -33,6 +34,8 @@ struct SocialCardTests {
.init("A summary.", name: .description), .init("A summary.", name: .description),
.init("https://site.example/", name: .url), .init("https://site.example/", name: .url),
.init("en", name: .locale), .init("en", name: .locale),
.init("nl_NL", name: .localeAlternate),
.init("de_DE", name: .localeAlternate),
.init("https://site.example/img/card.png", name: .image), .init("https://site.example/img/card.png", name: .image),
.init("2400", name: .imageWidth), .init("2400", name: .imageWidth),
.init("1260", name: .imageHeight), .init("1260", name: .imageHeight),