@@ -17,18 +17,21 @@ import {
1717 IconCloseCircle ,
1818 IconDesktop ,
1919 IconDown ,
20+ IconLanguage ,
2021 IconLink ,
2122 IconMoonFill ,
2223 IconSunFill ,
2324} from "@arco-design/web-react/icon" ;
24- import React , { ReactNode , useRef , useState } from "react" ;
25+ import React , { ReactNode , useEffect , useRef , useState } from "react" ;
2526import { useTranslation } from "react-i18next" ;
2627import "./index.css" ;
2728import { useAppDispatch , useAppSelector } from "@App/pages/store/hooks" ;
2829import { selectThemeMode , setDarkMode } from "@App/pages/store/features/config" ;
2930import { RiFileCodeLine , RiImportLine , RiPlayListAddLine , RiTerminalBoxLine , RiTimerLine } from "react-icons/ri" ;
3031import { scriptClient } from "@App/pages/store/features/script" ;
3132import { useDropzone } from "react-dropzone" ;
33+ import i18n , { matchLanguage } from "@App/locales/locales" ;
34+ import { systemConfig } from "@App/pages/store/global" ;
3235
3336const readFile = ( file : File ) : Promise < string > => {
3437 return new Promise ( ( resolve ) => {
@@ -57,7 +60,6 @@ const uploadFiles = async (files: File[], importByUrlsFunc: (urls: string[]) =>
5760 importByUrlsFunc ( urls ) ;
5861} ;
5962
60-
6163const MainLayout : React . FC < {
6264 children : ReactNode ;
6365 className : string ;
@@ -67,6 +69,7 @@ const MainLayout: React.FC<{
6769 const dispatch = useAppDispatch ( ) ;
6870 const importRef = useRef < RefTextAreaType > ( null ) ;
6971 const [ importVisible , setImportVisible ] = useState ( false ) ;
72+ const [ showLanguage , setShowLanguage ] = useState ( false ) ;
7073 const { t } = useTranslation ( ) ;
7174
7275 const importByUrlsLocal = async ( urls : string [ ] ) => {
@@ -104,6 +107,30 @@ const MainLayout: React.FC<{
104107 } ,
105108 } ) ;
106109
110+ const languageList : { key : string ; title : string } [ ] = [ ] ;
111+ Object . keys ( i18n . store . data ) . forEach ( ( key ) => {
112+ if ( key === "ach-UG" ) {
113+ return ;
114+ }
115+ languageList . push ( {
116+ key,
117+ title : i18n . store . data [ key ] . title as string ,
118+ } ) ;
119+ } ) ;
120+ languageList . push ( {
121+ key : "help" ,
122+ title : t ( "help_translate" ) ,
123+ } ) ;
124+
125+ useEffect ( ( ) => {
126+ // 当没有匹配语言且系统配置中没有设置语言时显示语言按钮
127+ matchLanguage ( ) . then ( ( result ) => {
128+ if ( ! result ) {
129+ setShowLanguage ( true ) ;
130+ }
131+ } ) ;
132+ } ) ;
133+
107134 return (
108135 < ConfigProvider
109136 renderEmpty = { ( ) => {
@@ -130,12 +157,7 @@ const MainLayout: React.FC<{
130157 setImportVisible ( false ) ;
131158 } }
132159 >
133- < Input . TextArea
134- ref = { importRef }
135- rows = { 8 }
136- placeholder = { t ( "import_script_placeholder" ) }
137- defaultValue = ""
138- />
160+ < Input . TextArea ref = { importRef } rows = { 8 } placeholder = { t ( "import_script_placeholder" ) } defaultValue = "" />
139161 </ Modal >
140162 < div className = "flex row items-center" >
141163 < img style = { { height : "40px" } } src = "/assets/logo.png" alt = "ScriptCat" />
@@ -232,6 +254,40 @@ const MainLayout: React.FC<{
232254 className = "!text-lg"
233255 />
234256 </ Dropdown >
257+ { showLanguage && (
258+ < Dropdown
259+ droplist = {
260+ < Menu >
261+ { languageList . map ( ( value ) => (
262+ < Menu . Item
263+ key = { value . key }
264+ onClick = { ( ) => {
265+ if ( value . key === "help" ) {
266+ window . open ( "https://crowdin.com/project/scriptcat" , "_blank" ) ;
267+ return ;
268+ }
269+ systemConfig . setLanguage ( value . key ) ;
270+ Message . success ( t ( "language_change_tip" ) ! ) ;
271+ } }
272+ >
273+ { value . title }
274+ </ Menu . Item >
275+ ) ) }
276+ </ Menu >
277+ }
278+ >
279+ < Button
280+ type = "text"
281+ size = "small"
282+ iconOnly
283+ icon = { < IconLanguage /> }
284+ style = { {
285+ color : "var(--color-text-1)" ,
286+ } }
287+ className = "!text-lg"
288+ > </ Button >
289+ </ Dropdown >
290+ ) }
235291 </ Space >
236292 </ Layout . Header >
237293 < Layout
0 commit comments