Skip to content

Commit

Permalink
feat: support i18n (#333)
Browse files Browse the repository at this point in the history
* setup i18n

* setup i18n

* setup i18n

* refactor: i18n

* refactor: i18n

* fixes

* fixes

* fix package lock

* install i18next

* refactor: i18n in visor

* fix: remove i18n lib

* add readme

* add readme

* add readme

* fix
  • Loading branch information
paulclindo authored Jun 15, 2024
1 parent 4529ff5 commit cfad0de
Show file tree
Hide file tree
Showing 59 changed files with 885 additions and 843 deletions.
1 change: 0 additions & 1 deletion apps/shinkai-app/.nvmrc

This file was deleted.

1 change: 0 additions & 1 deletion apps/shinkai-desktop/.nvmrc

This file was deleted.

58 changes: 33 additions & 25 deletions apps/shinkai-desktop/src/pages/agents.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { DotsVerticalIcon } from '@radix-ui/react-icons';
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import {
EditAgentFormSchema,
editAgentSchema,
Expand Down Expand Up @@ -39,6 +40,7 @@ import { getModelObject } from './create-agent';
import { SimpleLayout } from './layout/simple-layout';

const AgentsPage = () => {
const { t } = useTranslation();
const auth = useAuth((state) => state.auth);
const navigate = useNavigate();
const { agents } = useAgents({
Expand All @@ -63,15 +65,15 @@ const AgentsPage = () => {
navigate('/add-agent');
};
return (
<SimpleLayout classname="relative" title="AIs">
<SimpleLayout classname="relative" title={t('agents.label')}>
<div className="absolute right-3 top-[36px]">
<Button
className="h-[40px] gap-2"
onClick={onAddAgentClick}
size="auto"
>
<Plus className="h-4 w-4" />
<span>Add AI</span>
<span>{t('agents.add')}</span>
</Button>
</div>
<div className="flex h-full flex-col space-y-3">
Expand All @@ -81,14 +83,15 @@ const AgentsPage = () => {
<span aria-hidden className="text-5xl">
🤖
</span>
<p className="text-2xl font-semibold">No available agents</p>
<p className="text-2xl font-semibold">
{t('agents.notFound.title')}
</p>
<p className="text-center text-sm font-medium text-gray-100">
Connect your first agent to start asking Shinkai AI. Try
connecting OpenAI
{t('agents.notFound.description')}
</p>
</div>

<Button onClick={onAddAgentClick}>Add AI</Button>
<Button onClick={onAddAgentClick}>{t('agents.add')}</Button>
</div>
) : (
<ScrollArea className="flex h-full flex-col justify-between [&>div>div]:!block">
Expand Down Expand Up @@ -123,6 +126,7 @@ function AgentCard({
externalUrl: string;
agentApiKey: string;
}) {
const { t } = useTranslation();
const [isDeleteAgentDrawerOpen, setIsDeleteAgentDrawerOpen] =
React.useState(false);
const [isEditAgentDrawerOpen, setIsEditAgentDrawerOpen] =
Expand All @@ -141,7 +145,7 @@ function AgentCard({
role="button"
>
<div className="flex items-center gap-3">
<div className="flex h-8 w-8 items-center justify-center rounded-lg ">
<div className="flex h-8 w-8 items-center justify-center rounded-lg">
<BotIcon className="h-6 w-6" />
</div>
<div className="flex flex-col items-baseline gap-2">
Expand Down Expand Up @@ -169,7 +173,7 @@ function AgentCard({
role="button"
tabIndex={0}
>
<span className="sr-only">More options</span>
<span className="sr-only">{t('common.moreOptions')}</span>
<DotsVerticalIcon className="text-gray-100" />
</div>
</DropdownMenuTrigger>
Expand All @@ -179,14 +183,14 @@ function AgentCard({
>
{[
{
name: 'Edit',
name: t('common.edit'),
icon: <Edit className="mr-3 h-4 w-4" />,
onClick: () => {
setIsEditAgentDrawerOpen(true);
},
},
{
name: 'Delete',
name: t('common.delete'),
icon: <TrashIcon className="mr-3 h-4 w-4" />,
onClick: () => {
setIsDeleteAgentDrawerOpen(true);
Expand Down Expand Up @@ -247,6 +251,7 @@ const EditAgentDrawer = ({
agentExternalUrl: string;
agentApiKey: string;
}) => {
const { t } = useTranslation();
const auth = useAuth((state) => state.auth);

const form = useForm<EditAgentFormSchema>({
Expand All @@ -272,10 +277,10 @@ const EditAgentDrawer = ({
const { mutateAsync: updateAgent, isPending } = useUpdateAgent({
onSuccess: () => {
onOpenChange(false);
toast.success('AI updated successfully');
toast.success(t('agents.success.updateAgent'));
},
onError: (error) => {
toast.error('Error updating agent', {
toast.error(t('agents.errors.updateAgent'), {
description: typeof error === 'string' ? error : error.message,
});
},
Expand Down Expand Up @@ -313,7 +318,7 @@ const EditAgentDrawer = ({
<SheetContent>
<SheetHeader className="mb-6">
<SheetTitle className="font-normal">
Update <span className="font-medium">{agentId}</span>{' '}
{t('common.update')} <span className="font-medium">{agentId}</span>{' '}
</SheetTitle>
</SheetHeader>
<Form {...form}>
Expand All @@ -327,38 +332,41 @@ const EditAgentDrawer = ({
disabled
name="agentName"
render={({ field }) => (
<TextField field={field} label="AI Name" />
<TextField field={field} label={t('agents.form.agentName')} />
)}
/>

<FormField
control={form.control}
name="externalUrl"
render={({ field }) => (
<TextField field={field} label="External URL" />
<TextField
field={field}
label={t('agents.form.externalUrl')}
/>
)}
/>

<FormField
control={form.control}
name="apikey"
render={({ field }) => (
<TextField field={field} label="API Key" />
<TextField field={field} label={t('agents.form.apiKey')} />
)}
/>

<FormField
control={form.control}
name="modelCustom"
render={({ field }) => (
<TextField field={field} label={'Model Name'} />
<TextField field={field} label={t('agents.form.modelName')} />
)}
/>
<FormField
control={form.control}
name="modelTypeCustom"
render={({ field }) => (
<TextField field={field} label={'Model ID'} />
<TextField field={field} label={t('agents.form.modelId')} />
)}
/>
</div>
Expand All @@ -368,7 +376,7 @@ const EditAgentDrawer = ({
isLoading={isPending}
type="submit"
>
Save
{t('common.save')}
</Button>
</form>
</Form>
Expand All @@ -385,14 +393,15 @@ const RemoveAgentDrawer = ({
onOpenChange: (open: boolean) => void;
agentId: string;
}) => {
const { t } = useTranslation();
const auth = useAuth((state) => state.auth);
const { mutateAsync: deleteAgent, isPending } = useDeleteAgent({
onSuccess: () => {
onOpenChange(false);
toast.success('AI deleted successfully');
toast.success(t('agents.success.deleteAgent'));
},
onError: (error) => {
toast.error('Error deleting agent', {
toast.error(t('agents.errors.deleteAgent'), {
description: typeof error === 'string' ? error : error.message,
});
},
Expand All @@ -403,13 +412,12 @@ const RemoveAgentDrawer = ({
<SheetContent>
<SheetHeader>
<SheetTitle className="font-normal">
Delete AI
{t('agents.delete.label')}
<span className="font-medium">{agentId}</span>{' '}
</SheetTitle>
</SheetHeader>
<p className="text-gray-80 my-3 text-base">
Are you sure you want to delete this agent? This action cannot be
undone.
{t('agents.delete.description')}
</p>
<SheetFooter>
<Button
Expand All @@ -431,7 +439,7 @@ const RemoveAgentDrawer = ({
}}
variant="destructive"
>
Delete
{t('common.delete')}
</Button>
</SheetFooter>
</SheetContent>
Expand Down
6 changes: 4 additions & 2 deletions apps/shinkai-desktop/src/pages/ai-model-installation.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import { buttonVariants } from '@shinkai_network/shinkai-ui';
import { cn } from '@shinkai_network/shinkai-ui/utils';
import { QueryClientProvider } from '@tanstack/react-query';
Expand All @@ -10,11 +11,12 @@ import { shinkaiNodeQueryClient } from '../lib/shinkai-node-manager/shinkai-node
import { FixedHeaderLayout } from './layout/simple-layout';

const AIModelInstallation = () => {
const { t } = useTranslation();
return (
<QueryClientProvider client={shinkaiNodeQueryClient}>
<FixedHeaderLayout
className="relative flex w-full max-w-6xl flex-col gap-2 px-4"
title="Install AI"
title={t('agents.installAI')}
>
<ResourcesBanner />
<OllamaModels />
Expand All @@ -28,7 +30,7 @@ const AIModelInstallation = () => {
)}
to={{ pathname: '/' }}
>
Continue
{t('common.continue')}
<ArrowRight className="h-4 w-4" />
</Link>
</div>
Expand Down
9 changes: 5 additions & 4 deletions apps/shinkai-desktop/src/pages/ai-model-locally.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import { buttonVariants } from '@shinkai_network/shinkai-ui';
import { cn } from '@shinkai_network/shinkai-ui/utils';
import { QueryClientProvider } from '@tanstack/react-query';
Expand All @@ -9,15 +10,15 @@ import { shinkaiNodeQueryClient } from '../lib/shinkai-node-manager/shinkai-node
import { SubpageLayout } from './layout/simple-layout';

const AgentsLocally = () => {
const { t } = useTranslation();
return (
<QueryClientProvider client={shinkaiNodeQueryClient}>
<SubpageLayout
className="relative flex w-full max-w-6xl flex-col gap-2 px-4"
title="Install AI Models"
title={t('agents.localAI.installTitle')}
>
<p className="text-gray-80 pb-2 text-sm">
After installing AI models on your local machine, they will become
available as AI
{t('agents.localAI.installText')}
</p>
<OllamaModels />
<div className="absolute right-4 top-6 flex justify-center pt-3">
Expand All @@ -31,7 +32,7 @@ const AgentsLocally = () => {
to={{ pathname: '/add-agent' }}
>
<Plus className="h-4 w-4" />
Manually Add AI
{t('agents.addManually')}
</Link>
</div>
</SubpageLayout>
Expand Down
10 changes: 6 additions & 4 deletions apps/shinkai-desktop/src/pages/analytics.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import { Button } from '@shinkai_network/shinkai-ui';
import { useNavigate } from 'react-router-dom';

Expand All @@ -6,17 +7,18 @@ import OnboardingLayout from './layout/onboarding-layout';

const AnalyticsPage = () => {
const navigate = useNavigate();
const { t } = useTranslation();
const denyAnalytics = useSettings((state) => state.denyAnalytics);
const acceptAnalytics = useSettings((state) => state.acceptAnalytics);

return (
<OnboardingLayout>
<div className="mx-auto flex h-full max-w-lg flex-col">
<p className="text-center text-3xl font-medium leading-[1.5] tracking-wide">
Help us improve Shinkai
{t('analytics.title')}
</p>
<div className="mt-10 flex flex-1 flex-col gap-10 text-sm text-gray-50">
<ul className="space-y-3 text-gray-50">
<ul className="space-y-3 text-gray-50">
{[
'✅ Always allow you to opt-out via Settings',

Expand Down Expand Up @@ -57,7 +59,7 @@ const AnalyticsPage = () => {
size="lg"
variant="ghost"
>
No Thanks
{t('common.noThanks')}
</Button>
<Button
className="w-full"
Expand All @@ -67,7 +69,7 @@ const AnalyticsPage = () => {
}}
size="lg"
>
I Agree
{t('common.iAgree')}
</Button>
</div>
</div>
Expand Down
Loading

0 comments on commit cfad0de

Please sign in to comment.