From abd576bed9cb01e502a15aeebc4f15bc60210995 Mon Sep 17 00:00:00 2001 From: twwu Date: Mon, 21 Jul 2025 17:49:13 +0800 Subject: [PATCH] feat: enhance deprecation notice with improved messaging and localization support --- .../plugins/base/deprecation-notice.tsx | 30 ++++++++++++++----- web/i18n/en-US/plugin.ts | 10 +++++-- web/i18n/ja-JP/plugin.ts | 11 +++++++ web/i18n/zh-Hans/plugin.ts | 10 +++++-- web/utils/format.ts | 4 +++ 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/web/app/components/plugins/base/deprecation-notice.tsx b/web/app/components/plugins/base/deprecation-notice.tsx index b33ece1f9e..a670bee7cb 100644 --- a/web/app/components/plugins/base/deprecation-notice.tsx +++ b/web/app/components/plugins/base/deprecation-notice.tsx @@ -1,9 +1,10 @@ -import React from 'react' +import React, { useMemo } from 'react' import type { FC } from 'react' import Link from 'next/link' import cn from '@/utils/classnames' import { RiAlertFill } from '@remixicon/react' import { Trans, useTranslation } from 'react-i18next' +import { snakeCase2CamelCase } from '@/utils/format' type DeprecationNoticeProps = { status: 'deleted' | 'active' @@ -16,6 +17,8 @@ type DeprecationNoticeProps = { textClassName?: string } +const i18nPrefix = 'plugin.detailPanel.deprecation' + const DeprecationNotice: FC = ({ status, deprecatedReason, @@ -28,7 +31,12 @@ const DeprecationNotice: FC = ({ }) => { const { t } = useTranslation() - if (status !== 'deleted' || !deprecatedReason) + const deprecatedReasonKey = useMemo(() => { + if (!deprecatedReason) return '' + return snakeCase2CamelCase(deprecatedReason) + }, [deprecatedReason]) + + if (status !== 'deleted') return null return ( @@ -43,9 +51,9 @@ const DeprecationNotice: FC = ({
{ - alternativePluginId ? ( + deprecatedReason && alternativePluginId && ( = ({ ), }} values={{ - deprecatedReason, + deprecatedReason: t(`${i18nPrefix}.reason.${deprecatedReasonKey}`), alternativePluginId, }} /> - ) : ( + ) + } + { + deprecatedReason && !alternativePluginId && ( - {t('plugin.detailPanel.deprecation.onlyReason', { deprecatedReason })} + {t(`${i18nPrefix}.onlyReason`, { deprecatedReason: t(`${i18nPrefix}.reason.${deprecatedReasonKey}`) })} ) } + { + !deprecatedReason && ( + {t(`${i18nPrefix}.noReason`)} + ) + }
diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 6393079301..3258144132 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -101,8 +101,14 @@ const translation = { configureModel: 'Configure model', configureTool: 'Configure tool', deprecation: { - fullMessage: 'This plugin has been deprecated due to {{deprecatedReason}}, please use {{-alternativePluginId}} instead.', - onlyReason: 'This plugin has been deprecated due to {{deprecatedReason}}.', + fullMessage: 'This plugin has been deprecated due to {{deprecatedReason}}, and will no longer be updated. Please use {{-alternativePluginId}} instead.', + onlyReason: 'This plugin has been deprecated due to {{deprecatedReason}} and will no longer be updated.', + noReason: 'This plugin has been deprecated and will no longer be updated.', + reason: { + businessAdjustments: 'business adjustments', + ownershipTransferred: 'ownership transferred', + noMaintainer: 'no maintainer', + }, }, }, install: '{{num}} installs', diff --git a/web/i18n/ja-JP/plugin.ts b/web/i18n/ja-JP/plugin.ts index a12de17a16..a80cde7e38 100644 --- a/web/i18n/ja-JP/plugin.ts +++ b/web/i18n/ja-JP/plugin.ts @@ -84,6 +84,16 @@ const translation = { actionNum: '{{num}} {{action}} が含まれています', endpointsDocLink: 'ドキュメントを表示する', switchVersion: 'バージョンの切り替え', + deprecation: { + fullMessage: 'このプラグインは{{deprecatedReason}}のため非推奨となり、新しいバージョンはリリースされません。代わりに{{-alternativePluginId}}をご利用ください。', + onlyReason: 'このプラグインは{{deprecatedReason}}のため非推奨となり、新しいバージョンはリリースされません。', + noReason: 'このプラグインは廃止されており、今後更新されることはありません。', + reason: { + businessAdjustments: '事業調整', + ownershipTransferred: '所有権移転', + noMaintainer: 'メンテナーの不足', + }, + }, }, debugInfo: { title: 'デバッグ', @@ -198,6 +208,7 @@ const translation = { install: '{{num}} インストール', installAction: 'インストール', installFrom: 'インストール元', + deprecated: '非推奨', searchPlugins: '検索プラグイン', search: '検索', endpointsEnabled: '{{num}} セットのエンドポイントが有効になりました', diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index f29a75edc4..4c95101592 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -101,8 +101,14 @@ const translation = { configureModel: '模型设置', configureTool: '工具设置', deprecation: { - fullMessage: '此插件已被弃用,原因是{{deprecatedReason}},请使用 {{-alternativePluginId}} 替代。', - onlyReason: '此插件已被弃用,原因是{{deprecatedReason}}。', + fullMessage: '由于{{deprecatedReason}},此插件已被弃用,将不再发布新版本。请使用{{-alternativePluginId}}替代。', + onlyReason: '由于{{deprecatedReason}},此插件已被弃用,将不再发布新版本。', + noReason: '此插件已被弃用,将不再发布新版本。', + reason: { + businessAdjustments: '业务调整', + ownershipTransferred: '所有权转移', + noMaintainer: '无人维护', + }, }, }, install: '{{num}} 次安装', diff --git a/web/utils/format.ts b/web/utils/format.ts index 720c8f6762..781ec90815 100644 --- a/web/utils/format.ts +++ b/web/utils/format.ts @@ -56,3 +56,7 @@ export const downloadFile = ({ data, fileName }: { data: Blob; fileName: string a.remove() window.URL.revokeObjectURL(url) } + +export const snakeCase2CamelCase = (input: string): string => { + return input.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()) +}