feat(ui): make uiTranslations() optional for translations API

This commit is contained in:
Fuma Nama
2026-06-05 21:40:39 +08:00
parent 2ea0ed0aa8
commit 0cc1facdac
4 changed files with 45 additions and 29 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'fumadocs-ui': patch
'@fumadocs/base-ui': patch
---
Make `uiTranslations()` optional for translations API
@@ -46,7 +46,7 @@ import { uiTranslations } from 'fumadocs-ui/i18n';
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
// [!code ++:12]
export const i18nUI = i18n
export const translations = i18n
.translations()
.extend(uiTranslations())
.add('ui', {
+26 -16
View File
@@ -1,6 +1,7 @@
import type { I18nProviderProps } from '@/contexts/i18n';
import type {
I18nConfig,
SingularTranslationsAPI,
TranslationsAPI,
TranslationsAPIExtension,
TranslationValue,
@@ -119,26 +120,35 @@ export function uiTranslations(): TranslationsAPIExtension<'ui', Translations> {
};
}
export function i18nProvider<
Languages extends string,
P extends {
ui: Translations;
},
>(
translations: TranslationsAPI<Languages, P>,
export function i18nProvider(translations: SingularTranslationsAPI): I18nProviderProps;
export function i18nProvider<Languages extends string>(
translations: TranslationsAPI<Languages>,
lang?: NoInfer<Languages> | (string & {}),
): I18nProviderProps {
const { defaultLanguage, languages } = translations.config;
const { ui, ...rest } =
translations.get(lang ?? defaultLanguage) ?? translations.get(defaultLanguage);
): I18nProviderProps;
export function i18nProvider(
_translations: SingularTranslationsAPI | TranslationsAPI,
lang?: string,
): I18nProviderProps {
// ensure default labels/presets are applied
const t = _translations.extend(uiTranslations());
if ('config' in t) {
const { defaultLanguage, languages } = t.config;
const { ui, ...rest } = t.get(lang ?? defaultLanguage) ?? t.get(defaultLanguage);
return {
locale: lang,
translations: { ...ui, ...rest },
locales: languages.map((locale) => ({
locale,
name: t.get(locale).ui.displayName ?? locale,
})),
};
}
const { ui, ...rest } = t.get();
return {
locale: lang,
translations: { ...ui, ...rest },
locales: languages.map((locale) => ({
locale,
name: translations.get(locale).ui.displayName ?? locale,
})),
};
}
+12 -12
View File
@@ -120,33 +120,33 @@ export function uiTranslations(): TranslationsAPIExtension<'ui', Translations> {
};
}
export function i18nProvider<P extends { ui: Translations }>(
Translations: SingularTranslationsAPI<P>,
): I18nProviderProps;
export function i18nProvider<Languages extends string, P extends { ui: Translations }>(
Translations: TranslationsAPI<Languages, P>,
export function i18nProvider(translations: SingularTranslationsAPI): I18nProviderProps;
export function i18nProvider<Languages extends string>(
translations: TranslationsAPI<Languages>,
lang?: NoInfer<Languages> | (string & {}),
): I18nProviderProps;
export function i18nProvider(
translations: SingularTranslationsAPI | TranslationsAPI,
_translations: SingularTranslationsAPI | TranslationsAPI,
lang?: string,
): I18nProviderProps {
if ('config' in translations) {
const { defaultLanguage, languages } = translations.config;
const { ui, ...rest } =
translations.get(lang ?? defaultLanguage) ?? translations.get(defaultLanguage);
// ensure default labels/presets are applied
const t = _translations.extend(uiTranslations());
if ('config' in t) {
const { defaultLanguage, languages } = t.config;
const { ui, ...rest } = t.get(lang ?? defaultLanguage) ?? t.get(defaultLanguage);
return {
locale: lang,
translations: { ...ui, ...rest },
locales: languages.map((locale) => ({
locale,
name: translations.get(locale).ui.displayName ?? locale,
name: t.get(locale).ui.displayName ?? locale,
})),
};
}
const { ui, ...rest } = translations.get();
const { ui, ...rest } = t.get();
return {
translations: { ...ui, ...rest },
};