add some zh-CN translations
This commit is contained in:
parent
5bd04045b1
commit
85b51fe5c1
|
|
@ -2,13 +2,16 @@ import type { ParsedUrlQuery } from 'querystring'
|
|||
|
||||
import Link from 'next/link'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
const HomeCrumb = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<Link href="/">
|
||||
<a>
|
||||
<FontAwesomeIcon className="h-3 w-3" icon={['far', 'flag']} />
|
||||
<span className="ml-2 font-medium">Home</span>
|
||||
<span className="ml-2 font-medium">{t('Home')}</span>
|
||||
</a>
|
||||
</Link>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { FC, MouseEventHandler, SetStateAction, useEffect, useRef, useState } fr
|
|||
|
||||
import dynamic from 'next/dynamic'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import useLocalStorage from '../utils/useLocalStorage'
|
||||
import { getPreviewType, preview } from '../utils/getPreviewType'
|
||||
|
|
@ -146,6 +147,8 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
|
|||
const router = useRouter()
|
||||
const [layout, _] = useLocalStorage('preferredLayout', layouts[0])
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const path = queryToPath(query)
|
||||
|
||||
const { data, error, size, setSize } = useProtectedSWRInfinite(path)
|
||||
|
|
@ -166,7 +169,7 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
|
|||
if (!data) {
|
||||
return (
|
||||
<PreviewContainer>
|
||||
<Loading loadingText="Loading ..." />
|
||||
<Loading loadingText={t('Loading ...')} />
|
||||
</PreviewContainer>
|
||||
)
|
||||
}
|
||||
|
|
@ -240,13 +243,13 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
|
|||
downloadMultipleFiles({ toastId, router, files, folder })
|
||||
.then(() => {
|
||||
setTotalGenerating(false)
|
||||
toast.success('Finished downloading selected files.', {
|
||||
toast.success(t('Finished downloading selected files.'), {
|
||||
id: toastId,
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
setTotalGenerating(false)
|
||||
toast.error('Failed to download selected files.', { id: toastId })
|
||||
toast.error(t('Failed to download selected files.'), { id: toastId })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -256,7 +259,13 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
|
|||
const files = (async function* () {
|
||||
for await (const { meta: c, path: p, isFolder, error } of traverseFolder(path)) {
|
||||
if (error) {
|
||||
toast.error(`Failed to download folder ${p}: ${error.status} ${error.message} Skipped it to continue.`)
|
||||
toast.error(
|
||||
t('Failed to download folder {{path}}: {{status}} {{message}} Skipped it to continue.', {
|
||||
path: p,
|
||||
status: error.status,
|
||||
message: error.message
|
||||
})
|
||||
)
|
||||
continue
|
||||
}
|
||||
yield {
|
||||
|
|
@ -280,11 +289,11 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
|
|||
})
|
||||
.then(() => {
|
||||
setFolderGenerating({ ...folderGenerating, [id]: false })
|
||||
toast.success('Finished downloading folder.', { id: toastId })
|
||||
toast.success(t('Finished downloading folder.'), { id: toastId })
|
||||
})
|
||||
.catch(() => {
|
||||
setFolderGenerating({ ...folderGenerating, [id]: false })
|
||||
toast.error('Failed to download folder.', { id: toastId })
|
||||
toast.error(t('Failed to download folder.'), { id: toastId })
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -324,13 +333,13 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
|
|||
{isLoadingMore ? (
|
||||
<>
|
||||
<LoadingIcon className="inline-block h-4 w-4 animate-spin" />
|
||||
<span>Loading ...</span>{' '}
|
||||
<span>{t('Loading ...')}</span>{' '}
|
||||
</>
|
||||
) : isReachingEnd ? (
|
||||
<span>No more files</span>
|
||||
<span>{t('No more files')}</span>
|
||||
) : (
|
||||
<>
|
||||
<span>Load more</span>
|
||||
<span>{t('Load more')}</span>
|
||||
<FontAwesomeIcon icon="chevron-circle-down" />
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import Link from 'next/link'
|
|||
import { FC } from 'react'
|
||||
import { useClipboard } from 'use-clipboard-copy'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import { getBaseUrl } from '../utils/getBaseUrl'
|
||||
import { humanFileSize, formatModifiedDateTime } from '../utils/fileDetails'
|
||||
|
|
@ -44,20 +45,22 @@ const FolderListLayout = ({
|
|||
}) => {
|
||||
const clipboard = useClipboard()
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="rounded bg-white dark:bg-gray-900 dark:text-gray-100">
|
||||
<div className="grid grid-cols-12 items-center space-x-2 border-b border-gray-900/10 px-3 dark:border-gray-500/30">
|
||||
<div className="col-span-12 py-2 text-xs font-bold uppercase tracking-widest text-gray-600 dark:text-gray-300 md:col-span-6">
|
||||
Name
|
||||
{t('Name')}
|
||||
</div>
|
||||
<div className="col-span-3 hidden text-xs font-bold uppercase tracking-widest text-gray-600 dark:text-gray-300 md:block">
|
||||
Last Modified
|
||||
{t('Last Modified')}
|
||||
</div>
|
||||
<div className="hidden text-xs font-bold uppercase tracking-widest text-gray-600 dark:text-gray-300 md:block">
|
||||
Size
|
||||
{t('Size')}
|
||||
</div>
|
||||
<div className="hidden text-xs font-bold uppercase tracking-widest text-gray-600 dark:text-gray-300 md:block">
|
||||
Actions
|
||||
{t('Actions')}
|
||||
</div>
|
||||
<div className="hidden text-xs font-bold uppercase tracking-widest text-gray-600 dark:text-gray-300 md:block">
|
||||
<div className="hidden p-1.5 text-gray-700 dark:text-gray-400 md:flex">
|
||||
|
|
@ -65,13 +68,13 @@ const FolderListLayout = ({
|
|||
checked={totalSelected}
|
||||
onChange={toggleTotalSelected}
|
||||
indeterminate={true}
|
||||
title={'Select files'}
|
||||
title={t('Select files')}
|
||||
/>
|
||||
{totalGenerating ? (
|
||||
<Downloading title="Downloading selected files, refresh page to cancel" />
|
||||
<Downloading title={t('Downloading selected files, refresh page to cancel')} />
|
||||
) : (
|
||||
<button
|
||||
title="Download selected files"
|
||||
title={t('Download selected files')}
|
||||
className="cursor-pointer rounded p-1.5 hover:bg-gray-300 disabled:cursor-not-allowed disabled:text-gray-400 disabled:hover:bg-white dark:hover:bg-gray-600 disabled:dark:text-gray-600 disabled:hover:dark:bg-gray-900"
|
||||
disabled={totalSelected === 0}
|
||||
onClick={handleSelectedDownload}
|
||||
|
|
@ -97,20 +100,20 @@ const FolderListLayout = ({
|
|||
{c.folder ? (
|
||||
<div className="hidden p-1.5 text-gray-700 dark:text-gray-400 md:flex">
|
||||
<span
|
||||
title="Copy folder permalink"
|
||||
title={t('Copy folder permalink')}
|
||||
className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600"
|
||||
onClick={() => {
|
||||
clipboard.copy(`${getBaseUrl()}${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`)
|
||||
toast('Copied folder permalink.', { icon: '👌' })
|
||||
toast(t('Copied folder permalink.'), { icon: '👌' })
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={['far', 'copy']} />
|
||||
</span>
|
||||
{folderGenerating[c.id] ? (
|
||||
<Downloading title="Downloading folder, refresh page to cancel" />
|
||||
<Downloading title={t('Downloading folder, refresh page to cancel')} />
|
||||
) : (
|
||||
<span
|
||||
title="Download folder"
|
||||
title={t('Download folder')}
|
||||
className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600"
|
||||
onClick={() => {
|
||||
const p = `${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`
|
||||
|
|
@ -124,19 +127,19 @@ const FolderListLayout = ({
|
|||
) : (
|
||||
<div className="hidden p-1.5 text-gray-700 dark:text-gray-400 md:flex">
|
||||
<span
|
||||
title="Copy raw file permalink"
|
||||
title={t('Copy raw file permalink')}
|
||||
className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600"
|
||||
onClick={() => {
|
||||
clipboard.copy(
|
||||
`${getBaseUrl()}/api?path=${path === '/' ? '' : path}/${encodeURIComponent(c.name)}&raw=true`
|
||||
)
|
||||
toast.success('Copied raw file permalink.')
|
||||
toast.success(t('Copied raw file permalink.'))
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={['far', 'copy']} />
|
||||
</span>
|
||||
<a
|
||||
title="Download file"
|
||||
title={t('Download file')}
|
||||
className="cursor-pointer rounded px-1.5 py-1 hover:bg-gray-300 dark:hover:bg-gray-600"
|
||||
href={c['@microsoft.graph.downloadUrl']}
|
||||
>
|
||||
|
|
@ -149,7 +152,7 @@ const FolderListLayout = ({
|
|||
<Checkbox
|
||||
checked={selected[c.id] ? 2 : 0}
|
||||
onChange={() => toggleItemSelected(c.id)}
|
||||
title="Select file"
|
||||
title={t('Select file')}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { NextRouter } from 'next/router'
|
||||
import toast from 'react-hot-toast'
|
||||
import JSZip from 'jszip'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import { fetcher } from '../utils/fetchWithSWR'
|
||||
import { getStoredToken } from '../utils/protectedRouteHandler'
|
||||
|
|
@ -12,10 +13,12 @@ import { getStoredToken } from '../utils/protectedRouteHandler'
|
|||
* @returns Toast component with loading progress
|
||||
*/
|
||||
export function DownloadingToast(router: NextRouter, progress?: string) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-56">
|
||||
<span>Downloading {progress ? `${progress}%` : 'selected files...'}</span>
|
||||
<span>{progress ? t('Downloading {{progress}}%', { progress }) : t('Downloading selected files...')}</span>
|
||||
|
||||
<div className="relative mt-2">
|
||||
<div className="overflow-hidden h-1 flex rounded bg-gray-100">
|
||||
|
|
@ -27,7 +30,7 @@ export function DownloadingToast(router: NextRouter, progress?: string) {
|
|||
className="p-2 rounded bg-red-500 hover:bg-red-400 text-white focus:outline-none focus:ring focus:ring-red-300"
|
||||
onClick={() => router.reload()}
|
||||
>
|
||||
Cancel
|
||||
{t('Cancel')}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import Link from 'next/link'
|
|||
import Image from 'next/image'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Fragment, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import siteConfig from '../config/site.config'
|
||||
import SearchModal from './SearchModal'
|
||||
|
|
@ -37,6 +38,8 @@ const Navbar = () => {
|
|||
setTokenPresent(storedToken())
|
||||
}, [])
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
const clearTokens = () => {
|
||||
setIsOpen(false)
|
||||
|
||||
|
|
@ -71,7 +74,7 @@ const Navbar = () => {
|
|||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
<FontAwesomeIcon className="h-4 w-4" icon="search" />
|
||||
<span className="text-sm font-medium">Search ...</span>
|
||||
<span className="text-sm font-medium">{t('Search ...')}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-1">
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { Fragment } from 'react'
|
|||
import { IconProp } from '@fortawesome/fontawesome-svg-core'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { Listbox, Transition } from '@headlessui/react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import useLocalStorage from '../utils/useLocalStorage'
|
||||
|
||||
|
|
@ -13,13 +14,21 @@ export const layouts: Array<{ id: number; name: 'Grid' | 'List'; icon: IconProp
|
|||
export const SwitchLayout = () => {
|
||||
const [preferredLayout, setPreferredLayout] = useLocalStorage('preferredLayout', layouts[0])
|
||||
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="relative w-24 flex-shrink-0 text-sm text-gray-600 dark:text-gray-300 md:w-28">
|
||||
<Listbox value={preferredLayout} onChange={setPreferredLayout}>
|
||||
<Listbox.Button className="relative w-full cursor-pointer rounded pl-2">
|
||||
<span className="pointer-events-none flex items-center">
|
||||
<FontAwesomeIcon className="mr-2 h-3 w-3" icon={preferredLayout.icon} />
|
||||
<span>{preferredLayout.name}</span>
|
||||
<span>
|
||||
{
|
||||
// t('Grid')
|
||||
// t('List')
|
||||
t(preferredLayout.name)
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
||||
<FontAwesomeIcon className="h-3 w-3" icon="chevron-down" />
|
||||
|
|
@ -39,7 +48,11 @@ export const SwitchLayout = () => {
|
|||
>
|
||||
<FontAwesomeIcon className="mr-2 h-3 w-3" icon={layout.icon} />
|
||||
<span className={layout.name === preferredLayout.name ? 'font-medium' : 'font-normal'}>
|
||||
{layout.name}
|
||||
{
|
||||
// t('Grid')
|
||||
// t('List')
|
||||
t(layout.name)
|
||||
}
|
||||
</span>
|
||||
{layout.name === preferredLayout.name && (
|
||||
<span className="absolute inset-y-0 right-3 flex items-center">
|
||||
|
|
|
|||
|
|
@ -1 +1,32 @@
|
|||
{}
|
||||
{
|
||||
"Actions": "Actions",
|
||||
"Cancel": "Cancel",
|
||||
"Copied folder permalink.": "Copied folder permalink.",
|
||||
"Copied raw file permalink.": "Copied raw file permalink.",
|
||||
"Copy folder permalink": "Copy folder permalink",
|
||||
"Copy raw file permalink": "Copy raw file permalink",
|
||||
"Download file": "Download file",
|
||||
"Download folder": "Download folder",
|
||||
"Download selected files": "Download selected files",
|
||||
"Downloading folder, refresh page to cancel": "Downloading folder, refresh page to cancel",
|
||||
"Downloading selected files, refresh page to cancel": "Downloading selected files, refresh page to cancel",
|
||||
"Downloading selected files...": "Downloading selected files...",
|
||||
"Downloading {{progress}}%": "Downloading {{progress}}%",
|
||||
"Failed to download folder {{path}}: {{status}} {{message}} Skipped it to continue.": "Failed to download folder {{path}}: {{status}} {{message}} Skipped it to continue.",
|
||||
"Failed to download folder.": "Failed to download folder.",
|
||||
"Failed to download selected files.": "Failed to download selected files.",
|
||||
"Finished downloading folder.": "Finished downloading folder.",
|
||||
"Finished downloading selected files.": "Finished downloading selected files.",
|
||||
"Grid": "Grid",
|
||||
"Home": "Home",
|
||||
"Last Modified": "Last Modified",
|
||||
"List": "List",
|
||||
"Load more": "Load more",
|
||||
"Loading ...": "Loading ...",
|
||||
"Name": "Name",
|
||||
"No more files": "No more files",
|
||||
"Search ...": "Search ...",
|
||||
"Select file": "Select file",
|
||||
"Select files": "Select files",
|
||||
"Size": "Size"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,32 @@
|
|||
{}
|
||||
{
|
||||
"Actions": "操作",
|
||||
"Cancel": "取消",
|
||||
"Copied folder permalink.": "已复制文件夹永久链接。",
|
||||
"Copied raw file permalink.": "已复制文件永久链接。",
|
||||
"Copy folder permalink": "复制文件夹永久链接",
|
||||
"Copy raw file permalink": "复制文件永久链接",
|
||||
"Download file": "下载此文件",
|
||||
"Download folder": "下载此文件夹",
|
||||
"Download selected files": "下载选定文件",
|
||||
"Downloading folder, refresh page to cancel": "下载文件夹中,刷新页面以取消",
|
||||
"Downloading selected files, refresh page to cancel": "下载选定文件中,刷新页面以取消",
|
||||
"Downloading selected files...": "下载选定文件中...",
|
||||
"Downloading {{progress}}%": "已下载 {{progress}}%",
|
||||
"Failed to download folder {{path}}: {{status}} {{message}} Skipped it to continue.": "下载文件夹 {{path}} 失败:{{status}} {{message}} 已忽略此错误并继续下载。",
|
||||
"Failed to download folder.": "下载文件夹失败。",
|
||||
"Failed to download selected files.": "下载选定文件失败。",
|
||||
"Finished downloading folder.": "下载文件夹成功。",
|
||||
"Finished downloading selected files.": "下载选定文件成功。",
|
||||
"Grid": "图格",
|
||||
"Home": "首页",
|
||||
"Last Modified": "最后修改时间",
|
||||
"List": "列表",
|
||||
"Load more": "加载更多",
|
||||
"Loading ...": "加载中……",
|
||||
"Name": "文件名",
|
||||
"No more files": "加载完毕",
|
||||
"Search ...": "搜索……",
|
||||
"Select file": "选择此文件",
|
||||
"Select files": "选择以下文件",
|
||||
"Size": "文件大小"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue