Files
opsxshell/src/components/sftp/Breadcrumb.tsx
T
Logan.Li b0d0e3a5f3 feat(i18n): add multi-language support (ja/ko/vi/ru/zh-TW) with system auto-detection
- Extend AppLanguage to 7 locales: zh-CN, zh-TW, en, ja, ko, vi, ru
- Auto-detect system language via navigator.languages; fallback to English
- Add BCP47 locale mapping for date formatting and sorting
- Create 50 translation JSON files (5 languages × 10 namespaces, 1137 keys each)
- Update language selector with native language names
- Extend locale key parity test to cover all 7 languages (70 assertions)
- Add VNC/RDP desktop, serial terminal, AI agent, port forwarding, and SFTP features
- Add credential encryption, host metrics, session backup crypto, and zmodem bridge
- Update Rust backend: desktop services, host metrics, SSH/SFTP enhancements
2026-08-12 00:07:48 +08:00

53 lines
1.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Breadcrumb - 路径导航组件(本地支持 Windows / UNC,远程保持 POSIX)
*/
import { ChevronRight, Home } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { splitPathSegments } from '../../utils/localPath'
interface BreadcrumbProps {
path: string
isLocal?: boolean
onNavigate: (p: string) => void
onHome: () => void
}
export function Breadcrumb({ path, isLocal = false, onNavigate, onHome }: BreadcrumbProps) {
const { t } = useTranslation('sftp')
const { root, parts, join } = splitPathSegments(path || (isLocal ? '' : '/'), isLocal)
const rootLabel = isLocal && root !== '/' ? root.replace(/\\$/, '') || root : '/'
return (
<div className="flex min-w-0 items-center gap-1 text-sm">
<button
type="button"
onClick={onHome}
className="flex-shrink-0 rounded p-1.5 transition-colors hover:bg-dark-700"
title={t('nav.home')}
>
<Home className="h-4 w-4 text-txt-muted" />
</button>
<button
type="button"
onClick={() => onNavigate(root || '/')}
className="rounded px-1.5 py-0.5 text-txt-muted transition-colors hover:bg-dark-700 hover:text-dark-200"
>
{rootLabel}
</button>
{parts.map((part, index) => (
<span key={`${part}-${index}`} className="flex min-w-0 items-center">
<ChevronRight className="mx-0.5 h-3 w-3 flex-shrink-0 text-dark-600" />
<button
type="button"
onClick={() => onNavigate(join(parts.slice(0, index + 1)))}
className="max-w-[120px] truncate rounded px-1.5 py-0.5 text-content-primary transition-colors hover:bg-dark-700"
>
{part}
</button>
</span>
))}
</div>
)
}