diff --git a/astro.config.mjs b/astro.config.mjs index 24bdd536..dfb6f164 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -8,6 +8,17 @@ import mdx from "@astrojs/mdx"; export default defineConfig({ site: "https://interledger.org", base: "/developers", + i18n: { + locales: ["es", "en"], + defaultLocale: "en", + routing: { + prefixDefaultLocale: false, + fallbackType: "rewrite" + }, + fallback: { + es: "en" + } + }, integrations: [ starlight({ title: "Interledger", @@ -52,7 +63,7 @@ export default defineConfig({ Header: "./src/components/Header.astro", PageSidebar: "./src/components/PageSidebar.astro", }, - social: { + social:{ github: "https://github.com/interledger", }, sidebar: [ diff --git a/src/components/Header.astro b/src/components/Header.astro index a6006b48..b7d4e2b6 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -4,6 +4,10 @@ import Search from "@astrojs/starlight/components/Search.astro"; import SocialIcons from "@astrojs/starlight/components/SocialIcons.astro"; import ThemeSelect from "@astrojs/starlight/components/ThemeSelect.astro"; import DevelopersLogo from "./logos/DevelopersLogo.astro"; +import LanguagePicker from "./LanguagePicker.astro"; +import { getLangFromUrl } from "../i18n/utils"; + +const lang = getLangFromUrl(Astro.url); ---
@@ -24,9 +28,9 @@ import DevelopersLogo from "./logos/DevelopersLogo.astro";
- - +
+
@@ -95,10 +99,13 @@ import DevelopersLogo from "./logos/DevelopersLogo.astro"; .secondary-wrap { align-items: center; - gap: var(--space-s); } :global(site-search > button[data-open-modal]) { width: auto; } + + .theme-select-wrapper { + padding-inline-start: var(--space-s); + } diff --git a/src/components/LanguagePicker.astro b/src/components/LanguagePicker.astro new file mode 100644 index 00000000..0b973e0b --- /dev/null +++ b/src/components/LanguagePicker.astro @@ -0,0 +1,162 @@ +--- +import { defaultLang } from "../i18n/ui"; +import { useTranslatedPath } from "../i18n/utils"; +const { lang } = Astro.props; +const path = Astro.url.pathname; +const translatePath = useTranslatedPath(defaultLang, lang); +--- + + + + + + diff --git a/src/components/pages/Footer.astro b/src/components/pages/Footer.astro index 2b84d7a8..8f7c4b15 100644 --- a/src/components/pages/Footer.astro +++ b/src/components/pages/Footer.astro @@ -1,4 +1,8 @@ --- +import { getLangFromUrl, useTranslations } from "../../i18n/utils"; + +const lang = getLangFromUrl(Astro.url); +const t = useTranslations(lang); const currentYear = new Date().getFullYear(); --- @@ -53,7 +87,7 @@ const { title, description, ogType, ogImageUrl, canonicalURL = new URL(Astro.url flex-direction: column; min-height: 100%; min-width: 360px; - font-family: "Titillium", Arial, sans-serif; + font-family: "Titillium Web", Arial, sans-serif; overflow-x: clip; } diff --git a/src/layouts/BlogLayout.astro b/src/layouts/BlogLayout.astro index 39e7e8e1..c9fa649c 100644 --- a/src/layouts/BlogLayout.astro +++ b/src/layouts/BlogLayout.astro @@ -1,8 +1,13 @@ --- import BaseLayout from "./BaseLayout.astro"; +import { getLangFromUrl, useTranslations, useTranslatedPath } from "../i18n/utils"; const { frontmatter } = Astro.props; +const lang = getLangFromUrl(Astro.url); +const t = useTranslations(lang); +const translatePath = useTranslatedPath(lang, lang); + const dateObj = new Date(frontmatter.date); const isoDate = dateObj.toISOString().slice(0,10); const longDate = dateObj.toDateString().substring(4); @@ -16,14 +21,14 @@ const rawHTMLString = `This article was originally published at
  • - - Developers Portal + + {t("nav.developers")}
  • - - Engineering Blog + + {t("nav.tech-blog")}
  • diff --git a/src/layouts/LanderLayout.astro b/src/layouts/LanderLayout.astro index ea42257e..eaa13077 100644 --- a/src/layouts/LanderLayout.astro +++ b/src/layouts/LanderLayout.astro @@ -45,7 +45,7 @@ const { title, description, gradient = "option1" } = Astro.props; min-width: 360px; color: var(--color-text); font-size: var(--step-0); - font-family: "Titillium", Arial, sans-serif; + font-family: "Titillium Web", Arial, sans-serif; background-image: var(--gradient); background-repeat: no-repeat; background-attachment: fixed; diff --git a/src/pages/[lang]/blog/[...id].astro b/src/pages/[lang]/blog/[...id].astro new file mode 100644 index 00000000..4b3a99d2 --- /dev/null +++ b/src/pages/[lang]/blog/[...id].astro @@ -0,0 +1,26 @@ +--- +import { getCollection, render } from 'astro:content'; +import BlogLayout from '../../../layouts/BlogLayout.astro'; +import CommunityLinks from "../../../components/blog/CommunityLinks.astro"; + +export async function getStaticPaths() { + const blogEntries = await getCollection('blog'); + const defaultLang = 'en'; + + return blogEntries + .filter((entry) => entry.data.lang !== defaultLang) // handle the case of missing data? or is that done automatically? + .map((entry) => { + return { + params: { id: entry.id, lang: entry.data.lang }, + props: { entry }, + }; + }); +} + +const { entry } = Astro.props; +const { Content } = await render(entry); +--- + + + + diff --git a/src/pages/[lang]/blog/[...page].astro b/src/pages/[lang]/blog/[...page].astro new file mode 100644 index 00000000..7ca487c9 --- /dev/null +++ b/src/pages/[lang]/blog/[...page].astro @@ -0,0 +1,173 @@ +--- +import type { Page } from "astro"; +import { createExcerpt } from '../../../utils/create-excerpt'; +import BaseLayout from '../../../layouts/BaseLayout.astro'; +import Pagination from '../../../components/blog/Pagination.astro'; +import { getCollection } from 'astro:content'; +import { useTranslations, useTranslatedPath } from '../../../i18n/utils'; + +type Props = { + page: Page; +}; + +export async function getStaticPaths({ paginate }: any) { + const defaultLang = 'en'; + const blogEntries = (await getCollection("blog")) + const allLangs = Array.from(new Set(blogEntries.map((entry) => entry.data.lang))); + const langs = allLangs.filter((lang) => lang !== defaultLang); + return langs.flatMap((lang) => { + const filteredPosts = blogEntries + .filter((entry) => entry.data.lang !== defaultLang && entry.data.lang === lang) + .sort((a:any, b:any) => b.data.date.getTime() - a.data.date.getTime()); + + return paginate(filteredPosts, { + pageSize: 10, + params: { lang }, + }); + }); +} + +const { page } = Astro.props; +const { lang } = Astro.params; +const t = useTranslations(lang); +const translatePath = useTranslatedPath(lang, lang); +--- + +
    +
    + +
    +

    {t("nav.tech-blog")}

    + +

    {t("nav.foundation-blog")}

    + +
    +
    +
      + {((page as any).data || []).map((blogPostEntry: any) => { + const excerpt = `${createExcerpt(blogPostEntry.body).substring(0, 300)}...`; + return ( +
    1. + + {blogPostEntry.data.title} +

      {blogPostEntry.data.description ? blogPostEntry.data.description : excerpt}

      +
    2. + )} + )} +
    + +
    +
    +
    + + diff --git a/src/pages/blog/[...id].astro b/src/pages/blog/[...id].astro index ccdceff9..c4687539 100644 --- a/src/pages/blog/[...id].astro +++ b/src/pages/blog/[...id].astro @@ -5,10 +5,16 @@ import CommunityLinks from "../../components/blog/CommunityLinks.astro"; export async function getStaticPaths() { const blogEntries = await getCollection('blog'); - return blogEntries.map(entry => ({ - params: { id: entry.id }, - props: { entry }, - })); + const defaultLang = 'en'; + + return blogEntries + .filter((entry) => entry.data.lang === defaultLang) + .map((entry) => { + return { + params: { id: entry.id }, + props: { entry }, + }; + }); } const { entry } = Astro.props; diff --git a/src/pages/blog/[...page].astro b/src/pages/blog/[...page].astro index ac72b5d9..9218ac93 100644 --- a/src/pages/blog/[...page].astro +++ b/src/pages/blog/[...page].astro @@ -4,19 +4,25 @@ import { createExcerpt } from '../../utils/create-excerpt'; import BaseLayout from '../../layouts/BaseLayout.astro'; import Pagination from '../../components/blog/Pagination.astro'; import { getCollection } from 'astro:content'; +import { useTranslations, getLangFromUrl} from '../../i18n/utils'; type Props = { page: Page; }; export async function getStaticPaths({ paginate }: any) { - const blogEntries = (await getCollection("blog")).sort((a:any, b:any) => b.data.date.getTime() - a.data.date.getTime()); + const blogEntries = (await getCollection("blog")) + .filter((entry) => entry.filePath && entry.filePath.match(/\/blog\/[^\/]+\.mdx?$/)) + .sort((a:any, b:any) => b.data.date.getTime() - a.data.date.getTime()); return paginate(blogEntries, { pageSize: 10 }); } +const lang = getLangFromUrl(Astro.url); const { page } = Astro.props; +const t = useTranslations(lang); + --- - +