summaryrefslogtreecommitdiff
path: root/src/components/Translations.astro
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/Translations.astro')
-rw-r--r--src/components/Translations.astro133
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 {