Procházet zdrojové kódy

feat (1.34.9 -> 1.35.0): FunctionArea功能区国际化支持

- 在 FunctionArea.tsx 中集成 React Intl,使用 useIntl hook 和 formatMessage 实现动态翻译
- 为所有功能按钮添加国际化键值对,包括标记、翻转、旋转、裁剪、遮罩、布局、测量等功能
- 在 i18n 文件中新增 34 个 functionArea 相关的多语言键,支持中英文双语
- 优化禁用状态提示文本的国际化处理,使用 disabledTooltipSuffix 键统一管理
- 确保所有功能按钮在中英文界面下都能正确显示对应语言的提示文本

改动文件:
- scripts/output/i18n/en.js
- scripts/output/i18n/zh.js
- src/assets/i18n/messages/en.js
- src/assets/i18n/messages/zh.js
- src/pages/view/components/FunctionArea.tsx
- package.json
- CHANGELOG.md
dengdx před 1 týdnem
rodič
revize
a3cb26aaaa

+ 34 - 0
CHANGELOG.md

@@ -2,6 +2,40 @@
 
 本项目的所有重要变更都将记录在此文件中。
 
+## [1.35.0] - 2025-12-31 11:06
+
+### 新增 (Added)
+
+- **FunctionArea功能区国际化支持** - 实现功能按钮的完整多语言支持,提升国际化用户体验
+  - 在 FunctionArea.tsx 中集成 React Intl,使用 useIntl hook 和 formatMessage 实现动态翻译
+  - 为所有功能按钮添加国际化键值对,包括标记、翻转、旋转、裁剪、遮罩、布局、测量等功能
+  - 在 i18n 文件中新增 34 个 functionArea 相关的多语言键,支持中英文双语
+  - 优化禁用状态提示文本的国际化处理,使用 disabledTooltipSuffix 键统一管理
+  - 确保所有功能按钮在中英文界面下都能正确显示对应语言的提示文本
+
+**核心功能实现:**
+
+- 多语言键值对:新增 functionArea.addLMark、addRMark、horizontalFlip、rotateClockwise90 等 34 个翻译键
+- 动态翻译:所有按钮 title 属性使用 intl.formatMessage 动态获取当前语言文本
+- 一致性设计:禁用提示使用统一的 suffix 键,保持界面文本一致性
+- 双语支持:中文和英文翻译完整覆盖所有功能按钮
+
+**技术实现:**
+
+- 在 FunctionArea.tsx 中导入 useIntl hook
+- 使用 intl.formatMessage({ id: 'functionArea.xxx' }) 替换硬编码文本
+- 在 scripts/output/i18n/ 和 src/assets/i18n/messages/ 中添加翻译资源
+- 禁用提示使用模板字符串拼接 suffix 实现统一管理
+
+**改动文件:**
+
+- scripts/output/i18n/en.js - 添加 34 个英文翻译键
+- scripts/output/i18n/zh.js - 添加 34 个中文翻译键
+- src/assets/i18n/messages/en.js - 添加 34 个英文翻译键
+- src/assets/i18n/messages/zh.js - 添加 34 个中文翻译键
+- src/pages/view/components/FunctionArea.tsx - 集成 React Intl 多语言支持
+- package.json - 版本更新: 1.34.9 -> 1.35.0
+
 ## [1.34.9] - 2025-12-30 18:17
 
 ### 修复 (Fixed)

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "zsis",
-  "version": "1.34.9",
+  "version": "1.35.0",
   "private": true,
   "description": "医学成像系统",
   "main": "main.js",

+ 35 - 1
scripts/output/i18n/en.js

@@ -280,5 +280,39 @@
   "report.module.imageFindings": "imageFindings",
   "report.module.imagingDiagnosis": "imagingDiagnosis",
   "thumbnailList.title": "Image Thumbnails",
-  "thumbnailList.noImages": "No images to display"
+  "thumbnailList.noImages": "No images to display",
+  "functionArea.addLMark": "Add L Mark",
+  "functionArea.addRMark": "Add R Mark",
+  "functionArea.addMark": "Add Mark",
+  "functionArea.deleteSelectedMark": "Delete Selected Mark",
+  "functionArea.horizontalFlip": "Horizontal Flip",
+  "functionArea.verticalFlip": "Vertical Flip",
+  "functionArea.rotateCounterclockwise90": "Rotate Counterclockwise 90°",
+  "functionArea.rotateClockwise90": "Rotate Clockwise 90°",
+  "functionArea.rotateAnyAngle": "Rotate Any Angle",
+  "functionArea.cropSelectedArea": "Crop Selected Area",
+  "functionArea.deleteDigitalMask": "Delete Digital Mask",
+  "functionArea.adjustBrightnessAndContrast": "Adjust Brightness and Contrast",
+  "functionArea.addMask": "Add Mask",
+  "functionArea.deleteMask": "Delete Mask",
+  "functionArea.imageComparison": "Image Comparison",
+  "functionArea.invertContrast": "Invert Contrast",
+  "functionArea.1x1Layout": "1x1 Layout",
+  "functionArea.1x2Layout": "1x2 Layout",
+  "functionArea.2x2Layout": "2x2 Layout",
+  "functionArea.4x4Layout": "4x4 Layout",
+  "functionArea.magnifier": "Magnifier",
+  "functionArea.fitSize": "Fit Size",
+  "functionArea.originalSize": "Original Size",
+  "functionArea.zoomImage": "Zoom Image",
+  "functionArea.resetCursor": "Reset Cursor",
+  "functionArea.pan": "Pan",
+  "functionArea.invertImage": "Invert Image",
+  "functionArea.resetImage": "Reset Image",
+  "functionArea.snapshot": "Snapshot",
+  "functionArea.advancedProcessing": "Advanced Processing",
+  "functionArea.imageMeasurement": "Image Measurement",
+  "functionArea.rectangleCrop": "Rectangle Crop",
+  "functionArea.more": "More",
+  "functionArea.disabledTooltipSuffix": " (not available in multi-grid mode)"
 }

+ 35 - 1
scripts/output/i18n/zh.js

@@ -280,5 +280,39 @@
   "report.module.imageFindings": "影像所见",
   "report.module.imagingDiagnosis": "影像诊断",
   "thumbnailList.title": "图像缩略图",
-  "thumbnailList.noImages": "暂无图像显示"
+  "thumbnailList.noImages": "暂无图像显示",
+  "functionArea.addLMark": "添加左标记",
+  "functionArea.addRMark": "添加右标记",
+  "functionArea.addMark": "添加标记",
+  "functionArea.deleteSelectedMark": "删除选定标记",
+  "functionArea.horizontalFlip": "水平翻转",
+  "functionArea.verticalFlip": "垂直翻转",
+  "functionArea.rotateCounterclockwise90": "逆时针旋转90°",
+  "functionArea.rotateClockwise90": "顺时针旋转90°",
+  "functionArea.rotateAnyAngle": "任意角度旋转",
+  "functionArea.cropSelectedArea": "裁剪选中区域",
+  "functionArea.deleteDigitalMask": "删除数字遮线框",
+  "functionArea.adjustBrightnessAndContrast": "调整亮度和对比度",
+  "functionArea.addMask": "添加遮罩",
+  "functionArea.deleteMask": "删除遮罩",
+  "functionArea.imageComparison": "图像比较",
+  "functionArea.invertContrast": "反色对比",
+  "functionArea.1x1Layout": "1x1布局",
+  "functionArea.1x2Layout": "1x2布局",
+  "functionArea.2x2Layout": "2x2布局",
+  "functionArea.4x4Layout": "4x4布局",
+  "functionArea.magnifier": "放大镜",
+  "functionArea.fitSize": "适应尺寸",
+  "functionArea.originalSize": "原始尺寸",
+  "functionArea.zoomImage": "缩放图像",
+  "functionArea.resetCursor": "重置光标",
+  "functionArea.pan": "平移",
+  "functionArea.invertImage": "反转图像",
+  "functionArea.resetImage": "重置图像",
+  "functionArea.snapshot": "快照",
+  "functionArea.advancedProcessing": "高级处理",
+  "functionArea.imageMeasurement": "图像测量",
+  "functionArea.rectangleCrop": "矩形裁剪",
+  "functionArea.more": "更多",
+  "functionArea.disabledTooltipSuffix": " (多分格模式下不可用)"
 }

+ 34 - 0
src/assets/i18n/messages/en.js

@@ -283,4 +283,38 @@ export default {
   "report.module.imagingDiagnosis": "imagingDiagnosis",
   "thumbnailList.title": "Image Thumbnails",
   "thumbnailList.noImages": "No images to display",
+  "functionArea.addLMark": "Add L Mark",
+  "functionArea.addRMark": "Add R Mark",
+  "functionArea.addMark": "Add Mark",
+  "functionArea.deleteSelectedMark": "Delete Selected Mark",
+  "functionArea.horizontalFlip": "Horizontal Flip",
+  "functionArea.verticalFlip": "Vertical Flip",
+  "functionArea.rotateCounterclockwise90": "Rotate Counterclockwise 90°",
+  "functionArea.rotateClockwise90": "Rotate Clockwise 90°",
+  "functionArea.rotateAnyAngle": "Rotate Any Angle",
+  "functionArea.cropSelectedArea": "Crop Selected Area",
+  "functionArea.deleteDigitalMask": "Delete Digital Mask",
+  "functionArea.adjustBrightnessAndContrast": "Adjust Brightness and Contrast",
+  "functionArea.addMask": "Add Mask",
+  "functionArea.deleteMask": "Delete Mask",
+  "functionArea.imageComparison": "Image Comparison",
+  "functionArea.invertContrast": "Invert Contrast",
+  "functionArea.1x1Layout": "1x1 Layout",
+  "functionArea.1x2Layout": "1x2 Layout",
+  "functionArea.2x2Layout": "2x2 Layout",
+  "functionArea.4x4Layout": "4x4 Layout",
+  "functionArea.magnifier": "Magnifier",
+  "functionArea.fitSize": "Fit Size",
+  "functionArea.originalSize": "Original Size",
+  "functionArea.zoomImage": "Zoom Image",
+  "functionArea.resetCursor": "Reset Cursor",
+  "functionArea.pan": "Pan",
+  "functionArea.invertImage": "Invert Image",
+  "functionArea.resetImage": "Reset Image",
+  "functionArea.snapshot": "Snapshot",
+  "functionArea.advancedProcessing": "Advanced Processing",
+  "functionArea.imageMeasurement": "Image Measurement",
+  "functionArea.rectangleCrop": "Rectangle Crop",
+  "functionArea.more": "More",
+  "functionArea.disabledTooltipSuffix": " (not available in multi-grid mode)",
 };

+ 34 - 0
src/assets/i18n/messages/zh.js

@@ -283,5 +283,39 @@ export default {
   "report.module.imagingDiagnosis": "影像诊断",
   "thumbnailList.title": "图像缩略图",
   "thumbnailList.noImages": "暂无图像显示",
+  "functionArea.addLMark": "添加左标记",
+  "functionArea.addRMark": "添加右标记",
+  "functionArea.addMark": "添加标记",
+  "functionArea.deleteSelectedMark": "删除选定标记",
+  "functionArea.horizontalFlip": "水平翻转",
+  "functionArea.verticalFlip": "垂直翻转",
+  "functionArea.rotateCounterclockwise90": "逆时针旋转90°",
+  "functionArea.rotateClockwise90": "顺时针旋转90°",
+  "functionArea.rotateAnyAngle": "任意角度旋转",
+  "functionArea.cropSelectedArea": "裁剪选中区域",
+  "functionArea.deleteDigitalMask": "删除数字遮线框",
+  "functionArea.adjustBrightnessAndContrast": "调整亮度和对比度",
+  "functionArea.addMask": "添加遮罩",
+  "functionArea.deleteMask": "删除遮罩",
+  "functionArea.imageComparison": "图像比较",
+  "functionArea.invertContrast": "反色对比",
+  "functionArea.1x1Layout": "1x1布局",
+  "functionArea.1x2Layout": "1x2布局",
+  "functionArea.2x2Layout": "2x2布局",
+  "functionArea.4x4Layout": "4x4布局",
+  "functionArea.magnifier": "放大镜",
+  "functionArea.fitSize": "适应尺寸",
+  "functionArea.originalSize": "原始尺寸",
+  "functionArea.zoomImage": "缩放图像",
+  "functionArea.resetCursor": "重置光标",
+  "functionArea.pan": "平移",
+  "functionArea.invertImage": "反转图像",
+  "functionArea.resetImage": "重置图像",
+  "functionArea.snapshot": "快照",
+  "functionArea.advancedProcessing": "高级处理",
+  "functionArea.imageMeasurement": "图像测量",
+  "functionArea.rectangleCrop": "矩形裁剪",
+  "functionArea.more": "更多",
+  "functionArea.disabledTooltipSuffix": " (多分格模式下不可用)",
 
 };

+ 38 - 34
src/pages/view/components/FunctionArea.tsx

@@ -1,5 +1,6 @@
 import React, { useState } from 'react';
 import { Button, Flex, Divider } from 'antd';
+import { useIntl } from 'react-intl';
 import '@/themes/truncateText.css';
 import { useDispatch } from 'react-redux';
 import { setAction } from '@/states/view/functionAreaSlice';
@@ -26,6 +27,7 @@ const FunctionButton = ({
   action: string;
   iconName: string;
 }) => {
+  const intl = useIntl();
   const dispatch = useDispatch();
   const themeType = useAppSelector((state) => state.theme.themeType);
   const activeTools = useAppSelector((state) => state.functionArea.activeTools);
@@ -117,7 +119,7 @@ const FunctionButton = ({
         //minWidth: 44,            // 保险
         //overflow: 'hidden',      // 超出的文字裁掉
       }}
-      title={disabled ? `${title} (多分格模式下不可用)` : title}
+      title={disabled ? `${title}${intl.formatMessage({ id: 'functionArea.disabledTooltipSuffix' })}` : title}
       className="truncate-text"
     >
       {/* {title} */}
@@ -126,151 +128,153 @@ const FunctionButton = ({
 };
 
 const FunctionArea = () => {
+  const intl = useIntl();
+
   return (
     <Flex wrap gap="small" align="center" justify="start" className="p-1">
-      <FunctionButton title="Add L Mark" action="Add L Mark" iconName="LMark" />
-      <FunctionButton title="Add R Mark" action="Add R Mark" iconName="RMark" />
-      <FunctionButton title="Add Mark" action="AddMark" iconName="AddMark" />
+      <FunctionButton title={intl.formatMessage({ id: "functionArea.addLMark" })} action="Add L Mark" iconName="LMark" />
+      <FunctionButton title={intl.formatMessage({ id: "functionArea.addRMark" })} action="Add R Mark" iconName="RMark" />
+      <FunctionButton title={intl.formatMessage({ id: "functionArea.addMark" })} action="AddMark" iconName="AddMark" />
       <FunctionButton
-        title="Delete Selected Mark"
+        title={intl.formatMessage({ id: "functionArea.deleteSelectedMark" })}
         action="Delete Selected Mark"
         iconName="EraseMark"
       />
       <FunctionButton
-        title="Horizontal Flip"
+        title={intl.formatMessage({ id: "functionArea.horizontalFlip" })}
         action="Horizontal Flip"
         iconName="HReverse"
       />
       <FunctionButton
-        title="Vertical Flip"
+        title={intl.formatMessage({ id: "functionArea.verticalFlip" })}
         action="Vertical Flip"
         iconName="VReverse"
       />
       <FunctionButton
-        title="Rotate Counterclockwise 90°"
+        title={intl.formatMessage({ id: "functionArea.rotateCounterclockwise90" })}
         action="Rotate Counterclockwise 90"
         iconName="RotateL90"
       />
       <FunctionButton
-        title="Rotate Clockwise 90°"
+        title={intl.formatMessage({ id: "functionArea.rotateClockwise90" })}
         action="Rotate Clockwise 90"
         iconName="RotateR90"
       />
       <FunctionButton
-        title="Rotate Any Angle"
+        title={intl.formatMessage({ id: "functionArea.rotateAnyAngle" })}
         action="Rotate Any Angle"
         iconName="RotateAnyDegree"
       />
       <FunctionButton
-        title="Crop Selected Area"
+        title={intl.formatMessage({ id: "functionArea.cropSelectedArea" })}
         action="Crop Selected Area"
         iconName="Crop"
       />
       <FunctionButton
-        title="删除数字遮线框"
+        title={intl.formatMessage({ id: "functionArea.deleteDigitalMask" })}
         action="Delete Digital Mask"
         iconName="btn_RemoveCrop"
       />
       <FunctionButton
-        title="Adjust Brightness and Contrast"
+        title={intl.formatMessage({ id: "functionArea.adjustBrightnessAndContrast" })}
         action="Adjust Brightness and Contrast"
         iconName="btn_BrightnessContrast"
       />
       <FunctionButton
-        title="Add Mask"
+        title={intl.formatMessage({ id: "functionArea.addMask" })}
         action="Add Mask"
         iconName="AddMask"
       />
       <FunctionButton
-        title="Delete Mask"
+        title={intl.formatMessage({ id: "functionArea.deleteMask" })}
         action="Delete Mask"
         iconName="DeleteMask"
       />
       <FunctionButton
-        title="Image Comparison"
+        title={intl.formatMessage({ id: "functionArea.imageComparison" })}
         action="Image Comparison"
         iconName="btn_Compare"
       />
       <FunctionButton
-        title="反色对比"
+        title={intl.formatMessage({ id: "functionArea.invertContrast" })}
         action="Invert Contrast"
         iconName="btn_ReverseColour"
       />
       <FunctionButton
-        title="1x1 Layout"
+        title={intl.formatMessage({ id: "functionArea.1x1Layout" })}
         action="1x1 Layout"
         iconName="1x1_normal"
       />
       <FunctionButton
-        title="1x2 Layout"
+        title={intl.formatMessage({ id: "functionArea.1x2Layout" })}
         action="1x2 Layout"
         iconName="1x2_normal"
       />
       <FunctionButton
-        title="2x2 Layout"
+        title={intl.formatMessage({ id: "functionArea.2x2Layout" })}
         action="2x2 Layout"
         iconName="2x1_normal"
       />
       <FunctionButton
-        title="4x4 Layout"
+        title={intl.formatMessage({ id: "functionArea.4x4Layout" })}
         action="4x4 Layout"
         iconName="2x2_normal"
       />
       <FunctionButton
-        title="Magnifier"
+        title={intl.formatMessage({ id: "functionArea.magnifier" })}
         action="Magnifier"
         iconName="Magnifier"
       />
       <FunctionButton
-        title="Fit Size"
+        title={intl.formatMessage({ id: "functionArea.fitSize" })}
         action="Fit Size"
         iconName="FitInWindow"
       />
       <FunctionButton
-        title="Original Size"
+        title={intl.formatMessage({ id: "functionArea.originalSize" })}
         action="Original Size"
         iconName="1by1_normal"
       />
-      <FunctionButton title="Zoom Image" action="Zoom Image" iconName="Zoom" />
+      <FunctionButton title={intl.formatMessage({ id: "functionArea.zoomImage" })} action="Zoom Image" iconName="Zoom" />
       <FunctionButton
-        title="Reset Cursor"
+        title={intl.formatMessage({ id: "functionArea.resetCursor" })}
         action="Reset Cursor"
         iconName="btn_pointer"
       />
-      <FunctionButton title="Pan" action="Pan" iconName="Pan" />
+      <FunctionButton title={intl.formatMessage({ id: "functionArea.pan" })} action="Pan" iconName="Pan" />
       <FunctionButton
-        title="Invert Image"
+        title={intl.formatMessage({ id: "functionArea.invertImage" })}
         action="Invert Image"
         iconName="Invert"
       />
       <FunctionButton
-        title="Reset Image"
+        title={intl.formatMessage({ id: "functionArea.resetImage" })}
         action="Reset Image"
         iconName="Reset"
       />
       <FunctionButton
-        title="Snapshot"
+        title={intl.formatMessage({ id: "functionArea.snapshot" })}
         action="Snapshot"
         iconName="imgsnapshot"
       />
       <Divider type="horizontal" style={{ height: 'auto', margin: '8px' }} />
       <FunctionButton
-        title="Advanced Processing"
+        title={intl.formatMessage({ id: "functionArea.advancedProcessing" })}
         action="Advanced Processing"
         iconName="btn_Imageprocess"
       />
 
       <FunctionButton
-        title="Image Measurement"
+        title={intl.formatMessage({ id: "functionArea.imageMeasurement" })}
         action="Image Measurement"
         iconName="btn_Measurements"
       />
       <FunctionButton
-        title="矩形裁剪"
+        title={intl.formatMessage({ id: "functionArea.rectangleCrop" })}
         action="Rectangle Crop"
         iconName="rectangle-crop"
       />
-      <FunctionButton title="More" action="More" iconName="btn_OtherSetting" />
+      <FunctionButton title={intl.formatMessage({ id: "functionArea.more" })} action="More" iconName="btn_OtherSetting" />
     </Flex>
   );
 };