Translations: manage once, consume through the SDK
One translation API supports real SSR and CSR with explicit cache and fallback rules.
Manage entries
In Translations, select the portal namespace and create blog.searchPlaceholder with Chinese and English copy. GET /api/i18n/portal?locale=en-US returns {code:200,data:{namespace,locale,messages}}. Keys are relative to the namespace, without a repeated portal prefix.
import type { Shell } from '@mosaic-base/shell';
import type { ArticleSDK, SiteSDK, I18nSDK } from '@mosaic-base/client-sdk';
import type { AuthClient, ServerAuthClient } from '@mosaic-base/auth-sdk';
// Declare once in your application's type contract, never import SDK implementations.
declare module '@mosaic-base/shell/contracts' {
interface SdkRegistry {
'site.config': Pick<SiteSDK, 'getConfig'>;
'content.articles': Pick<ArticleSDK, 'list' | 'getBySlug' | 'getPreview' | 'search'>;
'i18n.messages': Pick<I18nSDK, 'load' | 't' | 'clearCache' | 'refresh'>;
'auth.client': AuthClient | ServerAuthClient;
}
}
export async function readSearchHint(shell: Shell, locale: string) {
const reader = await shell.getSdk('i18n.messages');
const messages = await reader.load('portal', locale);
return messages['blog.searchPlaceholder'] || 'Search articles…';
}
export async function refreshTranslations(shell: Shell, locale: string) {
return (await shell.getSdk('i18n.messages')).refresh('portal', locale);
}
export async function invalidateTranslations(shell: Shell) {
(await shell.getSdk('i18n.messages')).clearCache();
}
// Browser defaults: cacheTtlMs=60_000. Explicit server factory options use TTL0.Server rendering (SSR)
The server reads the value below, so the original HTML contains current copy. This server reader uses TTL0.
Client rendering (CSR)
This component makes its own anonymous request with the default 60-second SDK cache. Switch language, explicitly refresh that locale or retry after failure.
en-US · Loading public translations…
Loading…
Cache, fallback and import
Blank target copy falls back to the zh-CN source; wholly blank keys are omitted. Missing namespaces return 404. Request failures are not cached as successful empty data, allowing built-in application fallback.
SDK caches are isolated by namespace/locale, with cacheTtlMs, clearCache and scoped refresh(namespace, locale). Saving in Administration does not push into every open application. Exported JSON can be imported: merge fills blanks; replace updates matching keys and preserves unlisted ones. AI translation awaits later Agent work.