-
Notifications
You must be signed in to change notification settings - Fork 7
feat: enhance browser translation with dynamic translation hook #198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Add missing key handler with experimental Translator API integration - Translate node descriptions using t() function for internationalization - Format code improvements for better readability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add useDynamicTranslate hook for experimental browser translation - Implement toggle-able translation with visual indicators (🌐/🔄) - Apply dynamic translation to node descriptions and version changelogs - Convert i18n hook from TypeScript to TSX for React component support - Update dependencies to support new translation features 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces experimental browser translation capabilities using Chrome's new Translator API, allowing dynamic translation of node descriptions and version changelogs with toggle functionality and visual indicators.
Key changes:
- Added
useDynamicTranslate
hook for experimental browser translation with Chrome's Translator API - Converted i18n hook from TypeScript to TSX to support React component rendering
- Applied dynamic translation to NodeDetails component with toggle switcher and emoji indicators
Reviewed Changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 9 comments.
File | Description |
---|---|
src/hooks/i18n/index.tsx | New TSX file implementing dynamic translation hook and enhanced i18n functionality |
src/hooks/i18n/index.ts | Removed original TypeScript i18n implementation |
package.json | Added dependencies for translation features (hot-memo, react-use, use-async) |
components/nodes/NodeDetails.tsx | Integrated dynamic translation for node descriptions and changelogs |
import I18nextBrowserLanguageDetector from 'i18next-browser-languagedetector' | ||
import i18nextResourcesToBackend from 'i18next-resources-to-backend' | ||
import { useRouter } from 'next/router' | ||
import { forEach } from 'rambda' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The forEach
import from rambda appears unused and should be removed.
import { forEach } from 'rambda' |
Copilot uses AI. Check for mistakes.
@@ -0,0 +1,176 @@ | |||
import { LANGUAGE_STORAGE_KEY, SUPPORTED_LANGUAGES } from '@/src/constants' | |||
import hotMemo from 'hot-memo' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hotMemo
import appears unused and should be removed.
import hotMemo from 'hot-memo' |
Copilot uses AI. Check for mistakes.
console.log( | ||
`Missing translation for key "${key}" in language "${lng}"` | ||
) | ||
// (Experimental) Try use broswer Translator API to handle missing keys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: 'broswer' should be 'browser'.
// (Experimental) Try use broswer Translator API to handle missing keys | |
// (Experimental) Try use browser Translator API to handle missing keys |
Copilot uses AI. Check for mistakes.
// cons: | ||
// 1. requires network access to the browser's translation service | ||
// 2. not able to use in server-side rendering | ||
// 3. not avaliable in china |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: 'avaliable' should be 'available'.
// 3. not avaliable in china | |
// 3. not available in china |
Copilot uses AI. Check for mistakes.
(key?: string) => { | ||
if (!key) return key | ||
if (!available) return key | ||
return <>{enabled ? <>{t(key)}</> : <>{key}</>}</> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] This JSX structure is unnecessarily complex. Consider simplifying to return enabled ? t(key) : key
since the hook returns JSX elements but could return strings directly for better composability.
return <>{enabled ? <>{t(key)}</> : <>{key}</>}</> | |
return enabled ? t(key) : key |
Copilot uses AI. Check for mistakes.
const Translator = globalThis.Translator as any | ||
const translator = await Translator.create({ | ||
sourceLanguage: 'en', | ||
targetLanguage: lng, | ||
}).catch(() => null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using any
type defeats TypeScript's type safety. Consider defining a proper interface for the Translator API or using a more specific type assertion.
const Translator = globalThis.Translator as any | |
const translator = await Translator.create({ | |
sourceLanguage: 'en', | |
targetLanguage: lng, | |
}).catch(() => null) | |
interface TranslatorAPI { | |
create(options: { sourceLanguage: string; targetLanguage: string }): Promise<TranslatorInstance>; | |
} | |
interface TranslatorInstance { | |
translateStreaming(text: string): AsyncIterable<string>; | |
} | |
const Translator = globalThis.Translator as TranslatorAPI; | |
const translator = await Translator.create({ | |
sourceLanguage: 'en', | |
targetLanguage: lng, | |
}).catch(() => null); |
Copilot uses AI. Check for mistakes.
// 3. not avaliable in china | ||
// | ||
const [available, availableState] = useAsyncData(async () => { | ||
const Translator = globalThis.Translator as any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using any
type defeats TypeScript's type safety. Consider defining a proper interface for the Translator API or using a more specific type assertion.
const Translator = globalThis.Translator as any | |
const Translator = globalThis.Translator as TranslatorAPI |
Copilot uses AI. Check for mistakes.
aria-label="translate" | ||
onClick={() => { | ||
setEnabled((e) => !e) | ||
}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Switcher component lacks proper accessibility attributes. It should include tabIndex={0}
and onKeyDown
handler to support keyboard navigation, and a more descriptive aria-label
.
aria-label="translate" | |
onClick={() => { | |
setEnabled((e) => !e) | |
}} | |
aria-label={enabled ? "Disable translation" : "Enable translation"} | |
tabIndex={0} | |
onClick={() => { | |
setEnabled((e) => !e) | |
}} | |
onKeyDown={(event) => { | |
if (event.key === "Enter" || event.key === " ") { | |
setEnabled((e) => !e) | |
} | |
}} |
Copilot uses AI. Check for mistakes.
🎨 Chromatic Visual Testing Results
Check the visual changes and approve or request changes as needed. |
Co-authored-by: Copilot <[email protected]>
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
🎨 Chromatic Visual Testing Results
Check the visual changes and approve or request changes as needed. |
Summary
useDynamicTranslate
hook for experimental browser translation using Chrome's new Translator APITest plan
🤖 Generated with Claude Code