Skip to content

Commit f6c22ae

Browse files
committed
fix residential seo copy fallbacks
1 parent 7aaa06c commit f6c22ae

8 files changed

Lines changed: 63 additions & 13 deletions

File tree

messages/de.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@
430430
"localCommunity": "Lokale Gemeinschaft",
431431
"businessIn": "Unternehmen in {area}",
432432
"localBusiness": "Lokales Unternehmen",
433-
"avatarAlt": "Der Avatar für diesen Eintrag"
433+
"avatarAlt": "Der Avatar für diesen Eintrag",
434+
"privateHostAvatarAlt": "Ein verschwommener Avatar für {name}. Melde dich an, um die vollständigen Informationen zu sehen."
434435
},
435436
"seo": {
436437
"privateHostName": "Privater Host",

messages/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@
430430
"localCommunity": "Local community",
431431
"businessIn": "Business in {area}",
432432
"localBusiness": "Local business",
433-
"avatarAlt": "The avatar for this listing"
433+
"avatarAlt": "The avatar for this listing",
434+
"privateHostAvatarAlt": "A blurred avatar for {name}. Sign in to see their full information."
434435
},
435436
"seo": {
436437
"privateHostName": "Private Host",

messages/es.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@
430430
"localCommunity": "Comunidad local",
431431
"businessIn": "Negocio en {area}",
432432
"localBusiness": "Negocio local",
433-
"avatarAlt": "El avatar de este anuncio"
433+
"avatarAlt": "El avatar de este anuncio",
434+
"privateHostAvatarAlt": "Un avatar difuminado de {name}. Inicia sesión para ver la información completa."
434435
},
435436
"seo": {
436437
"privateHostName": "Anfitrión privado",

messages/fr.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@
430430
"localCommunity": "Communauté locale",
431431
"businessIn": "Commerce à {area}",
432432
"localBusiness": "Commerce local",
433-
"avatarAlt": "L’avatar de cette annonce"
433+
"avatarAlt": "L’avatar de cette annonce",
434+
"privateHostAvatarAlt": "Un avatar flouté pour {name}. Connectez-vous pour voir les informations complètes."
434435
},
435436
"seo": {
436437
"privateHostName": "Hôte privé",

messages/pt-BR.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@
430430
"localCommunity": "Comunidade local",
431431
"businessIn": "Negócio em {area}",
432432
"localBusiness": "Negócio local",
433-
"avatarAlt": "O avatar deste anúncio"
433+
"avatarAlt": "O avatar deste anúncio",
434+
"privateHostAvatarAlt": "Um avatar desfocado de {name}. Entre para ver as informações completas."
434435
},
435436
"seo": {
436437
"privateHostName": "Anfitrião privado",

src/components/ListingHeader/ListingHeader.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,14 @@ function ListingHeader({
130130
user?: any;
131131
}) {
132132
const t = useTranslations();
133-
const avatarProps = getListingAvatar(listing, user);
133+
const privateHostName = t("Listings.seo.privateHostName");
134+
const avatarProps = getListingAvatar(listing, user, {
135+
privateHostName,
136+
fallbackListingName: t("Listings.seo.fallbackListingName"),
137+
privateHostAvatarAlt: t("Listings.read.privateHostAvatarAlt", {
138+
name: privateHostName,
139+
}),
140+
});
134141

135142
return (
136143
<StyledListingHeader $presentation={presentation}>

src/utils/listingUtils.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
generateListingJsonLd,
77
generateListingMetadata,
88
getAnonymousResidentialListingTeaser,
9+
getListingAvatar,
910
} from "./listingUtils.ts";
1011
import type { Listing } from "../types/listing.ts";
1112
import type { ListingSeoCopy } from "./listingUtils.ts";
@@ -308,9 +309,37 @@ test("authenticated residential metadata can use private display names", () => {
308309
assert.deepEqual(metadata.title, {
309310
absolute: "Sam",
310311
});
312+
assert.match(
313+
String(metadata.description),
314+
/^Sam accepts food scraps for composting in Marrickville, Australia\./
315+
);
316+
assert.doesNotMatch(String(metadata.description), /helps people compost/);
311317
assert.equal(metadata.robots, undefined);
312318
});
313319

320+
test("anonymous residential avatars can use localised private-host alt text", () => {
321+
const residentialListing = {
322+
...communityListing,
323+
type: "residential",
324+
name: "Sam's backyard bin",
325+
owner_first_name: "Sam",
326+
slug: "private-host",
327+
} satisfies Listing;
328+
329+
const avatar = getListingAvatar(residentialListing, null, {
330+
privateHostName: "Anfitrión privado",
331+
fallbackListingName: "Anuncio",
332+
privateHostAvatarAlt:
333+
"Un avatar difuminado de Anfitrión privado. Inicia sesión para ver la información completa.",
334+
});
335+
336+
assert.equal(
337+
avatar?.alt,
338+
"Un avatar difuminado de Anfitrión privado. Inicia sesión para ver la información completa."
339+
);
340+
assert.doesNotMatch(avatar?.alt ?? "", /Private Host/);
341+
});
342+
314343
test("listing JSON-LD describes the public listing page and place conservatively", () => {
315344
const jsonLd = generateListingJsonLd(communityListing, null);
316345

src/utils/listingUtils.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ export type ListingSeoCopy = {
4949
type ListingDisplayNameCopy = Pick<
5050
ListingSeoCopy,
5151
"privateHostName" | "fallbackListingName"
52-
>;
52+
> & {
53+
privateHostAvatarAlt?: string;
54+
};
5355

5456
type ListingSeoOptions = {
5557
locale?: string;
@@ -258,7 +260,8 @@ export function getListingDisplayName(
258260

259261
export function getListingAvatar(
260262
listing: ListingLike | null | undefined,
261-
user: ListingUser
263+
user: ListingUser,
264+
seoCopy: ListingDisplayNameCopy = defaultListingSeoCopy
262265
): AvatarDescriptor {
263266
if (!listing) return null;
264267

@@ -276,21 +279,23 @@ export function getListingAvatar(
276279
};
277280
}
278281

279-
const listingDisplayName = getListingDisplayName(listing, user);
282+
const listingDisplayName = getListingDisplayName(listing, user, seoCopy);
280283

281284
if (isSensitiveAnonymousListing(listingType, user)) {
282285
return {
283286
bucket: "public",
284287
filename: "avatars/default/private.jpg",
285-
alt: "A blurred avatar for Private Host. Sign in to see their full information.",
288+
alt:
289+
seoCopy.privateHostAvatarAlt ??
290+
`A blurred avatar for ${seoCopy.privateHostName}. Sign in to see their full information.`,
286291
};
287292
}
288293

289294
if (listingType === "residential") {
290295
return {
291296
bucket: "avatars",
292297
filename: listing.owner_avatar || null,
293-
alt: `${listing.owner_first_name || "Private Host"} avatar`,
298+
alt: `${listing.owner_first_name || seoCopy.privateHostName} avatar`,
294299
};
295300
}
296301

@@ -388,8 +393,12 @@ export function generateListingDescription(
388393
const listingDisplayName = getListingDisplayName(listing, user, seoCopy);
389394
const listingType = normaliseListingType(listing.type);
390395
const isSensitiveAnonymous = isSensitiveAnonymousListing(listingType, user);
396+
const shouldUseResidentialIntro =
397+
listingType === "residential" || isSensitiveAnonymous;
398+
const shouldOmitListingDescription =
399+
listingType === "residential" || isSensitiveAnonymous;
391400
const listingFullLocation = getListingLocation(listing, options.locale);
392-
const listingIntro = isSensitiveAnonymous
401+
const listingIntro = shouldUseResidentialIntro
393402
? seoCopy.residentialIntro({
394403
name: listingDisplayName,
395404
location: listingFullLocation || undefined,
@@ -403,7 +412,7 @@ export function generateListingDescription(
403412
: listing.name || listingDisplayName;
404413
const listingDescriptionParts = [
405414
listingIntro,
406-
isSensitiveAnonymous
415+
shouldOmitListingDescription
407416
? null
408417
: listing.description?.trim()
409418
? listing.description.trim()

0 commit comments

Comments
 (0)