diff options
Diffstat (limited to 'src/components/Translations.astro')
-rw-r--r-- | src/components/Translations.astro | 133 |
1 files changed, 73 insertions, 60 deletions
diff --git a/src/components/Translations.astro b/src/components/Translations.astro index 6c2bf42..b78e5af 100644 --- a/src/components/Translations.astro +++ b/src/components/Translations.astro @@ -1,102 +1,115 @@ --- -import type { CollectionEntry } from "astro:content"; import { getFlagEmojiFromLocale, getLanguageNameFromLocale, } from "../utils/lang"; -import { getEntries } from "astro:content"; +import type { BlogPosting } from "@lib/collection/types"; +import { get } from "@utils/anonymous"; interface Props { - lang: string; - translations?: CollectionEntry<"blog">["data"]["translations"]; + id: string; + lang: Intl.LocalesArgument; + workTranslations: BlogPosting[]; + translationOfWork?: BlogPosting; } -const { lang } = Astro.props; +const { id, lang, workTranslations, translationOfWork } = Astro.props; -const translations = await getEntries(Astro.props.translations ?? []).then( - (translations) => - translations.sort((x, y) => x.data.lang.localeCompare(y.data.lang)), +const entries = [ + { "@type": "BlogPosting", "@id": id, inLanguage: lang }, + ...workTranslations, +]; +if (translationOfWork !== undefined) { + entries.push(translationOfWork); +} +const translations = entries.sort((x, y) => + x.inLanguage.localeCompare(y.inLanguage, lang) ); + +const list = new Intl.ListFormat(lang, { + type: "unit", + style: "narrow", +}); +const parts = list.formatToParts(translations.map(get("inLanguage"))); +let i = 0; --- -{ - /* TODO: What about <https://schema.org/translationOfWork> and <https://schema.org/translator>? */ -} +{/* TODO: <https://schema.org/translator> */} { translations.length > 0 && ( <aside> - <nav> - <p>Traduções:</p> - <ul class="translations"> + <nav class="mute small"> + <span>Traduções:{" "}</span> + <span class="translations" role="list"> { - translations.map(async ( - { data, collection, id }, - ) => { - const active = lang.localeCompare(data.lang) === 0; - return ( - <li - itemprop={active ? undefined : "workTranslation"} + parts.map( + ( + { type, value }: { + type: "element" | "literal"; + value: string; + }, + ) => { + switch (type) { + case "element": { + const { + "@id": identifier, + headline, + inLanguage, + } = translations[i++]; + const original = id === identifier; + const active = + lang.localeCompare(inLanguage, lang) === 0; + return ( + <span + role="listitem" + itemprop={active + ? undefined + : original + ? "translationOfWork" + : "workTranslation"} itemscope={!active} itemtype={active ? undefined : "http://schema.org/BlogPosting"} - itemid={active - ? undefined - : new URL(`${collection}/read/${id}`, Astro.site).href} + itemid={active ? undefined : identifier} > <a - href={`/${collection}/read/${id}`} + href={identifier} class:list={[{ active }]} rel={active ? undefined : "alternate"} - hreflang={active ? undefined : data.lang} + hreflang={active ? undefined : inLanguage} type="text/html" - title={data.title} - ><span class="emoji">{getFlagEmojiFromLocale(data.lang)}</span> - {getLanguageNameFromLocale(data.lang)} (<span + title={headline} + ><span class="emoji">{getFlagEmojiFromLocale(inLanguage)}</span> + {getLanguageNameFromLocale(inLanguage)} (<span itemprop="inLanguage" - >{data.lang}</span>)</a> - </li> + >{inLanguage}</span>)</a> + </span> ); - }) + } + case "literal": { + return <span>{value}</span>; + } + } + }, + ) } - </ul> + </span> </nav> </aside> ) } <style> - .translations { - list-style-type: none; - padding-inline-start: 0; - } - - .translations > li { - display: inline; + nav { + padding-block: calc(var(--size-2) * 1em); } - .translations > li > a > .emoji { - text-decoration: none; - font-family: var(--ff-icons); - } - - .translations > li > a.active { + a.active { font-weight: bolder; - text-decoration: underline; - color: var(--color-active); - } - - nav:has(.translations) { - display: flex; - gap: 1rem; - } - - nav:has(.translations) > * { - font-size: smaller; } - .translations > li:not(:first-child)::before { - content: "|"; - margin-inline: 0.5em; + a:hover { + color: var(--color-active); } @media print { |