1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
---
import {
getFlagEmojiFromLocale,
getLanguageNameFromLocale,
} from "../utils/lang";
import type { BlogPosting } from "@lib/collection/types";
import { get } from "@utils/anonymous";
interface Props {
id: string;
lang: Intl.LocalesArgument;
workTranslations: BlogPosting[];
translationOfWork?: BlogPosting;
}
const { id, lang, workTranslations, translationOfWork } = Astro.props;
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: <https://schema.org/translator> */}
{
translations.length > 0 && (
<aside>
<nav class="mute small">
<span>Traduções:{" "}</span>
<span class="translations" role="list">
{
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 : identifier}
>
<a
href={identifier}
class:list={[{ active }]}
rel={active ? undefined : "alternate"}
hreflang={active ? undefined : inLanguage}
type="text/html"
title={headline}
><span class="emoji">{getFlagEmojiFromLocale(inLanguage)}</span>
{getLanguageNameFromLocale(inLanguage)} (<span
itemprop="inLanguage"
>{inLanguage}</span>)</a>
</span>
);
}
case "literal": {
return <span>{value}</span>;
}
}
},
)
}
</span>
</nav>
</aside>
)
}
<style>
nav {
padding-block: calc(var(--size-2) * 1em);
}
a.active {
font-weight: bolder;
}
a:hover {
color: var(--color-active);
}
@media print {
aside {
display: none;
}
}
</style>
|