feat(web): integrate localized application catalogs
- compose app, UI, and independently imported block catalogs from JSON configuration\n- persist the selected locale on the server and activate it without hydration flicker\n- add a flag-based language switcher and localized navigation descriptors\n- mount the redesigned i18n devtool only in development\n- regenerate English and Simplified Chinese catalogs and add switcher coverage
This commit is contained in:
@@ -24,10 +24,19 @@ import { HotkeysProvider } from "@tanstack/react-hotkeys"
|
||||
import { TooltipProvider } from "@workspace/ui/components/tooltip"
|
||||
import { QueryClientProvider } from "@tanstack/react-query"
|
||||
import { AppI18nProvider } from "@/i18n/app-i18n-provider"
|
||||
import { getAppLocale } from "@/server/app-locale.functions"
|
||||
import type { AppLocale } from "@/i18n/app-locales"
|
||||
import { queryClient } from "@/lib/query-client"
|
||||
|
||||
export const Route = createRootRoute({
|
||||
loader: () => getUiState(),
|
||||
loader: async () => {
|
||||
const [initialState, initialLocale] = await Promise.all([
|
||||
getUiState(),
|
||||
getAppLocale(),
|
||||
])
|
||||
|
||||
return { initialLocale, initialState }
|
||||
},
|
||||
head: () => ({
|
||||
meta: [
|
||||
{ charSet: "utf-8" },
|
||||
@@ -48,11 +57,11 @@ export const Route = createRootRoute({
|
||||
})
|
||||
|
||||
function RootComponent() {
|
||||
const initialState = Route.useLoaderData()
|
||||
const { initialLocale, initialState } = Route.useLoaderData()
|
||||
|
||||
return (
|
||||
<RootDocument initialState={initialState}>
|
||||
<AppI18nProvider>
|
||||
<RootDocument initialLocale={initialLocale} initialState={initialState}>
|
||||
<AppI18nProvider locale={initialLocale}>
|
||||
<BreakpointReactor />
|
||||
<UiStateProvider
|
||||
initialState={initialState}
|
||||
@@ -94,9 +103,11 @@ function getUiInitializationScript(state: UiState) {
|
||||
|
||||
function RootDocument({
|
||||
children,
|
||||
initialLocale,
|
||||
initialState,
|
||||
}: Readonly<{
|
||||
children: ReactNode
|
||||
initialLocale: AppLocale
|
||||
initialState: UiState
|
||||
}>) {
|
||||
const themeMode = initialState["theme-mode"]
|
||||
@@ -110,7 +121,7 @@ function RootDocument({
|
||||
|
||||
return (
|
||||
<html
|
||||
lang="zh-CN"
|
||||
lang={initialLocale === "zh-Hans" ? "zh-CN" : "en-US"}
|
||||
suppressHydrationWarning
|
||||
className={className || undefined}
|
||||
style={themeMode === "system" ? undefined : { colorScheme: themeMode }}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
fetchMockNotifications,
|
||||
notificationsQueryKey,
|
||||
} from "@/data/notifications"
|
||||
import { AppLanguageSwitcher } from "@/i18n/app-language-switcher"
|
||||
|
||||
export const Route = createFileRoute("/_app")({
|
||||
component: ApplicationLayoutRoute,
|
||||
@@ -17,6 +18,7 @@ function ApplicationLayoutRoute() {
|
||||
return (
|
||||
<AppLayout
|
||||
chatThreads={chatThreads}
|
||||
headerActions={<AppLanguageSwitcher />}
|
||||
navigationGroups={primaryNavigationGroups}
|
||||
notifications={{
|
||||
queryFn: fetchMockNotifications,
|
||||
|
||||
Reference in New Issue
Block a user