summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiDeoo2024-04-05 15:28:03 +0200
committerGitHub2024-04-05 15:28:03 +0200
commita72cb96600798c1fbc7558f8fd24556ca442d312 (patch)
treea122f36c6d775e615bd0013f307977183e1e3bcb
parentb26238f22990dcf8ba002bea6a50c66f20ad5786 (diff)
downloadIT.starlight-a72cb96600798c1fbc7558f8fd24556ca442d312.tar.gz
IT.starlight-a72cb96600798c1fbc7558f8fd24556ca442d312.tar.bz2
IT.starlight-a72cb96600798c1fbc7558f8fd24556ca442d312.zip
Fix various Expressive Code translation issues (#1708)
Co-authored-by: Chris Swithinbank <357379+delucis@users.noreply.github.com> Co-authored-by: Hippo <6137925+hippotastic@users.noreply.github.com>
-rw-r--r--.changeset/wet-lemons-drum.md5
-rw-r--r--packages/starlight/__tests__/i18n/translations-ec.test.ts117
-rw-r--r--packages/starlight/integrations/expressive-code/index.ts4
-rw-r--r--packages/starlight/integrations/expressive-code/translations.ts45
-rw-r--r--packages/starlight/integrations/shared/localeToLang.ts11
5 files changed, 163 insertions, 19 deletions
diff --git a/.changeset/wet-lemons-drum.md b/.changeset/wet-lemons-drum.md
new file mode 100644
index 00000000..79a013a9
--- /dev/null
+++ b/.changeset/wet-lemons-drum.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/starlight': patch
+---
+
+Fixes translation issues with Expressive Code when using a default language other than English
diff --git a/packages/starlight/__tests__/i18n/translations-ec.test.ts b/packages/starlight/__tests__/i18n/translations-ec.test.ts
new file mode 100644
index 00000000..cbefb76f
--- /dev/null
+++ b/packages/starlight/__tests__/i18n/translations-ec.test.ts
@@ -0,0 +1,117 @@
+import { pluginFramesTexts } from 'astro-expressive-code';
+import { afterEach, expect, test, vi } from 'vitest';
+import { addTranslations } from '../../integrations/expressive-code/translations';
+import { StarlightConfigSchema, type StarlightUserConfig } from '../../utils/user-config';
+
+vi.mock('astro-expressive-code', async () => {
+ const mod = await vi.importActual<typeof import('astro-expressive-code')>(
+ 'astro-expressive-code'
+ );
+ return {
+ ...mod,
+ pluginFramesTexts: {
+ ...mod.pluginFramesTexts,
+ overrideTexts: vi.fn(),
+ },
+ };
+});
+
+afterEach(() => {
+ vi.clearAllMocks();
+});
+
+test('adds default english translations with no i18n config', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations(undefined);
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['en']);
+});
+
+test('adds translations in a monolingual site with english as root locale', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations({
+ root: { label: 'English', lang: 'en' },
+ });
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['en']);
+});
+
+test('adds translations in a monolingual site with french as root locale', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations({
+ root: { label: 'Français', lang: 'fr' },
+ });
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['fr']);
+});
+
+test('add translations in a multilingual site with english as root locale', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations({
+ root: { label: 'English', lang: 'en' },
+ fr: { label: 'French' },
+ });
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['en', 'fr']);
+});
+
+test('add translations in a multilingual site with french as root locale', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations({
+ root: { label: 'French', lang: 'fr' },
+ ru: { label: 'Русский', lang: 'ru' },
+ });
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['fr', 'ru']);
+});
+
+test('add translations in a multilingual site with english as default locale', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations(
+ {
+ en: { label: 'English', lang: 'en' },
+ fr: { label: 'French' },
+ },
+ 'en'
+ );
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['en', 'fr']);
+});
+
+test('add translations in a multilingual site with french as default locale', async () => {
+ const [config, useTranslations] = getStarlightConfigAndUseTranslations(
+ {
+ fr: { label: 'French', lang: 'fr' },
+ ru: { label: 'Русский', lang: 'ru' },
+ },
+ 'fr'
+ );
+
+ addTranslations(config, useTranslations);
+
+ expect(getExpressiveCodeOverridenLanguages()).toEqual(['fr', 'ru']);
+});
+
+function getStarlightConfigAndUseTranslations(
+ locales: StarlightUserConfig['locales'],
+ defaultLocale?: StarlightUserConfig['defaultLocale']
+) {
+ return [
+ StarlightConfigSchema.parse({
+ title: 'Expressive Code Translations Test',
+ locales,
+ defaultLocale,
+ }),
+ vi.fn().mockReturnValue(() => 'test UI string'),
+ ] as const;
+}
+
+function getExpressiveCodeOverridenLanguages() {
+ return [...new Set(vi.mocked(pluginFramesTexts.overrideTexts).mock.calls.map(([lang]) => lang))];
+}
diff --git a/packages/starlight/integrations/expressive-code/index.ts b/packages/starlight/integrations/expressive-code/index.ts
index 0c1a0af6..fc9962f8 100644
--- a/packages/starlight/integrations/expressive-code/index.ts
+++ b/packages/starlight/integrations/expressive-code/index.ts
@@ -77,7 +77,6 @@ export function getStarlightEcConfigPreprocessor({
return (input): AstroExpressiveCodeOptions => {
const astroConfig = input.astroConfig;
const ecConfig = input.ecConfig as StarlightExpressiveCodeOptions;
- const { locales } = starlightConfig;
const {
themes: themesInput,
@@ -111,7 +110,7 @@ export function getStarlightEcConfigPreprocessor({
});
// Add Expressive Code UI translations (if any) for all defined locales
- if (useTranslations) addTranslations(locales, useTranslations);
+ if (useTranslations) addTranslations(starlightConfig, useTranslations);
return {
themes,
@@ -124,6 +123,7 @@ export function getStarlightEcConfigPreprocessor({
}
return theme;
},
+ defaultLocale: starlightConfig.defaultLocale?.lang ?? starlightConfig.defaultLocale?.locale,
themeCssSelector: (theme, { styleVariants }) => {
// If one dark and one light theme are available, and the user has not disabled it,
// generate theme CSS selectors compatible with Starlight's dark mode switch
diff --git a/packages/starlight/integrations/expressive-code/translations.ts b/packages/starlight/integrations/expressive-code/translations.ts
index 1ff1c286..7aa5a4a1 100644
--- a/packages/starlight/integrations/expressive-code/translations.ts
+++ b/packages/starlight/integrations/expressive-code/translations.ts
@@ -1,26 +1,37 @@
import { pluginFramesTexts } from 'astro-expressive-code';
import type { StarlightConfig } from '../../types';
import type { createTranslationSystemFromFs } from '../../utils/translations-fs';
+import { localeToLang } from '../shared/localeToLang';
export function addTranslations(
- locales: StarlightConfig['locales'],
+ config: StarlightConfig,
useTranslations: ReturnType<typeof createTranslationSystemFromFs>
) {
- for (const locale in locales) {
- const lang = locales[locale]?.lang;
- if (!lang) continue;
-
- const t = useTranslations(locale);
- const translationKeys = [
- 'expressiveCode.copyButtonCopied',
- 'expressiveCode.copyButtonTooltip',
- 'expressiveCode.terminalWindowFallbackTitle',
- ] as const;
- translationKeys.forEach((key) => {
- const translation = t(key);
- if (!translation) return;
- const ecId = key.replace(/^expressiveCode\./, '');
- pluginFramesTexts.overrideTexts(lang, { [ecId]: translation });
- });
+ addTranslationsForLocale(config.defaultLocale.locale, config, useTranslations);
+ if (config.isMultilingual) {
+ for (const locale in config.locales) {
+ if (locale === config.defaultLocale.locale || locale === 'root') continue;
+ addTranslationsForLocale(locale, config, useTranslations);
+ }
}
}
+
+function addTranslationsForLocale(
+ locale: string | undefined,
+ config: StarlightConfig,
+ useTranslations: ReturnType<typeof createTranslationSystemFromFs>
+) {
+ const lang = localeToLang(config, locale);
+ const t = useTranslations(locale);
+ const translationKeys = [
+ 'expressiveCode.copyButtonCopied',
+ 'expressiveCode.copyButtonTooltip',
+ 'expressiveCode.terminalWindowFallbackTitle',
+ ] as const;
+ translationKeys.forEach((key) => {
+ const translation = t(key);
+ if (!translation) return;
+ const ecId = key.replace(/^expressiveCode\./, '');
+ pluginFramesTexts.overrideTexts(lang, { [ecId]: translation });
+ });
+}
diff --git a/packages/starlight/integrations/shared/localeToLang.ts b/packages/starlight/integrations/shared/localeToLang.ts
new file mode 100644
index 00000000..5d79d017
--- /dev/null
+++ b/packages/starlight/integrations/shared/localeToLang.ts
@@ -0,0 +1,11 @@
+import type { StarlightConfig } from '../../types';
+
+/**
+ * Get the BCP-47 language tag for the given locale.
+ * @param locale Locale string or `undefined` for the root locale.
+ */
+export function localeToLang(config: StarlightConfig, locale: string | undefined): string {
+ const lang = locale ? config.locales?.[locale]?.lang : config.locales?.root?.lang;
+ const defaultLang = config.defaultLocale?.lang || config.defaultLocale?.locale;
+ return lang || defaultLang || 'en';
+}