- This route (the folder itself and the files inside) is password protected. If you know the password, please
- enter it below.
+ {t('This route (the folder itself and the files inside) is password protected. ') +
+ t('If you know the password, please enter it below.')}
diff --git a/components/DownloadBtnGtoup.tsx b/components/DownloadBtnGtoup.tsx
index 7f0eabc..f86ffc7 100644
--- a/components/DownloadBtnGtoup.tsx
+++ b/components/DownloadBtnGtoup.tsx
@@ -3,6 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { IconProp } from '@fortawesome/fontawesome-svg-core'
import toast from 'react-hot-toast'
import { useClipboard } from 'use-clipboard-copy'
+import { useTranslation } from 'next-i18next'
import Image from 'next/image'
import { useRouter } from 'next/router'
@@ -63,31 +64,33 @@ const DownloadButtonGroup: React.FC<{ downloadUrl: string }> = ({ downloadUrl })
const { asPath } = useRouter()
const clipboard = useClipboard()
+ const { t } = useTranslation()
+
return (
window.open(downloadUrl)}
btnColor="blue"
- btnText="Download"
+ btnText={t('Download')}
btnIcon="file-download"
- btnTitle="Download the file directly through OneDrive"
+ btnTitle={t('Download the file directly through OneDrive')}
/>
{/* window.open(`/api/proxy?url=${encodeURIComponent(downloadUrl)}`)}
btnColor="teal"
- btnText="Proxy download"
+ btnText={t('Proxy download')}
btnIcon="download"
- btnTitle="Download the file with the stream proxied through Vercel Serverless"
+ btnTitle={t('Download the file with the stream proxied through Vercel Serverless')}
/> */}
{
clipboard.copy(`${getBaseUrl()}/api?path=${asPath}&raw=true`)
- toast.success('Copied direct link to clipboard.')
+ toast.success(t('Copied direct link to clipboard.'))
}}
btnColor="pink"
- btnText="Copy direct link"
+ btnText={t('Copy direct link')}
btnIcon="copy"
- btnTitle="Copy the permalink to the file to the clipboard"
+ btnTitle={t('Copy the permalink to the file to the clipboard')}
/>
)
diff --git a/components/FileListing.tsx b/components/FileListing.tsx
index 1178741..499f330 100644
--- a/components/FileListing.tsx
+++ b/components/FileListing.tsx
@@ -321,7 +321,10 @@ const FileListing: FC<{ query?: ParsedUrlQuery }> = ({ query }) => {
{!onlyOnePage && (
- - showing {size} page{size > 1 ? 's' : ''} of {isLoadingMore ? '...' : folderChildren.length} files -
+ {t('- showing {{count}} page(s) of {{totalFileNum}} files -', {
+ count: size,
+ totalFileNum: isLoadingMore ? '...' : folderChildren.length
+ })}
= ({ query }) => {
return (
-
+
)
}
diff --git a/components/FolderGridLayout.tsx b/components/FolderGridLayout.tsx
index 7f32807..53e98ac 100644
--- a/components/FolderGridLayout.tsx
+++ b/components/FolderGridLayout.tsx
@@ -4,6 +4,7 @@ import Link from 'next/link'
import { useState } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useClipboard } from 'use-clipboard-copy'
+import { useTranslation } from 'next-i18next'
import { getBaseUrl } from '../utils/getBaseUrl'
import { formatModifiedDateTime } from '../utils/fileDetails'
@@ -65,6 +66,8 @@ const FolderGridLayout = ({
}) => {
const clipboard = useClipboard()
+ const { t } = useTranslation()
+
return (
@@ -74,13 +77,13 @@ const FolderGridLayout = ({
checked={totalSelected}
onChange={toggleTotalSelected}
indeterminate={true}
- title={'Select all files'}
+ title={t('Select all files')}
/>
{totalGenerating ? (
-
+
) : (
{
clipboard.copy(`${getBaseUrl()}${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`)
- toast('Copied folder permalink.', { icon: '👌' })
+ toast(t('Copied folder permalink.'), { icon: '👌' })
}}
>
{folderGenerating[c.id] ? (
-
+
) : (
{
const p = `${path === '/' ? '' : path}/${encodeURIComponent(c.name)}`
@@ -128,19 +131,19 @@ const FolderGridLayout = ({
) : (
diff --git a/components/FourOhFour.tsx b/components/FourOhFour.tsx
index cffee5c..8e4650d 100644
--- a/components/FourOhFour.tsx
+++ b/components/FourOhFour.tsx
@@ -1,4 +1,5 @@
import Image from 'next/image'
+import { Trans } from 'next-i18next'
const FourOhFour: React.FC<{ errorMsg: string }> = ({ errorMsg }) => {
return (
@@ -8,24 +9,30 @@ const FourOhFour: React.FC<{ errorMsg: string }> = ({ errorMsg }) => {
- Oops, that's a four-oh-four .
+
+ Oops, that's a four-oh-four .
+
{errorMsg}
diff --git a/components/Navbar.tsx b/components/Navbar.tsx
index 2ea78a6..c74d034 100644
--- a/components/Navbar.tsx
+++ b/components/Navbar.tsx
@@ -47,7 +47,7 @@ const Navbar = () => {
localStorage.removeItem(r)
})
- toast.success('Cleared all tokens')
+ toast.success(t('Cleared all tokens'))
setTimeout(() => {
router.reload()
}, 1000)
@@ -95,14 +95,20 @@ const Navbar = () => {
className="flex items-center space-x-2 hover:opacity-80 dark:text-white"
>
- {l.name}
+
+ {
+ // Append link name comments here to add translations
+ // t('Weibo')
+ t(l.name)
+ }
+
))}
{siteConfig.email && (
- Email
+ {t('Email')}
)}
@@ -111,7 +117,7 @@ const Navbar = () => {
className="flex items-center space-x-2 p-2 hover:opacity-80 dark:text-white"
onClick={() => setIsOpen(true)}
>
- Logout
+ {t('Logout')}
)}
@@ -148,12 +154,12 @@ const Navbar = () => {
>
- Clear all tokens?
+ {t('Clear all tokens?')}
- These tokens are used to authenticate yourself into password protected folders, clearing them means
- that you will need to re-enter the passwords again.
+ {t('These tokens are used to authenticate yourself into password protected folders, ') +
+ t('clearing them means that you will need to re-enter the passwords again.')}
@@ -171,14 +177,14 @@ const Navbar = () => {
className="mr-3 inline-flex items-center justify-center space-x-2 rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-400 focus:outline-none focus:ring focus:ring-blue-300"
onClick={() => setIsOpen(false)}
>
- Cancel
+ {t('Cancel')}
clearTokens()}
>
- Clear all
+ {t('Clear all')}
diff --git a/components/SearchModal.tsx b/components/SearchModal.tsx
index f416426..ae0016d 100644
--- a/components/SearchModal.tsx
+++ b/components/SearchModal.tsx
@@ -4,6 +4,7 @@ import { Dispatch, Fragment, SetStateAction, useState } from 'react'
import AwesomeDebouncePromise from 'awesome-debounce-promise'
import { useAsync } from 'react-async-hook'
import useConstant from 'use-constant'
+import { useTranslation } from 'next-i18next'
import Link from 'next/link'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
@@ -112,12 +113,19 @@ function SearchResultItemTemplate({
function SearchResultItemLoadRemote({ result }: { result: OdSearchResult[number] }) {
const { data, error }: SWRResponse
= useSWR(`/api/item?id=${result.id}`, fetcher)
+ const { t } = useTranslation()
+
if (error) {
return
}
if (!data) {
return (
-
+
)
}
@@ -159,6 +167,8 @@ export default function SearchModal({
}) {
const { query, setQuery, results } = useDriveItemSearch()
+ const { t } = useTranslation()
+
const closeSearchBox = () => {
setSearchOpen(false)
setQuery('')
@@ -199,13 +209,13 @@ export default function SearchModal({
type="text"
id="search-box"
className="w-full bg-transparent focus:outline-none focus-visible:outline-none"
- placeholder="Search ..."
+ placeholder={t('Search ...')}
value={query}
onChange={e => setQuery(e.target.value)}
/>
ESC
-
+ {t('Nothing here.')}
- Loading ...
+ {t('Loading ...')}
)}
{results.error && (
- Error: {results.error.message}
+
+ {t('Error: {{message}}', { message: results.error.message })}
+
)}
{results.result && (
<>
{results.result.length === 0 ? (
- Nothing here.
+ {t('Nothing here.')}
) : (
results.result.map(result => )
)}
diff --git a/i18next-scanner.config.js b/i18next-scanner.config.js
index aab3e37..ec12847 100644
--- a/i18next-scanner.config.js
+++ b/i18next-scanner.config.js
@@ -1,4 +1,5 @@
const path = require('path')
+const tsTransform = require('i18next-scanner-typescript')
const { i18n, localePath } = require('./next-i18next.config')
@@ -8,8 +9,10 @@ module.exports = {
sort: true,
removeUnusedKeys: true,
func: {
- list: ['t'],
- extensions: ['.ts', '.tsx']
+ list: ['t']
+ },
+ trans: {
+ fallbackKey: (_ns, val) => val
},
lngs: i18n.locales,
ns: ['common'],
@@ -22,5 +25,6 @@ module.exports = {
},
nsSeparator: false,
keySeparator: false
- }
+ },
+ transform: tsTransform()
}
diff --git a/package.json b/package.json
index d7417ac..1a7e39a 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
"eslint-config-next": "12.0.10",
"eslint-config-prettier": "^8.3.0",
"i18next-scanner": "^3.1.0",
+ "i18next-scanner-typescript": "^1.0.6",
"postcss": "^8.4.5",
"prettier": "^2.5.1",
"prettier-plugin-tailwindcss": "^0.1.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index e899cca..c6ca845 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -27,6 +27,7 @@ specifiers:
eslint-config-next: 12.0.10
eslint-config-prettier: ^8.3.0
i18next-scanner: ^3.1.0
+ i18next-scanner-typescript: ^1.0.6
ioredis: ^4.28.2
jszip: ^3.7.1
next: ^12.0.10
@@ -110,6 +111,7 @@ devDependencies:
eslint-config-next: 12.0.10_9534215cc73b6f260bf33f1b86e3ae0e
eslint-config-prettier: 8.3.0_eslint@8.8.0
i18next-scanner: 3.1.0
+ i18next-scanner-typescript: 1.0.6
postcss: 8.4.6
prettier: 2.5.1
prettier-plugin-tailwindcss: 0.1.4_prettier@2.5.1
@@ -2009,6 +2011,12 @@ packages:
resolution: {integrity: sha512-/MfAGMP0jHonV966uFf9PkWWuDjPYLIcsipnSO3NxpNtAgRUKLTwvm85fEmsF6hGeu0zbZiCQ3W74jwO6K9uXA==}
dev: false
+ /i18next-scanner-typescript/1.0.6:
+ resolution: {integrity: sha512-v6kULnsv32OlFM9pnWTH+wNtRXf5owmFUNBYcX78jbZxQBFnTCUo3w99JjnxuzuXA9ch4UKNQBnt2P/o94eyeQ==}
+ dependencies:
+ typescript: 3.9.10
+ dev: true
+
/i18next-scanner/3.1.0:
resolution: {integrity: sha512-dHLXUJIiF1CYJNslCkJFDYJySk5fg+dzdg9O73XXqHcdZwJ2947SWusqq8HdNFB7LpkBi8oTG6TWLZPmqbAh8Q==}
engines: {node: '>=12'}
@@ -4024,6 +4032,12 @@ packages:
resolution: {integrity: sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==}
dev: false
+ /typescript/3.9.10:
+ resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
/typescript/4.5.5:
resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==}
engines: {node: '>=4.2.0'}