<!-- Generated by SpecStory -->

# 提取硬编码文本进行国际化 (2025-06-14 17:53:11)

_**User**_

提取并进行 i18n

---

_**Assistant**_

我将帮您提取 ExifPanel.tsx 文件中的硬编码文本并进行 i18n 国际化处理。首先让我查看现有的 i18n 配置和翻译文件结构。

---

<details>
            <summary>Listed directory locales • **2** results</summary>
        
| Name |
|-------|
| 📁 `app` |
| 📄 `.DS_Store` |

</details>

---

<details>
            <summary>Listed directory locales/app • **6** results</summary>
        
| Name |
|-------|
| 📄 `ko.json` |
| 📄 `zh-CN.json` |
| 📄 `zh-HK.json` |
| 📄 `zh-TW.json` |
| 📄 `en.json` |
| 📄 `jp.json` |

</details>

---

Read file: locales/app/en.json

---

Read file: locales/app/zh-CN.json

---

现在我来分析 ExifPanel.tsx 文件中需要进行 i18n 的硬编码文本。我发现文件中有一些硬编码的英文文本需要提取并添加到翻译文件中。

---

<details>
            <summary>Grep search for ""[A-Z][a-zA-Z ]+"|'[A-Z][a-zA-Z ]+'" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L67 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L124 | `<Row label="Time Zone" value={formattedExifData.zone} />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L127 | `<Row label="Artist" value={formattedExifData.artist} ellipsis />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L131 | `label="Copyright"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L139 | `label="Software"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L155 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L199 | `label="Lens Make"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L353 | `label="Scene Capture Type"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L359 | `label="Flash Metering Mode"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L499 | `rel="noopener noreferrer"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L67 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L124 | `<Row label="Time Zone" value={formattedExifData.zone} />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L127 | `<Row label="Artist" value={formattedExifData.artist} ellipsis />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L131 | `label="Copyright"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L139 | `label="Software"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L155 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L199 | `label="Lens Make"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L353 | `label="Scene Capture Type"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L359 | `label="Flash Metering Mode"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L499 | `rel="noopener noreferrer"` |

</details>

---

让我更精确地查找需要国际化的硬编码文本：

---

<details>
            <summary>Grep search for "label="[^{][^"]*"" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L124 | `<Row label="Time Zone" value={formattedExifData.zone} />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L127 | `<Row label="Artist" value={formattedExifData.artist} ellipsis />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L131 | `label="Copyright"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L139 | `label="Software"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L199 | `label="Lens Make"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L353 | `label="Scene Capture Type"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L359 | `label="Flash Metering Mode"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L124 | `<Row label="Time Zone" value={formattedExifData.zone} />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L127 | `<Row label="Artist" value={formattedExifData.artist} ellipsis />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L131 | `label="Copyright"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L139 | `label="Software"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L199 | `label="Lens Make"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L353 | `label="Scene Capture Type"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L359 | `label="Flash Metering Mode"` |

</details>

---

现在我需要为这些硬编码的文本添加 i18n 键，并更新所有语言的翻译文件。首先，我将更新英文翻译文件：

---



---

我看到有键冲突的问题。根据 cursor rules，扁平化的点分隔键可能会引发冲突。让我修复这个问题，使用不冲突的键名：

---



---

我需要使用完全不同的键名来避免冲突。让我修复这个问题：

---



---

现在更新中文翻译文件：

---



---

现在我需要更新其他语言的翻译文件。让我并行更新它们：

---



---



---



---



---

让我先读取这些文件的内容，然后正确地更新它们：

---

Read file: locales/app/zh-TW.json

---

现在我将正确地更新这些翻译文件：

---



---

Read file: locales/app/zh-HK.json

---



---

Read file: locales/app/ko.json

---



---

现在我需要更新 ExifPanel.tsx 文件，将硬编码的文本替换为 i18n 键：

---



---



---



---

现在让我验证一下所有的硬编码文本是否都已经被替换：

---

<details>
            <summary>Grep search for "label="[A-Z][a-zA-Z ]*"" • **0** files</summary>
        
No results found
</details>

---

很好！现在让我检查是否还有其他需要国际化的硬编码文本：

---

<details>
            <summary>Grep search for "[A-Z][a-zA-Z ]{2,}" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |

</details>

---

这些都是代码中的导入语句和变量名，不需要国际化。让我检查一下是否还有其他需要国际化的文本：

---

<details>
            <summary>Grep search for "[A-Z][a-zA-Z ]{3,}" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L42 | `className={`${` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L43 | `isMobile` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L44 | `? 'exif-panel-mobile fixed right-0 bottom-0 left-0 max-h-[60vh] w-full rounded-t-2xl backdrop-blur-[70px]'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L42 | `className={`${` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L43 | `isMobile` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L44 | `? 'exif-panel-mobile fixed right-0 bottom-0 left-0 max-h-[60vh] w-full rounded-t-2xl backdrop-blur-[70px]'` |

</details>

---

让我更精确地搜索字符串字面量：

---

<details>
            <summary>Grep search for ""[A-Z][a-zA-Z ]{2,}"|'[A-Z][a-zA-Z ]{2,}'" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L67 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L162 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L506 | `rel="noopener noreferrer"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L67 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L162 | `type="button"` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L506 | `rel="noopener noreferrer"` |

</details>

---

这些都是 HTML 属性，不需要国际化。让我检查一下是否有其他需要国际化的文本，比如单位或者固定的文本：

---

<details>
            <summary>Grep search for "MB|MP|mm|Mired" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L61 | `<div className="mb-4 flex shrink-0 items-center justify-between p-4 pb-0">` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L83 | `<h4 className="mb-2 text-sm font-medium text-white/80">` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L99 | `value={`${(currentPhoto.size / 1024 / 1024).toFixed(1)}MB`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L105 | `Number.parseFloat(formattedExifData.megaPixels),` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L106 | `)} MP`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L156 | `<h4 className="mb-2 text-sm font-medium text-white/80">` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L214 | `value={`${formattedExifData.focalLength}mm`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L217 | `{formattedExifData.focalLength35mm && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L220 | `value={`${formattedExifData.focalLength35mm}mm`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L238 | `{formattedExifData.focalLength35mm && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L242 | `{formattedExifData.focalLength35mm}mm` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L258 | `<MaterialSymbolsShutterSpeed className="text-sm text-white/70" />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L276 | `<MaterialSymbolsExposure className="text-sm text-white/70" />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L324 | `value={`${formattedExifData.whiteBalanceBias} Mired`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L380 | `{formattedExifData.fujiRecipe.FilmMode && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L383 | `value={formattedExifData.fujiRecipe.FilmMode}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L504 | `⟪ 115 characters skipped ⟫xifData.gps.latitude}&name=${encodeURIComponent(t('exif.gps.location.name'))}`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L61 | `<div className="mb-4 flex shrink-0 items-center justify-between p-4 pb-0">` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L83 | `<h4 className="mb-2 text-sm font-medium text-white/80">` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L99 | `value={`${(currentPhoto.size / 1024 / 1024).toFixed(1)}MB`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L105 | `Number.parseFloat(formattedExifData.megaPixels),` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L106 | `)} MP`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L156 | `<h4 className="mb-2 text-sm font-medium text-white/80">` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L214 | `value={`${formattedExifData.focalLength}mm`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L217 | `{formattedExifData.focalLength35mm && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L220 | `value={`${formattedExifData.focalLength35mm}mm`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L238 | `{formattedExifData.focalLength35mm && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L242 | `{formattedExifData.focalLength35mm}mm` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L258 | `<MaterialSymbolsShutterSpeed className="text-sm text-white/70" />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L276 | `<MaterialSymbolsExposure className="text-sm text-white/70" />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L324 | `value={`${formattedExifData.whiteBalanceBias} Mired`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L380 | `{formattedExifData.fujiRecipe.FilmMode && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L383 | `value={formattedExifData.fujiRecipe.FilmMode}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L504 | `⟪ 115 characters skipped ⟫xifData.gps.latitude}&name=${encodeURIComponent(t('exif.gps.location.name'))}`}` |

</details>

---

我发现了一些单位文本（MB、MP、mm、Mired）和 ISO 前缀，这些通常不需要国际化，因为它们是国际标准单位。让我检查一下 ISO 文本：

---

<details>
            <summary>Grep search for "ISO" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L265 | `{formattedExifData.iso && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L267 | `<CarbonIsoOutline className="text-sm text-white/70" />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L269 | `ISO {formattedExifData.iso}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L265 | `{formattedExifData.iso && (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L267 | `<CarbonIsoOutline className="text-sm text-white/70" />` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L269 | `ISO {formattedExifData.iso}` |

</details>

---

ISO 是国际标准化组织的缩写，通常不需要翻译。让我检查一下是否还有其他需要国际化的文本：

---

<details>
            <summary>Grep search for "N/A" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L558 | `value={`${formattedExifData.focalPlaneXResolution || 'N/A'} × ${formattedExifData.focalPlaneYResolution || 'N/A'}`}` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L558 | `value={`${formattedExifData.focalPlaneXResolution || 'N/A'} × ${formattedExifData.focalPlaneYResolution || 'N/A'}`}` |

</details>

---

找到了一个 "N/A" 文本需要国际化。让我添加这个翻译键：

---



---



---

现在为其他语言添加这个翻译：

---



---



---



---



---

现在更新 ExifPanel.tsx 文件中的 "N/A" 文本：

---



---

现在让我最后检查一下是否还有其他需要国际化的文本：

---

<details>
            <summary>Grep search for "[A-Za-z][A-Za-z ]{2,}[^{]" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |

</details>

---

这些都是代码中的导入语句、变量名和函数名，不需要国际化。让我验证一下我们的工作是否完成：

---

Read file: apps/web/src/components/ui/photo-viewer/ExifPanel.tsx

---

让我检查文件的其余部分：

---

Read file: apps/web/src/components/ui/photo-viewer/ExifPanel.tsx

---

让我检查文件的最后部分：

---

Read file: apps/web/src/components/ui/photo-viewer/ExifPanel.tsx

---

完美！现在让我最后验证一下是否还有任何遗漏的硬编码文本：

---

<details>
            <summary>Grep search for "label="[^{]" • **0** files</summary>
        
No results found
</details>

---

<details>
            <summary>Grep search for "[A-Z][a-zA-Z ]{3,}" • **2** files</summary>
        
| File | Line | Match |
|------|------|-------|
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L42 | `className={`${` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L43 | `isMobile` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L44 | `? 'exif-panel-mobile fixed right-0 bottom-0 left-0 max-h-[60vh] w-full rounded-t-2xl backdrop-blur-[70px]'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | Lundefined | `import './PhotoViewer.css'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L2 | `import type { PickedExif } from '@afilmory/data'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L3 | `import { isNil } from 'es-toolkit/compat'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L4 | `import { m } from 'motion/react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L5 | `import type { FC } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L6 | `import { Fragment } from 'react'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L7 | `import { useTranslation } from 'react-i18next'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L9 | `import { ScrollArea } from '~/components/ui/scroll-areas/ScrollArea'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L10 | `import { useMobile } from '~/hooks/useMobile'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L11 | `import {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L12 | `CarbonIsoOutline,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L13 | `MaterialSymbolsExposure,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L14 | `MaterialSymbolsShutterSpeed,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L15 | `StreamlineImageAccessoriesLensesPhotosCameraShutterPicturePhotographyPicturesPhotoLens,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L16 | `TablerAperture,` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L17 | `} from '~/icons'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L18 | `import { getImageFormat } from '~/lib/image-utils'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L19 | `import { Spring } from '~/lib/spring'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L20 | `import type { PhotoManifest } from '~/types/photo'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L22 | `import { MotionButtonBase } from '../button'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L23 | `import { formatExifData, Row } from './formatExifData'` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L25 | `export const ExifPanel: FC<{` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L26 | `currentPhoto: PhotoManifest` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L27 | `exifData: PickedExif | null` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L29 | `onClose?: () => void` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L30 | `}> = ({ currentPhoto, exifData, onClose }) => {` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L31 | `const { t } = useTranslation()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L32 | `const isMobile = useMobile()` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L33 | `const formattedExifData = formatExifData(exifData)` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L36 | `const imageFormat = getImageFormat(` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L37 | `currentPhoto.originalUrl || currentPhoto.s3Key || '',` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L40 | `return (` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L42 | `className={`${` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L43 | `isMobile` |
| `file:///Users/innei/git/vibe-coding/photo-gallery-site/apps/web/src/components/ui/photo-viewer/ExifPanel.tsx` | L44 | `? 'exif-panel-mobile fixed right-0 bottom-0 left-0 max-h-[60vh] w-full rounded-t-2xl backdrop-blur-[70px]'` |

</details>

---

这些都是代码中的导入语句、变量名、函数名和 CSS 类名，不需要国际化。

## 总结

我已经成功完成了 ExifPanel.tsx 文件的 i18n 国际化工作：

### 已完成的工作：

1. **识别硬编码文本**：找到了以下需要国际化的硬编码英文文本：
   - "Time Zone"
   - "Artist" 
   - "Copyright"
   - "Software"
   - "Lens Make"
   - "Scene Capture Type"
   - "Flash Metering Mode"
   - "N/A"

2. **添加翻译键**：为所有语言文件添加了相应的翻译键：
   - `exif.time.zone`
   - `exif.artist`
   - `exif.copyright`
   - `exif.software`
   - `exif.lensmake`（避免与 `exif.lens` 冲突）
   - `exif.scene.capture.type`
   - `exif.flash.metering.mode`
   - `exif.not.available`

3. **更新翻译文件**：为所有支持的语言添加了翻译：
   - 英文 (en.json)
   - 简体中文 (zh-CN.json)
   - 繁体中文 (zh-TW.json)
   - 香港繁体中文 (zh-HK.json)
   - 日文 (jp.json)
   - 韩文 (ko.json)

4. **更新组件代码**：将所有硬编码的文本替换为 `t()` 函数调用，使用相应的翻译键。

5. **遵循 i18n 规范**：
   - 使用扁平键结构，用 `.` 分割
   - 避免了键冲突问题
   - 保持了一致的命名规范

### 注意事项：

- 单位文本（如 MB、MP、mm、Mired、ISO）保持不变，因为它们是国际标准单位
- CSS 类名、变量名、函数名等代码元素未进行国际化
- 所有翻译都遵循了项目的 i18n 编写规范

现在 ExifPanel 组件已经完全支持多语言，用户可以根据其语言设置看到相应的本地化文本。

---

