summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan Thomas2023-08-10 08:08:41 -0300
committerGitHub2023-08-10 13:08:41 +0200
commit06a205e0e673f505bbb87dfcfcb0f35b051677e9 (patch)
treeae4be87f29799cd4d95ac210df4dc62db8f7254a
parent43c1481da61d112a2212b86b56a49020e4063424 (diff)
downloadIT.starlight-06a205e0e673f505bbb87dfcfcb0f35b051677e9.tar.gz
IT.starlight-06a205e0e673f505bbb87dfcfcb0f35b051677e9.tar.bz2
IT.starlight-06a205e0e673f505bbb87dfcfcb0f35b051677e9.zip
Include built-in UI translation for regional docs (#475)
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Chris Swithinbank <357379+delucis@users.noreply.github.com>
-rw-r--r--.changeset/two-experts-rest.md5
-rw-r--r--docs/src/content/docs/reference/configuration.md2
-rw-r--r--packages/starlight/__tests__/i18n/config.test.ts2
-rw-r--r--packages/starlight/__tests__/i18n/routing.test.ts2
-rw-r--r--packages/starlight/__tests__/i18n/translations-with-user-config.test.ts (renamed from packages/starlight/__tests__/basics/translations-with-user-config.test.ts)11
-rw-r--r--packages/starlight/__tests__/i18n/translations.test.ts (renamed from packages/starlight/__tests__/basics/translations.test.ts)6
-rw-r--r--packages/starlight/__tests__/i18n/vitest.config.ts1
-rw-r--r--packages/starlight/utils/translations.ts19
8 files changed, 41 insertions, 7 deletions
diff --git a/.changeset/two-experts-rest.md b/.changeset/two-experts-rest.md
new file mode 100644
index 00000000..550fe900
--- /dev/null
+++ b/.changeset/two-experts-rest.md
@@ -0,0 +1,5 @@
+---
+"@astrojs/starlight": patch
+---
+
+Locales whose language tag includes a regional subtag now use built-in UI translations for their base language. For example, a locale with a language of `pt-BR` will use our `pt` UI translations.
diff --git a/docs/src/content/docs/reference/configuration.md b/docs/src/content/docs/reference/configuration.md
index c0d77d7f..593f4593 100644
--- a/docs/src/content/docs/reference/configuration.md
+++ b/docs/src/content/docs/reference/configuration.md
@@ -255,7 +255,7 @@ The label for this language to show to users, for example in the language switch
**type:** `string`
-The BCP-47 tag for this language, e.g. `"en"`, `"ar"`, or `"zh-CN"`. If not set, the language’s directory name will be used by default.
+The BCP-47 tag for this language, e.g. `"en"`, `"ar"`, or `"zh-CN"`. If not set, the language’s directory name will be used by default. Language tags with regional subtags (e.g. `"pt-BR"` or `"en-US"`) will use built-in UI translations for their base language if no region-specific translations are found.
##### `dir`
diff --git a/packages/starlight/__tests__/i18n/config.test.ts b/packages/starlight/__tests__/i18n/config.test.ts
index 93f9659c..0e8e9c8d 100644
--- a/packages/starlight/__tests__/i18n/config.test.ts
+++ b/packages/starlight/__tests__/i18n/config.test.ts
@@ -7,7 +7,7 @@ test('test suite is using correct env', () => {
test('config.isMultilingual is true with multiple locales', () => {
expect(config.isMultilingual).toBe(true);
- expect(config.locales).keys('fr', 'en', 'ar');
+ expect(config.locales).keys('fr', 'en', 'ar', 'pt-br');
});
test('config.defaultLocale is populated from the user’s chosen default', () => {
diff --git a/packages/starlight/__tests__/i18n/routing.test.ts b/packages/starlight/__tests__/i18n/routing.test.ts
index e0402b54..18d8ed89 100644
--- a/packages/starlight/__tests__/i18n/routing.test.ts
+++ b/packages/starlight/__tests__/i18n/routing.test.ts
@@ -38,7 +38,7 @@ test('routes have locale data added', () => {
expect(lang).toBe('ar');
expect(dir).toBe('rtl');
expect(locale).toBe('ar');
- } else {
+ } else if (id.startsWith('fr')) {
expect(lang).toBe('fr');
expect(dir).toBe('ltr');
expect(locale).toBe('fr');
diff --git a/packages/starlight/__tests__/basics/translations-with-user-config.test.ts b/packages/starlight/__tests__/i18n/translations-with-user-config.test.ts
index 57c0afe9..4335aa03 100644
--- a/packages/starlight/__tests__/basics/translations-with-user-config.test.ts
+++ b/packages/starlight/__tests__/i18n/translations-with-user-config.test.ts
@@ -4,7 +4,10 @@ import { useTranslations } from '../../utils/translations';
vi.mock('astro:content', async () =>
(await import('../test-utils')).mockedAstroContent({
- i18n: [['en', { 'page.editLink': 'Modify this doc!' }]],
+ i18n: [
+ ['en-US', { 'page.editLink': 'Modify this doc!' }],
+ ['pt-BR', { 'page.editLink': 'Modifique esse doc!' }],
+ ],
})
);
@@ -14,4 +17,10 @@ describe('useTranslations()', () => {
expect(t('page.editLink')).toBe('Modify this doc!');
expect(t('page.editLink')).not.toBe(translations.en?.['page.editLink']);
});
+
+ test('uses user-defined regional translations when available', () => {
+ const t = useTranslations('pt-br');
+ expect(t('page.editLink')).toBe('Modifique esse doc!');
+ expect(t('page.editLink')).not.toBe(translations.pt?.['page.editLink']);
+ });
});
diff --git a/packages/starlight/__tests__/basics/translations.test.ts b/packages/starlight/__tests__/i18n/translations.test.ts
index bd67ef9c..a8442166 100644
--- a/packages/starlight/__tests__/basics/translations.test.ts
+++ b/packages/starlight/__tests__/i18n/translations.test.ts
@@ -29,4 +29,10 @@ describe('useTranslations()', () => {
'tableOfContents.overview': 'Overview',
});
});
+
+ test('uses built-in translations for regional variants', () => {
+ const t = useTranslations('pt-br');
+ expect(t('page.nextLink')).toBe(translations.pt?.['page.nextLink']);
+ expect(t('page.nextLink')).not.toBe(translations.en?.['page.nextLink']);
+ });
});
diff --git a/packages/starlight/__tests__/i18n/vitest.config.ts b/packages/starlight/__tests__/i18n/vitest.config.ts
index da62f01a..36212fc7 100644
--- a/packages/starlight/__tests__/i18n/vitest.config.ts
+++ b/packages/starlight/__tests__/i18n/vitest.config.ts
@@ -7,5 +7,6 @@ export default defineVitestConfig({
fr: { label: 'French' },
en: { label: 'English', lang: 'en-US' },
ar: { label: 'Arabic', dir: 'rtl' },
+ 'pt-br': { label: 'Brazilian Portuguese', lang: 'pt-BR' },
},
});
diff --git a/packages/starlight/utils/translations.ts b/packages/starlight/utils/translations.ts
index da69bb1e..b4c6da4b 100644
--- a/packages/starlight/utils/translations.ts
+++ b/packages/starlight/utils/translations.ts
@@ -19,11 +19,21 @@ try {
const defaults = buildDictionary(
builtinTranslations.en!,
userTranslations.en,
- builtinTranslations[defaultLocale],
+ builtinTranslations[defaultLocale] || builtinTranslations[stripLangRegion(defaultLocale)],
userTranslations[defaultLocale]
);
/**
+ * Strips the region subtag from a BCP-47 lang string.
+ * @param {string} [lang]
+ * @example
+ * const lang = stripLangRegion('en-GB'); // => 'en'
+ */
+export function stripLangRegion(lang: string) {
+ return lang.replace(/-[a-zA-Z]{2}/, '');
+}
+
+/**
* Generate a utility function that returns UI strings for the given `locale`.
* @param {string | undefined} [locale]
* @example
@@ -31,9 +41,12 @@ const defaults = buildDictionary(
* const label = t('search.label'); // => 'Search'
*/
export function useTranslations(locale: string | undefined) {
- // TODO: Use better mapping, e.g. so that `en-GB` matches `en`.
const lang = localeToLang(locale);
- const dictionary = buildDictionary(defaults, builtinTranslations[lang], userTranslations[lang]);
+ const dictionary = buildDictionary(
+ defaults,
+ builtinTranslations[lang] || builtinTranslations[stripLangRegion(lang)],
+ userTranslations[lang]
+ );
const t = <K extends keyof typeof dictionary>(key: K) => dictionary[key];
t.pick = (startOfKey: string) =>
Object.fromEntries(Object.entries(dictionary).filter(([k]) => k.startsWith(startOfKey)));