Skip to content

Commit

Permalink
feat: i18n (All-Hands-AI#723)
Browse files Browse the repository at this point in the history
* feat: i18n

* fix: ci lint error

* fix: pnpm run pre script not trigger

---------

Co-authored-by: Jim Su <[email protected]>
  • Loading branch information
94mashiro and yimothysu authored Apr 4, 2024
1 parent baa981c commit 0534c14
Show file tree
Hide file tree
Showing 15 changed files with 7,332 additions and 3,164 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ build:
rm -rf node_modules; \
fi
@which corepack > /dev/null || (echo "Installing corepack..." && npm install -g corepack)
@cd frontend && corepack enable && pnpm install
@cd frontend && corepack enable && pnpm install && pnpm run make-i18n

# Start backend
start-backend:
Expand Down
3 changes: 3 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# i18n translation files make by script using `make build`
public/locales/**/*
src/i18n/declaration.ts
1 change: 1 addition & 0 deletions frontend/.npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
public-hoist-pattern[]=*@nextui-org/*
enable-pre-post-scripts=true
10,082 changes: 6,960 additions & 3,122 deletions frontend/package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@
"@xterm/xterm": "^5.4.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"framer-motion": "^11.0.24",
"i18next": "^23.10.1",
"i18next-browser-languagedetector": "^7.2.1",
"i18next-http-backend": "^2.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^14.1.0",
"react-redux": "^9.1.0",
"react-syntax-highlighter": "^15.5.0",
"tailwind-merge": "^2.2.2",
Expand All @@ -39,6 +43,8 @@
"build": "tsc && vite build",
"test": "jest",
"preview": "vite preview",
"make-i18n": "node scripts/make-i18n-translations.cjs",
"prelint": "pnpm run make-i18n",
"lint": "eslint src/**/*.ts* && prettier --check src/**/*.ts*",
"prepare": "cd .. && husky install frontend/.husky"
},
Expand Down
98 changes: 98 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions frontend/scripts/make-i18n-translations.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const fs = require("fs");
const path = require("path");
const i18n = require("../src/i18n/translation.json");

// { [lang]: { [key]: content } }
const translationMap = {};

Object.entries(i18n).forEach(([key, transMap]) => {
Object.entries(transMap).forEach(([lang, content]) => {
if (!translationMap[lang]) {
translationMap[lang] = {};
}
translationMap[lang][key] = content;
})
});

// remove old locales directory
const localesPath = path.join(__dirname, "../public/locales");
if (fs.existsSync(localesPath)) {
fs.rmSync(localesPath, { recursive: true });
}

// write translation files
Object.entries(translationMap).forEach(([lang, transMap]) => {
const filePath = path.join(__dirname, `../public/locales/${lang}/translation.json`);
if (!fs.existsSync(filePath)) {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
}
fs.writeFileSync(filePath, JSON.stringify(transMap, null, 2));
});

// write translation key enum
const transKeys = Object.keys(translationMap.en);
const transKeyDeclareFilePath = path.join(__dirname, "../src/i18n/declaration.ts");
if (!fs.existsSync(transKeyDeclareFilePath)) {
fs.mkdirSync(path.dirname(transKeyDeclareFilePath), { recursive: true });
}
fs.writeFileSync(transKeyDeclareFilePath, `
// this file generate by script, don't modify it manually!!!
export enum I18nKey {
${transKeys.map(key => ` ${key} = "${key}",`).join('\n')}
}`.trim() + '\n');
6 changes: 5 additions & 1 deletion frontend/src/components/ChatInterface.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Card, CardBody } from "@nextui-org/react";
import React, { useEffect, useRef } from "react";
import { useSelector } from "react-redux";
import { useTranslation } from "react-i18next";
import assistantAvatar from "../assets/assistant-avatar.png";
import CogTooth from "../assets/cog-tooth";
import userAvatar from "../assets/user-avatar.png";
Expand All @@ -14,6 +15,7 @@ import {
import { RootState } from "../store";
import { Message } from "../state/chatSlice";
import Input from "./Input";
import { I18nKey } from "../i18n/declaration";

interface IChatBubbleProps {
msg: Message;
Expand Down Expand Up @@ -169,14 +171,16 @@ function MessageList(): JSX.Element {
}

function InitializingStatus(): JSX.Element {
const { t } = useTranslation();

return (
<div className="flex items-center m-auto h-full">
<img
src={assistantAvatar}
alt="assistant avatar"
className="w-[40px] h-[40px] mx-2.5"
/>
<div>Initializing agent (may take up to 10 seconds)...</div>
<div>{t(I18nKey.CHAT_INTERFACE$INITIALZING_AGENT_LOADING_MESSAGE)}</div>
</div>
);
}
Expand Down
7 changes: 5 additions & 2 deletions frontend/src/components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import React, { ChangeEvent, useState, KeyboardEvent } from "react";
import { useSelector } from "react-redux";
import { Textarea } from "@nextui-org/react";
import { twMerge } from "tailwind-merge";
import { useTranslation } from "react-i18next";
import { RootState } from "../store";
import useInputComposition from "../hooks/useInputComposition";
import { sendChatMessage } from "../services/chatService";
import { I18nKey } from "../i18n/declaration";

function Input() {
const { t } = useTranslation();
const { initialized } = useSelector((state: RootState) => state.task);
const [inputMessage, setInputMessage] = useState("");

Expand Down Expand Up @@ -54,7 +57,7 @@ function Input() {
onKeyDown={handleSendMessageOnEnter}
onCompositionStart={onCompositionStart}
onCompositionEnd={onCompositionEnd}
placeholder="Send a message (won't interrupt the Assistant)"
placeholder={t(I18nKey.CHAT_INTERFACE$INPUT_PLACEHOLDER)}
/>
<button
type="button"
Expand All @@ -65,7 +68,7 @@ function Input() {
onClick={handleSendMessage}
disabled={!initialized}
>
Send
{t(I18nKey.CHAT_INTERFACE$INPUT_SEND_MESSAGE_BUTTON_CONTENT)}
</button>
</div>
);
Expand Down
Loading

0 comments on commit 0534c14

Please sign in to comment.