From 2df258f7917d6c0dc15243d401a4201f75c14ea8 Mon Sep 17 00:00:00 2001 From: myl7 Date: Sun, 6 Feb 2022 18:35:03 +0800 Subject: [PATCH] add trans support and hook all compnents excluding preview dir --- components/Auth.tsx | 9 ++++++--- components/DownloadBtnGtoup.tsx | 17 ++++++++++------- components/FileListing.tsx | 7 +++++-- components/FolderGridLayout.tsx | 25 ++++++++++++++----------- components/FourOhFour.tsx | 33 ++++++++++++++++++++------------- components/Navbar.tsx | 24 +++++++++++++++--------- components/SearchModal.tsx | 24 ++++++++++++++++++------ i18next-scanner.config.js | 10 +++++++--- package.json | 1 + pnpm-lock.yaml | 14 ++++++++++++++ 10 files changed, 110 insertions(+), 54 deletions(-) diff --git a/components/Auth.tsx b/components/Auth.tsx index af67829..16ab760 100644 --- a/components/Auth.tsx +++ b/components/Auth.tsx @@ -3,6 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import Image from 'next/image' import { useRouter } from 'next/router' import { FC, useState } from 'react' +import { useTranslation } from 'next-i18next' import { matchProtectedRoute } from '../utils/protectedRouteHandler' import useLocalStorage from '../utils/useLocalStorage' @@ -14,16 +15,18 @@ const Auth: FC<{ redirect: string }> = ({ redirect }) => { const [token, setToken] = useState('') const [_, setPersistedToken] = useLocalStorage(authTokenPath, '') + const { t } = useTranslation() + return (
authenticate
-
Enter Password
+
{t('Enter Password')}

- 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 + })}
- Oops, that's a four-oh-four. + + Oops, that's a four-oh-four. +
{errorMsg}
- Press{' '} - F12{' '} - and open devtools for more details, or seek help at{' '} - - onedrive-vercel-index discussions - - . + + Press{' '} + + F12 + {' '} + and open devtools for more details, or seek help at{' '} + + onedrive-vercel-index discussions + + . +
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')}
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'}