Skip to content

Commit

Permalink
feat(i18n): add ErrorCode and DeviceCheck i18n (#774)
Browse files Browse the repository at this point in the history
  • Loading branch information
Leooeloel authored Jun 29, 2021
1 parent f9e4fa6 commit 6e5c84b
Show file tree
Hide file tree
Showing 34 changed files with 442 additions and 284 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { observer } from "mobx-react-lite";
import { ChatMessageListReplay } from "./ChatMessageListReplay";
import { ClassRoomReplayStore } from "../../stores/ClassRoomReplayStore";
import { useTranslation } from "react-i18next";

export interface ChatMessagesReplayProps {
classRoomReplayStore: ClassRoomReplayStore;
Expand All @@ -10,6 +11,7 @@ export interface ChatMessagesReplayProps {
export const ChatMessagesReplay = observer<ChatMessagesReplayProps>(function ChatMessagesReplay({
classRoomReplayStore,
}) {
const { t } = useTranslation();
return (
<div className="chat-messages-wrap">
<div className="chat-messages">
Expand All @@ -18,7 +20,7 @@ export const ChatMessagesReplay = observer<ChatMessagesReplayProps>(function Cha
{<ChatMessageListReplay classRoomReplayStore={classRoomReplayStore} />}
</div>
) : (
<div className="chat-messages-default">无消息...</div>
<div className="chat-messages-default">{t("no-message-tips")}</div>
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Tabs } from "antd";
import { observer } from "mobx-react-lite";
import { ChatMessagesReplay } from "./ChatMessagesReplay";
import { ClassRoomReplayStore } from "../../stores/ClassRoomReplayStore";
import { useTranslation } from "react-i18next";

export interface ChatPanelReplayProps {
classRoomReplayStore: ClassRoomReplayStore;
Expand All @@ -11,10 +12,11 @@ export interface ChatPanelReplayProps {
export const ChatPanelReplay = observer<ChatPanelReplayProps>(function ChatPanelReplay({
classRoomReplayStore,
}) {
const { t } = useTranslation();
return (
<div className="chat-panel">
<Tabs defaultActiveKey="messages" tabBarGutter={0}>
<Tabs.TabPane tab="消息列表" key="messages">
<Tabs.TabPane tab={t("messages")} key="messages">
<ChatMessagesReplay classRoomReplayStore={classRoomReplayStore} />
</Tabs.TabPane>
</Tabs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { useHistory, useLocation } from "react-router-dom";
import { MainPageLayout, MainPageLayoutItem, MainPageLayoutProps } from "flat-components";
import { routeConfig, RouteNameType } from "../../route-config";
import { GlobalStoreContext } from "../StoreProvider";
import { useTranslation } from "react-i18next";

export interface MainPageLayoutContainerProps {
subMenu?: MainPageLayoutItem[];
Expand All @@ -30,6 +31,7 @@ export const MainPageLayoutContainer: React.FC<MainPageLayoutContainerProps> = (
activeKeys,
onRouteChange,
}) => {
const { t } = useTranslation();
const sideMenu = [
{
key: routeConfig[RouteNameType.HomePage].path,
Expand Down Expand Up @@ -64,25 +66,25 @@ export const MainPageLayoutContainer: React.FC<MainPageLayoutContainerProps> = (
{
key: routeConfig[RouteNameType.GeneralSettingPage].path,
icon: (): React.ReactNode => <img src={settingSVG} />,
title: "个人设置",
title: t("settings"),
route: routeConfig[RouteNameType.GeneralSettingPage].path,
},
{
key: "getGitHubCode",
icon: (): React.ReactNode => <img src={gitHubSVG} />,
title: "获取源码",
title: t("source-code"),
route: "https://github.com/netless-io/flat/",
},
{
key: "feedback",
icon: (): React.ReactNode => <img src={feedbackSVG} />,
title: "反馈意见",
title: t("feedback"),
route: "https://github.com/netless-io/flat/issues",
},
{
key: "logout",
icon: (): React.ReactNode => <img src={logoutSVG} />,
title: <span className="logout-title">退出登录</span>,
title: <span className="logout-title">{t("logout")}</span>,
route: routeConfig[RouteNameType.LoginPage].path,
},
];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { observer } from "mobx-react-lite";
import { Button, Modal } from "antd";
import { useTranslation } from "react-i18next";

interface ExitReplayConfirmModalProps {
visible: boolean;
Expand All @@ -10,21 +11,22 @@ interface ExitReplayConfirmModalProps {

export const ExitReplayConfirmModal = observer<ExitReplayConfirmModalProps>(
function ExitReplayConfirmModal({ visible, onCancel, onConfirm }) {
const { t } = useTranslation();
return (
<Modal
title={"退出回放"}
title={t("exit-replay")}
visible={visible}
onCancel={onCancel}
footer={[
<Button key="exit-cancel" onClick={onCancel}>
取消
{t("cancel")}
</Button>,
<Button key="exit-confirm" onClick={onConfirm}>
确定
{t("confirm")}
</Button>,
]}
>
确定退出回放?
{t("exit-reply-tips")}
</Modal>
);
},
Expand Down
3 changes: 2 additions & 1 deletion desktop/renderer-app/src/components/Tips/ErrorTips.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { message } from "antd";
import { ServerRequestError } from "../../utils/error/ServerRequestError";
import { NODE_ENV } from "../../constants/Process";
import { i18n } from "../../utils/i18n";

export const errorTips = (e: Error): void => {
if (NODE_ENV === "development") {
console.error(e);
}

if (e instanceof ServerRequestError) {
void message.error(e.errorMessage);
void message.error(i18n.t(e.errorMessage));
} else {
void message.error(e.message);
}
Expand Down
44 changes: 22 additions & 22 deletions desktop/renderer-app/src/constants/ErrorCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,28 @@ export enum RequestErrorCode {

export const RequestErrorMessage = {
// request parameter error
[RequestErrorCode.ParamsCheckFailed]: "参数错误",
[RequestErrorCode.ParamsCheckFailed]: "parameter-error",
// this error may occur in high concurrency situations, the request should be retried
[RequestErrorCode.ServerFail]: "请求失败",
[RequestErrorCode.ServerFail]: "request-failed",
// server operation failed, possibly due to database failure or other reasons
[RequestErrorCode.CurrentProcessFailed]: "请求出错",
[RequestErrorCode.NotPermission]: "没有权限操作",
[RequestErrorCode.NeedLoginAgain]: "凭证已过期,请重新登录",
[RequestErrorCode.UnsupportedPlatform]: "不支持的登录平台",
[RequestErrorCode.JWTSignFailed]: "认证信息校验失败,请重新登录",

[RequestErrorCode.RoomNotFound]: "房间不存在",
[RequestErrorCode.RoomIsEnded]: "房间已结束",
[RequestErrorCode.RoomIsRunning]: "房间正在进行中",
[RequestErrorCode.RoomNotIsRunning]: "房间不在进行中",
[RequestErrorCode.RoomNotIsEnded]: "房间还未结束",
[RequestErrorCode.RoomNotIsIdle]: "房间还未开始",

[RequestErrorCode.PeriodicNotFound]: "周期性房间不存在",
[RequestErrorCode.PeriodicIsEnded]: "周期性房间已结束",
[RequestErrorCode.PeriodicSubRoomHasRunning]: "周期性子房间不存在",

[RequestErrorCode.UserNotFound]: "用户不存在",

[RequestErrorCode.RecordNotFound]: "回放不存在",
[RequestErrorCode.CurrentProcessFailed]: "request-error",
[RequestErrorCode.NotPermission]: "no-permission",
[RequestErrorCode.NeedLoginAgain]: "voucher-expired",
[RequestErrorCode.UnsupportedPlatform]: "unsupported-login-platforms",
[RequestErrorCode.JWTSignFailed]: "authentication-information-verification-failed",

[RequestErrorCode.RoomNotFound]: "room-does-not-exist",
[RequestErrorCode.RoomIsEnded]: "the-room-has-ended",
[RequestErrorCode.RoomIsRunning]: "the-room-is-in-progress",
[RequestErrorCode.RoomNotIsRunning]: "the-room-is-not-in-progress",
[RequestErrorCode.RoomNotIsEnded]: "the-room-is-not-over-yet",
[RequestErrorCode.RoomNotIsIdle]: "the-room-has-not-yet-started",

[RequestErrorCode.PeriodicNotFound]: "periodic-rooms-do-not-exist",
[RequestErrorCode.PeriodicIsEnded]: "periodic-rooms-have-ended",
[RequestErrorCode.PeriodicSubRoomHasRunning]: "periodic-sub-rooms-do-not-exist",

[RequestErrorCode.UserNotFound]: "user-does-not-exist",

[RequestErrorCode.RecordNotFound]: "replay-does-not-exist",
};
28 changes: 13 additions & 15 deletions desktop/renderer-app/src/pages/BigClassPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export type BigClassPageProps = {};
export const BigClassPage = observer<BigClassPageProps>(function BigClassPage() {
usePowerSaveBlocker();
useWindowSize("Class");

const { t } = useTranslation();
const params = useParams<RouteParams<RouteNameType.BigClassPage>>();

const classRoomStore = useClassRoomStore(params.roomUUID, params.ownerUUID, recordingConfig);
Expand All @@ -102,8 +102,6 @@ export const BigClassPage = observer<BigClassPageProps>(function BigClassPage()

const updateLayoutTimeoutRef = useRef(NaN);

const { t } = useTranslation();

// control whiteboard writable
useEffect(() => {
if (!classRoomStore.isCreator && classRoomStore.users.currentUser) {
Expand Down Expand Up @@ -214,13 +212,13 @@ export const BigClassPage = observer<BigClassPageProps>(function BigClassPage()
<>
<TopBarRoundBtn iconName="class-pause" onClick={classRoomStore.pauseClass}>
{classRoomStore.roomStatusLoading === RoomStatusLoadingType.Pausing
? "暂停中..."
: "暂停上课"}
? t("pausing")
: t("pause")}
</TopBarRoundBtn>
<TopBarRoundBtn iconName="class-stop" onClick={stopClass}>
{classRoomStore.roomStatusLoading === RoomStatusLoadingType.Stopping
? "结束中..."
: "结束上课"}
? t("ending")
: t("end-the-class")}
</TopBarRoundBtn>
</>
);
Expand All @@ -230,13 +228,13 @@ export const BigClassPage = observer<BigClassPageProps>(function BigClassPage()
<>
<TopBarRoundBtn iconName="class-pause" onClick={classRoomStore.resumeClass}>
{classRoomStore.roomStatusLoading === RoomStatusLoadingType.Starting
? "开始中..."
: "恢复上课"}
? t("starting")
: t("resume")}
</TopBarRoundBtn>
<TopBarRoundBtn iconName="class-stop" onClick={stopClass}>
{classRoomStore.roomStatusLoading === RoomStatusLoadingType.Stopping
? "结束中..."
: "结束上课"}
? t("ending")
: t("end-the-class")}
</TopBarRoundBtn>
</>
);
Expand All @@ -249,8 +247,8 @@ export const BigClassPage = observer<BigClassPageProps>(function BigClassPage()
>
<TopBarRoundBtn iconName="class-begin" onClick={classRoomStore.startClass}>
{classRoomStore.roomStatusLoading === RoomStatusLoadingType.Starting
? "开始中..."
: "开始上课"}
? t("starting")
: t("start")}
</TopBarRoundBtn>
</RecordHintTips>
);
Expand Down Expand Up @@ -376,10 +374,10 @@ export const BigClassPage = observer<BigClassPageProps>(function BigClassPage()
}
if (room.state.broadcastState.mode !== ViewMode.Broadcaster) {
room.setViewMode(ViewMode.Broadcaster);
void message.success("其他用户将跟随您的视角");
void message.success(t("follow-your-perspective-tips"));
} else {
room.setViewMode(ViewMode.Freedom);
void message.success("其他用户将停止跟随您的视角");
void message.success(t("Stop-following-your-perspective-tips"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { useRTCEngine } from "../../../utils/hooks/useRTCEngine";
import { DeviceCheckLayoutContainer } from "../DeviceCheckLayoutContainer";
import { routeConfig } from "../../../route-config";
import { DeviceCheckResults } from "../utils";
import { useTranslation } from "react-i18next";

export const CameraCheckPage = (): React.ReactElement => {
const { t } = useTranslation();
const rtcEngine = useRTCEngine();
const [devices, setDevices] = useState<Device[]>([]);
const [currentDeviceID, setCurrentDeviceID] = useState<string | null>(null);
Expand Down Expand Up @@ -62,17 +64,17 @@ export const CameraCheckPage = (): React.ReactElement => {
return (
<DeviceCheckLayoutContainer>
<div className="camera-check-container">
<p>摄像头</p>
<p>{t("camera")}</p>
<DeviceSelect
devices={devices}
currentDeviceID={currentDeviceID}
onChange={setCurrentDeviceID}
/>
<div className="camera-check-info" ref={cameraStream} />
<div className="camera-check-btn">
<Button onClick={checkFail}>不能看到</Button>
<Button onClick={checkFail}>{t("unable-to-see")}</Button>
<Button onClick={checkSuccess} type="primary">
能看到
{t("able-to-see")}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,38 @@ import { routeConfig, RouteNameType } from "../../route-config";
import { useHistory, useLocation } from "react-router-dom";
import { DeviceCheckState } from "./utils";
import { MainPageLayoutItem } from "flat-components";
import { useTranslation } from "react-i18next";

export const DeviceCheckLayoutContainer: React.FC = ({ children }): React.ReactElement => {
useWindowSize("Main");

const { t } = useTranslation();
const history = useHistory<DeviceCheckState>();
const location = useLocation<DeviceCheckState | undefined>();

const subMenu = [
{
key: routeConfig[RouteNameType.SystemCheckPage].path,
icon: (): React.ReactNode => <img src={systemSVG} />,
title: "系统检测",
title: t("system-testing"),
route: routeConfig[RouteNameType.SystemCheckPage].path,
},
{
key: routeConfig[RouteNameType.CameraCheckPage].path,
icon: (): React.ReactNode => <img src={cameraSVG} />,
title: "摄像头检测",
title: t("camera-testing"),
route: routeConfig[RouteNameType.CameraCheckPage].path,
},
{
key: routeConfig[RouteNameType.SpeakerCheckPage].path,
icon: (): React.ReactNode => <img src={speakerSVG} />,
title: "扬声器检测",
title: t("headphone-testing"),
route: routeConfig[RouteNameType.SpeakerCheckPage].path,
},
{
key: routeConfig[RouteNameType.MicrophoneCheckPage].path,
icon: (): React.ReactNode => <img src={microphoneSVG} />,
title: "麦克风检测",
title: t("microphone-testing"),
route: routeConfig[RouteNameType.MicrophoneCheckPage].path,
},
];
Expand Down
Loading

0 comments on commit 6e5c84b

Please sign in to comment.