Skip to content

Commit

Permalink
Support translating default aside titles (#517)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
  • Loading branch information
liruifengv and delucis committed Nov 17, 2023
1 parent 1ec69e9 commit 5b549cb
Show file tree
Hide file tree
Showing 28 changed files with 227 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/thick-boxes-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@astrojs/starlight": minor
---

Add i18n support for default aside labels
61 changes: 59 additions & 2 deletions packages/starlight/__tests__/remark-rehype/asides.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import { createMarkdownProcessor } from '@astrojs/markdown-remark';
import { describe, expect, test } from 'vitest';
import { starlightAsides } from '../../integrations/asides';
import { createTranslationSystemFromFs } from '../../utils/translations-fs';
import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config';

const starlightConfig = StarlightConfigSchema.parse({
title: 'Asides Tests',
locales: { en: { label: 'English' }, fr: { label: 'French' } },
defaultLocale: 'en',
} satisfies StarlightUserConfig);

const useTranslations = createTranslationSystemFromFs(
starlightConfig,
// Using non-existent `_src/` to ignore custom files in this test fixture.
{ srcDir: new URL('./_src/', import.meta.url) }
);

const processor = await createMarkdownProcessor({
remarkPlugins: [...starlightAsides()],
remarkPlugins: [
...starlightAsides({
starlightConfig,
astroConfig: { root: new URL(import.meta.url), srcDir: new URL('./_src/', import.meta.url) },
useTranslations,
}),
],
});

test('generates <aside>', async () => {
Expand All @@ -23,7 +43,7 @@ describe('default labels', () => {
['danger', 'Danger'],
])('%s has label %s', async (type, label) => {
const res = await processor.render(`
:::${type}[${label}]
:::${type}
Some text
:::
`);
Expand Down Expand Up @@ -85,3 +105,40 @@ Nested tip.
`);
expect(res.code).toMatchFileSnapshot('./snapshots/nested-asides.html');
});

describe('translated labels in French', () => {
test.each([
['note', 'Note'],
['tip', 'Astuce'],
['caution', 'Attention'],
['danger', 'Danger'],
])('%s has label %s', async (type, label) => {
const res = await processor.render(
`
:::${type}
Some text
:::
`,
{ fileURL: new URL('./_src/content/docs/fr/index.md', import.meta.url) }
);
expect(res.code).includes(`aria-label="${label}"`);
expect(res.code).includes(`</svg>${label}</p>`);
});
});

test('runs without locales config', async () => {
const processor = await createMarkdownProcessor({
remarkPlugins: [
...starlightAsides({
starlightConfig: { locales: undefined },
astroConfig: {
root: new URL(import.meta.url),
srcDir: new URL('./_src/', import.meta.url),
},
useTranslations,
}),
],
});
const res = await processor.render(':::note\nTest\n::');
expect(res.code.includes('aria-label=Note"'));
});
2 changes: 1 addition & 1 deletion packages/starlight/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn
plugins: [vitePluginStarlightUserConfig(userConfig, config)],
},
markdown: {
remarkPlugins: [...starlightAsides()],
remarkPlugins: [...starlightAsides({ starlightConfig: userConfig, astroConfig: config, useTranslations })],
rehypePlugins: [rehypeRtlCodeSupport()],
shikiConfig:
// Configure Shiki theme if the user is using the default github-dark theme.
Expand Down
57 changes: 43 additions & 14 deletions packages/starlight/integrations/asides.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
import type { AstroUserConfig } from 'astro';
import type { AstroConfig, AstroUserConfig } from 'astro';
import { h as _h, s as _s, type Properties } from 'hastscript';
import type { Paragraph as P, Root } from 'mdast';
import remarkDirective from 'remark-directive';
import type { Plugin, Transformer } from 'unified';
import { remove } from 'unist-util-remove';
import { visit } from 'unist-util-visit';
import type { StarlightConfig } from '../types';
import type { createTranslationSystemFromFs } from '../utils/translations-fs';

interface AsidesOptions {
starlightConfig: { locales: StarlightConfig['locales'] };
astroConfig: { root: AstroConfig['root']; srcDir: AstroConfig['srcDir'] };
useTranslations: ReturnType<typeof createTranslationSystemFromFs>;
}

function pathToLocale(
slug: string | undefined,
config: AsidesOptions['starlightConfig']
): string | undefined {
const locales = Object.keys(config.locales || {});
const baseSegment = slug?.split('/')[0];
if (baseSegment && locales.includes(baseSegment)) return baseSegment;
return undefined;
}

/** get current lang from file full path */
function getLocaleFromPath(
unformattedPath: string | undefined,
{ starlightConfig, astroConfig }: AsidesOptions
): string | undefined {
const srcDir = new URL(astroConfig.srcDir, astroConfig.root);
const docsDir = new URL('content/docs/', srcDir);
const path = unformattedPath
// Format path to unix style path.
?.replace(/\\/g, '/')
// Strip docs path leaving only content collection file ID.
// Example: /Users/houston/repo/src/content/docs/en/guide.md => en/guide.md
.replace(docsDir.pathname, '');
const locale = pathToLocale(path, starlightConfig);
return locale;
}

/** Hacky function that generates an mdast HTML tree ready for conversion to HTML by rehype. */
function h(el: string, attrs: Properties = {}, children: any[] = []): P {
Expand Down Expand Up @@ -50,19 +85,11 @@ function s(el: string, attrs: Properties = {}, children: any[] = []): P {
* </Aside>
* ```
*/
function remarkAsides(): Plugin<[], Root> {
function remarkAsides(options: AsidesOptions): Plugin<[], Root> {
type Variant = 'note' | 'tip' | 'caution' | 'danger';
const variants = new Set(['note', 'tip', 'caution', 'danger']);
const isAsideVariant = (s: string): s is Variant => variants.has(s);

// TODO: hook these up for i18n once the design for translating strings is ready
const defaultTitles = {
note: 'Note',
tip: 'Tip',
caution: 'Caution',
danger: 'Danger',
};

const iconPaths = {
// Information icon
note: [
Expand Down Expand Up @@ -95,7 +122,9 @@ function remarkAsides(): Plugin<[], Root> {
],
};

const transformer: Transformer<Root> = (tree) => {
const transformer: Transformer<Root> = (tree, file) => {
const locale = getLocaleFromPath(file.history[0], options);
const t = options.useTranslations(locale);
visit(tree, (node, index, parent) => {
if (!parent || index === null || node.type !== 'containerDirective') {
return;
Expand All @@ -107,7 +136,7 @@ function remarkAsides(): Plugin<[], Root> {
// its children, but we want to pass it as the title prop to <Aside>, so
// we iterate over the children, find a directive label, store it for the
// title prop, and remove the paragraph from children.
let title = defaultTitles[variant];
let title = t(`aside.${variant}`);
remove(node, (child): boolean | void => {
if (child.data?.directiveLabel) {
if (
Expand Down Expand Up @@ -157,6 +186,6 @@ function remarkAsides(): Plugin<[], Root> {

type RemarkPlugins = NonNullable<NonNullable<AstroUserConfig['markdown']>['remarkPlugins']>;

export function starlightAsides(): RemarkPlugins {
return [remarkDirective, remarkAsides()];
export function starlightAsides(options: AsidesOptions): RemarkPlugins {
return [remarkDirective, remarkAsides(options)];
}
4 changes: 4 additions & 0 deletions packages/starlight/schemas/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ function starlightI18nSchema() {
.describe('Label shown on the “next page” pagination arrow in the page footer.'),

'404.text': z.string().describe('Text shown on Starlight’s default 404 page'),
'aside.tip': z.string().describe('Text shown on the tip aside variant'),
'aside.note': z.string().describe('Text shown on the note aside variant'),
'aside.caution': z.string().describe('Text shown on the warning aside variant'),
'aside.danger': z.string().describe('Text shown on the danger aside variant'),
})
.partial();
}
Expand Down
6 changes: 5 additions & 1 deletion packages/starlight/translations/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "اخر تحديث:",
"page.previousLink": "السابق",
"page.nextLink": "التالي",
"404.text": "الصفحة غير موجودة. تأكد من الرابط أو ابحث بإستعمال شريط البحث."
"404.text": "الصفحة غير موجودة. تأكد من الرابط أو ابحث بإستعمال شريط البحث.",
"aside.note": "ملحوظة",
"aside.tip": "نصيحة",
"aside.caution": "تنبيه",
"aside.danger": "تحذير"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Poslední aktualizace:",
"page.previousLink": "Předchozí",
"page.nextLink": "Další",
"404.text": "Stránka nenalezena. Zkontrolujte adresu URL nebo zkuste použít vyhledávací pole."
"404.text": "Stránka nenalezena. Zkontrolujte adresu URL nebo zkuste použít vyhledávací pole.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Sidst opdateret:",
"page.previousLink": "Forrige",
"page.nextLink": "Næste",
"404.text": "Siden er ikke fundet. Tjek din URL eller prøv søgelinjen."
"404.text": "Siden er ikke fundet. Tjek din URL eller prøv søgelinjen.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Zuletzt bearbeitet:",
"page.previousLink": "Vorherige Seite",
"page.nextLink": "Nächste Seite",
"404.text": "Seite nicht gefunden. Überprüfe die URL oder nutze die Suchleiste."
"404.text": "Seite nicht gefunden. Überprüfe die URL oder nutze die Suchleiste.",
"aside.note": "Hinweis",
"aside.tip": "Tipp",
"aside.caution": "Achtung",
"aside.danger": "Gefahr"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Last updated:",
"page.previousLink": "Previous",
"page.nextLink": "Next",
"404.text": "Page not found. Check the URL or try using the search bar."
"404.text": "Page not found. Check the URL or try using the search bar.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Última actualización:",
"page.previousLink": "Página anterior",
"page.nextLink": "Siguiente página",
"404.text": "Página no encontrada. Verifica la URL o intenta usar la barra de búsqueda."
"404.text": "Página no encontrada. Verifica la URL o intenta usar la barra de búsqueda.",
"aside.note": "Nota",
"aside.tip": "Consejo",
"aside.caution": "Precaución",
"aside.danger": "Peligro"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "آخرین به روز رسانی:",
"page.previousLink": "قبلی",
"page.nextLink": "بعدی",
"404.text": "صفحه یافت نشد. لطفاً URL را بررسی کنید یا از جستجو استفاده نمایید."
"404.text": "صفحه یافت نشد. لطفاً URL را بررسی کنید یا از جستجو استفاده نمایید.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Dernière mise à jour :",
"page.previousLink": "Précédent",
"page.nextLink": "Suivant",
"404.text": "Page non trouvée. Vérifiez l’URL ou essayez d’utiliser la barre de recherche."
"404.text": "Page non trouvée. Vérifiez l’URL ou essayez d’utiliser la barre de recherche.",
"aside.note": "Note",
"aside.tip": "Astuce",
"aside.caution": "Attention",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/gl.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Última actualización:",
"page.previousLink": "Anterior",
"page.nextLink": "Seguinte",
"404.text": "Paxina non atopada. Comproba a URL ou intenta usar a barra de busca."
"404.text": "Paxina non atopada. Comproba a URL ou intenta usar a barra de busca.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "עדכון אחרון:",
"page.previousLink": "הקודם",
"page.nextLink": "הבא",
"404.text": "הדף לא נמצא. אנא בדקו את כתובת האתר או נסו להשתמש בסרגל החיפוש."
"404.text": "הדף לא נמצא. אנא בדקו את כתובת האתר או נסו להשתמש בסרגל החיפוש.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Terakhir diperbaharui:",
"page.previousLink": "Sebelumnya",
"page.nextLink": "Selanjutnya",
"404.text": "Halaman tidak ditemukan. Cek kembali kolom URL atau gunakan fitur pencarian."
"404.text": "Halaman tidak ditemukan. Cek kembali kolom URL atau gunakan fitur pencarian.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Ultimo aggiornamento:",
"page.previousLink": "Indietro",
"page.nextLink": "Avanti",
"404.text": "Pagina non trovata. Verifica l'URL o prova a utilizzare la barra di ricerca."
"404.text": "Pagina non trovata. Verifica l'URL o prova a utilizzare la barra di ricerca.",
"aside.note": "Nota",
"aside.tip": "Consiglio",
"aside.caution": "Attenzione",
"aside.danger": "Pericolo"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "最終更新日:",
"page.previousLink": "前へ",
"page.nextLink": "次へ",
"404.text": "ページが見つかりません。 URL を確認するか、検索バーを使用してみてください。"
"404.text": "ページが見つかりません。 URL を確認するか、検索バーを使用してみてください。",
"aside.note": "ノート",
"aside.tip": "ヒント",
"aside.caution": "注意",
"aside.danger": "危険"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "최종 수정:",
"page.previousLink": "이전 페이지",
"page.nextLink": "다음 페이지",
"404.text": "페이지를 찾을 수 없습니다. URL을 확인하거나 검색창을 사용해보세요."
"404.text": "페이지를 찾을 수 없습니다. URL을 확인하거나 검색창을 사용해보세요.",
"aside.note": "노트",
"aside.tip": "",
"aside.caution": "주의",
"aside.danger": "위험"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Sist oppdatert:",
"page.previousLink": "Forrige",
"page.nextLink": "Neste",
"404.text": "Siden ble ikke funnet. Sjekk URL-en eller prøv å bruke søkefeltet."
"404.text": "Siden ble ikke funnet. Sjekk URL-en eller prøv å bruke søkefeltet.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Laatst bewerkt:",
"page.previousLink": "Vorige",
"page.nextLink": "Volgende",
"404.text": "Pagina niet gevonden. Controleer de URL of probeer de zoekbalk."
"404.text": "Pagina niet gevonden. Controleer de URL of probeer de zoekbalk.",
"aside.note": "Note",
"aside.tip": "Tip",
"aside.caution": "Caution",
"aside.danger": "Danger"
}
6 changes: 5 additions & 1 deletion packages/starlight/translations/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
"page.lastUpdated": "Última atualização:",
"page.previousLink": "Anterior",
"page.nextLink": "Próximo",
"404.text": "Página não encontrada. Verifique o URL ou tente usar a barra de pesquisa."
"404.text": "Página não encontrada. Verifique o URL ou tente usar a barra de pesquisa.",
"aside.note": "Nota",
"aside.tip": "Dica",
"aside.caution": "Cuidado",
"aside.danger": "Perigo"
}

0 comments on commit 5b549cb

Please sign in to comment.