summaryrefslogtreecommitdiff
path: root/src/components/Translations.astro
blob: b78e5afc6d1ea962b46d7bbaac706dc33ed85990 (plain)
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>