- {`Failed to ${type} document${result.title ? ` "${result.title}"` : ''}`}
+ {t('Failed to {type} document{title}', {
+ type,
+ title: result.title ? ` "${result.title}"` : ''
+ })}
{result.error}
@@ -156,7 +162,10 @@ function PureDocumentToolResult({
- {`${getActionText(type, 'past')} "${result.title ?? 'document'}"`}
+ {t('{action} "{title}"', {
+ action: getActionText(type, 'past', t),
+ title: result.title ?? t('document')
+ })}
{result.status && ({result.status})}
@@ -178,7 +187,7 @@ function PureDocumentToolResult({
className="text-xs flex items-center gap-1.5"
>
- {`${getActionText(type, 'past')} ${result.title ? `"${result.title}"` : '(active document)'}`}
+ {t('{action} {title}', {
+ action: getActionText(type, 'past', t),
+ title: result.title ? `"${result.title}"` : t('(active document)')
+ })}
{successMessage}
@@ -248,6 +260,7 @@ function PureDocumentToolCall({
isReadonly,
}: DocumentToolCallProps) {
const { artifact: localArtifact } = useArtifact();
+ const t = useGT();
const artTitle = localArtifact?.title ?? '';
const titleArg = args.title ?? '';
@@ -271,8 +284,10 @@ function PureDocumentToolCall({
- {`${getActionText(type, 'present')}`}{' '}
- {displayTitle ? `"${displayTitle}"` : '(active document)'}
+ {t('{action} {title}', {
+ action: getActionText(type, 'present', t),
+ title: displayTitle ? `"${displayTitle}"` : t('(active document)')
+ })}
diff --git a/apps/snow-leopard/components/document/editor-toolbar.tsx b/apps/snow-leopard/components/document/editor-toolbar.tsx
index 88e46111..e09e6881 100644
--- a/apps/snow-leopard/components/document/editor-toolbar.tsx
+++ b/apps/snow-leopard/components/document/editor-toolbar.tsx
@@ -3,6 +3,7 @@
import React from 'react';
import { toggleMark, setBlockType } from 'prosemirror-commands';
import { wrapInList, liftListItem } from 'prosemirror-schema-list';
+import { useGT } from 'gt-next/client';
import {
List,
ListOrdered,
@@ -48,6 +49,7 @@ interface EditorToolbarProps {
export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
const view = getActiveEditorView();
+ const t = useGT();
const textContent = view?.state.doc.textContent || '';
const wordCount = textContent.trim().split(/\s+/).filter(Boolean).length;
const buttonClass = (format: string) =>
@@ -60,10 +62,10 @@ export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
);
const currentTextStyle = activeFormats.h1
- ? 'Heading 1'
+ ? t('Heading 1')
: activeFormats.h2
- ? 'Heading 2'
- : 'Paragraph';
+ ? t('Heading 2')
+ : t('Paragraph');
const textOptions: {
label: string;
@@ -71,17 +73,17 @@ export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
command: () => void;
}[] = [
{
- label: 'Heading 1',
+ label: t('Heading 1'),
formatKey: 'h1',
command: () => runCommand(setBlockType(nodes.heading, { level: 1 })),
},
{
- label: 'Heading 2',
+ label: t('Heading 2'),
formatKey: 'h2',
command: () => runCommand(setBlockType(nodes.heading, { level: 2 })),
},
{
- label: 'Paragraph',
+ label: t('Paragraph'),
formatKey: 'p',
command: () => runCommand(setBlockType(nodes.paragraph)),
},
@@ -143,7 +145,7 @@ export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
activeFormats.bulletList
@@ -154,7 +156,7 @@ export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
activeFormats.orderedList
@@ -168,14 +170,14 @@ export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
runCommand(toggleMark(marks.strong))}
>
runCommand(toggleMark(marks.em))}
>
@@ -183,7 +185,7 @@ export function EditorToolbar({ activeFormats }: EditorToolbarProps) {
- {wordCount} word{wordCount === 1 ? '' : 's'}
+ {t('{count} {word}', { count: wordCount, word: wordCount === 1 ? t('word') : t('words') })}
);
}
\ No newline at end of file
diff --git a/apps/snow-leopard/components/document/version-header.tsx b/apps/snow-leopard/components/document/version-header.tsx
index 6dd5fe8f..579b97fa 100644
--- a/apps/snow-leopard/components/document/version-header.tsx
+++ b/apps/snow-leopard/components/document/version-header.tsx
@@ -5,6 +5,7 @@ import { useSWRConfig } from 'swr';
import { RotateCcw, Clock, Loader2 } from 'lucide-react';
import { format, formatDistance, isToday, isYesterday, differenceInDays } from 'date-fns';
import { toast } from 'sonner';
+import { useGT } from 'gt-next/client';
import type { Document } from '@snow-leopard/db';
import { getDocumentTimestampByIndex } from '@/lib/utils';
@@ -25,12 +26,13 @@ export const VersionHeader = ({
currentVersionIndex,
}: VersionHeaderProps) => {
const { artifact, setArtifact } = useArtifact();
+ const t = useGT();
const { mutate } = useSWRConfig();
const [isMutating, setIsMutating] = useState(false);
const handleRestoreVersion = useCallback(async () => {
if (!documents || currentVersionIndex < 0 || currentVersionIndex >= documents.length) {
- toast.error('Invalid version selected');
+ toast.error(t('Invalid version selected'));
return;
}
@@ -75,10 +77,10 @@ export const VersionHeader = ({
});
window.dispatchEvent(event);
- toast.success('Version restored successfully');
+ toast.success(t('Version restored successfully'));
} catch (error) {
console.error('[Version] Error restoring version:', error);
- toast.error('Failed to restore version');
+ toast.error(t('Failed to restore version'));
} finally {
setIsMutating(false);
}
@@ -87,8 +89,8 @@ export const VersionHeader = ({
if (!documents || documents.length === 0) return null;
const formatVersionLabel = (date: Date) => {
- if (isToday(date)) return "Today";
- if (isYesterday(date)) return "Yesterday";
+ if (isToday(date)) return t("Today");
+ if (isYesterday(date)) return t("Yesterday");
const days = differenceInDays(new Date(), date);
if (days < 7) return format(date, 'EEE');
@@ -150,11 +152,11 @@ export const VersionHeader = ({
) : (
)}
-
Restore
+
{t('Restore')}
- Make this version the current version
+ {t('Make this version the current version')}
@@ -164,7 +166,7 @@ export const VersionHeader = ({
className="text-xs h-7 px-2.5"
onClick={() => handleVersionChange('latest')}
>
- Exit History
+ {t('Exit History')}
diff --git a/apps/snow-leopard/components/highlight-blog-tool.tsx b/apps/snow-leopard/components/highlight-blog-tool.tsx
index 2da2554e..7c0edba9 100644
--- a/apps/snow-leopard/components/highlight-blog-tool.tsx
+++ b/apps/snow-leopard/components/highlight-blog-tool.tsx
@@ -6,6 +6,7 @@ import {
LoaderIcon,
MessageIcon as SearchIcon,
} from '@/components/icons';
+import { T, Branch } from 'gt-next';
import type { ToolInvocation } from 'ai';
interface HighlightToolProps {
@@ -30,9 +31,15 @@ function PureHighlightTool({ toolInvocation }: HighlightToolProps) {
diff --git a/apps/snow-leopard/components/mobile-warning.tsx b/apps/snow-leopard/components/mobile-warning.tsx
index 3ae6220c..c389adea 100644
--- a/apps/snow-leopard/components/mobile-warning.tsx
+++ b/apps/snow-leopard/components/mobile-warning.tsx
@@ -2,6 +2,7 @@
import { usePathname } from 'next/navigation';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
+import { T } from 'gt-next';
// Only display on the root and documents pages
@@ -19,12 +20,16 @@ export default function MobileWarning() {
- Snow Leopard works best on desktop
+
+ Snow Leopard works best on desktop
+
-
- For the best experience, please use a desktop device.
-
+
+
+ For the best experience, please use a desktop device.
+
+
diff --git a/apps/snow-leopard/components/onboard.tsx b/apps/snow-leopard/components/onboard.tsx
index 88fd840d..01a74fcd 100644
--- a/apps/snow-leopard/components/onboard.tsx
+++ b/apps/snow-leopard/components/onboard.tsx
@@ -6,6 +6,7 @@ import { useSWRConfig } from 'swr';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { toast } from '@/components/toast';
+import { T, useGT } from 'gt-next';
import Image from 'next/image';
interface OnboardProps {
@@ -18,6 +19,7 @@ export function Onboard({ isOpen, onOpenChange, required = false }: OnboardProps
const [isLoading, setIsLoading] = useState(false);
const router = useRouter();
const { mutate } = useSWRConfig();
+ const t = useGT();
const handleStartTrial = async () => {
setIsLoading(true);
@@ -25,20 +27,20 @@ export function Onboard({ isOpen, onOpenChange, required = false }: OnboardProps
const res = await fetch('/api/user/start-trial', { method: 'POST' });
const data = await res.json();
if (!res.ok) {
- toast({ type: 'error', description: data.error || 'Could not start trial.' });
+ toast({ type: 'error', description: data.error || t('Could not start trial.') });
} else if (data.alreadyInTrial) {
- toast({ type: 'info', description: 'You already have an active trial.' });
+ toast({ type: 'info', description: t('You already have an active trial.') });
} else if (data.alreadyActive) {
- toast({ type: 'info', description: 'You already have an active subscription.' });
+ toast({ type: 'info', description: t('You already have an active subscription.') });
} else {
- toast({ type: 'success', description: 'Free trial started! Enjoy.' });
+ toast({ type: 'success', description: t('Free trial started! Enjoy.') });
onOpenChange?.(false);
await mutate('/api/user/subscription-status');
router.refresh();
}
} catch (err) {
console.error('Start trial error:', err);
- toast({ type: 'error', description: 'Unexpected error starting trial.' });
+ toast({ type: 'error', description: t('Unexpected error starting trial.') });
} finally {
setIsLoading(false);
}
@@ -64,15 +66,21 @@ export function Onboard({ isOpen, onOpenChange, required = false }: OnboardProps
/>
-
snow leopard
+
+ snow leopard
+