diff --git a/app/components/@settings/tabs/connections/components/RepositoryList.tsx b/app/components/@settings/tabs/connections/components/RepositoryList.tsx
index d6f0abda..7f90a98e 100644
--- a/app/components/@settings/tabs/connections/components/RepositoryList.tsx
+++ b/app/components/@settings/tabs/connections/components/RepositoryList.tsx
@@ -1,6 +1,7 @@
import React, { useContext } from 'react';
import type { GitHubRepoInfo } from '~/types/GitHub';
import { EmptyState, StatusIndicator } from '~/components/ui';
+import { useI18n } from '~/hooks/useI18n';
import { RepositoryCard } from './RepositoryCard';
import { RepositoryDialogContext } from './RepositoryDialogContext';
@@ -12,15 +13,16 @@ interface RepositoryListProps {
}
export function RepositoryList({ repos, isLoading, onSelect, activeTab }: RepositoryListProps) {
+ const { t } = useI18n();
// Access the parent component's setShowAuthDialog function
const { setShowAuthDialog } = useContext(RepositoryDialogContext);
if (isLoading) {
return (
-
+
- This may take a moment
+ {t('This may take a moment')}
);
@@ -31,9 +33,9 @@ export function RepositoryList({ repos, isLoading, onSelect, activeTab }: Reposi
return (
setShowAuthDialog(true)}
/>
);
@@ -41,8 +43,8 @@ export function RepositoryList({ repos, isLoading, onSelect, activeTab }: Reposi
return (
);
}
diff --git a/app/components/I18nProvider.tsx b/app/components/I18nProvider.tsx
new file mode 100644
index 00000000..76fa8cbe
--- /dev/null
+++ b/app/components/I18nProvider.tsx
@@ -0,0 +1,51 @@
+import React, { useState, useCallback } from 'react';
+import { I18nContext, I18nContextType } from '../context/i18n';
+
+interface I18nProviderProps {
+ children: React.ReactNode;
+}
+
+// Basic translations (replace with a proper i18n library later)
+const translations: Record> = {
+ en: {
+ greeting: 'Hello',
+ welcome: 'Welcome to our application!',
+ 'Loading repositories...': 'Loading repositories...',
+ 'This may take a moment': 'This may take a moment',
+ 'No repositories found': 'No repositories found',
+ 'Connect your GitHub account or create a new repository to get started': 'Connect your GitHub account or create a new repository to get started',
+ 'Connect GitHub Account': 'Connect GitHub Account',
+ 'Try searching with different keywords or filters': 'Try searching with different keywords or filters',
+ },
+ es: {
+ greeting: 'Hola',
+ welcome: '¡Bienvenido a nuestra aplicación!',
+ 'Loading repositories...': 'Cargando repositorios...',
+ 'This may take a moment': 'Esto puede tomar un momento',
+ 'No repositories found': 'No se encontraron repositorios',
+ 'Connect your GitHub account or create a new repository to get started': 'Conecta tu cuenta de GitHub o crea un nuevo repositorio para comenzar',
+ 'Connect GitHub Account': 'Conectar cuenta de GitHub',
+ 'Try searching with different keywords or filters': 'Intenta buscar con diferentes palabras clave o filtros',
+ },
+};
+
+export const I18nProvider: React.FC = ({ children }) => {
+ const [locale, setLocale] = useState('en');
+
+ const t = useCallback(
+ (key: string): string => {
+ return translations[locale]?.[key] || key;
+ },
+ [locale]
+ );
+
+ const contextValue: I18nContextType = {
+ locale,
+ setLocale,
+ t,
+ };
+
+ return (
+ {children}
+ );
+};
diff --git a/app/components/LanguageSelector.tsx b/app/components/LanguageSelector.tsx
new file mode 100644
index 00000000..62400210
--- /dev/null
+++ b/app/components/LanguageSelector.tsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import { useI18n } from '../hooks/useI18n';
+import { Button } from './ui/Button'; // Assuming a Button component exists
+
+export const LanguageSelector: React.FC = () => {
+ const { locale, setLocale } = useI18n();
+
+ return (
+
+
+
+
+ );
+};
diff --git a/app/components/chat/ChatSkeleton.tsx b/app/components/chat/ChatSkeleton.tsx
new file mode 100644
index 00000000..cc40d0f8
--- /dev/null
+++ b/app/components/chat/ChatSkeleton.tsx
@@ -0,0 +1,27 @@
+// app/components/chat/ChatSkeleton.tsx
+export function ChatSkeleton() {
+ return (
+
+
+
+ {/* Placeholder for a few messages */}
+ {[1, 2, 3].map((i) => (
+
+ ))}
+ {/* Placeholder for chat input box */}
+
+
+
+ );
+}
diff --git a/app/context/i18n.tsx b/app/context/i18n.tsx
new file mode 100644
index 00000000..b61d8fb4
--- /dev/null
+++ b/app/context/i18n.tsx
@@ -0,0 +1,9 @@
+import { createContext } from 'react';
+
+export interface I18nContextType {
+ locale: string;
+ setLocale: (locale: string) => void;
+ t: (key: string) => string;
+}
+
+export const I18nContext = createContext(undefined);
diff --git a/app/hooks/useI18n.ts b/app/hooks/useI18n.ts
new file mode 100644
index 00000000..77233afb
--- /dev/null
+++ b/app/hooks/useI18n.ts
@@ -0,0 +1,10 @@
+import { useContext } from 'react';
+import { I18nContext, I18nContextType } from '../context/i18n';
+
+export const useI18n = (): I18nContextType => {
+ const context = useContext(I18nContext);
+ if (context === undefined) {
+ throw new Error('useI18n must be used within an I18nProvider');
+ }
+ return context;
+};
diff --git a/app/root.tsx b/app/root.tsx
index a7ccb285..ff1587f0 100644
--- a/app/root.tsx
+++ b/app/root.tsx
@@ -1,6 +1,8 @@
import { useStore } from '@nanostores/react';
import type { LinksFunction } from '@remix-run/cloudflare';
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
+import { I18nProvider } from './components/I18nProvider';
+import { LanguageSelector } from './components/LanguageSelector';
import tailwindReset from '@unocss/reset/tailwind-compat.css?url';
import { themeStore } from './lib/stores/theme';
import { stripIndents } from './utils/stripIndent';
diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx
index 65df404a..0207af8a 100644
--- a/app/routes/_index.tsx
+++ b/app/routes/_index.tsx
@@ -1,9 +1,10 @@
import { json, type MetaFunction } from '@remix-run/cloudflare';
import { ClientOnly } from 'remix-utils/client-only';
-import { BaseChat } from '~/components/chat/BaseChat';
+import { BaseChat } from '~/components/chat/BaseChat'; // Keep BaseChat import if Chat.client still needs it, or remove if ChatSkeleton replaces all BaseChat SSR usage
import { Chat } from '~/components/chat/Chat.client';
import { Header } from '~/components/header/Header';
import BackgroundRays from '~/components/ui/BackgroundRays';
+import { ChatSkeleton } from '~/components/chat/ChatSkeleton'; // Import the new skeleton
export const meta: MetaFunction = () => {
return [{ title: 'Bolt' }, { name: 'description', content: 'Talk with Bolt, an AI assistant from StackBlitz' }];
@@ -22,7 +23,7 @@ export default function Index() {
- }>{() => }
+ }>{() => }
);
}