feat: modify translation for Collection and keep filtering settings (#35676)

This commit is contained in:
Hanqing Zhao 2026-04-29 14:19:57 +08:00 committed by GitHub
parent 73f7b9daa6
commit 521c145817
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 25 additions and 18 deletions

View File

@ -46,7 +46,10 @@ export function useActivePluginCategory() {
const validatedCategory = getValidatedPluginCategory(categoryFromPath)
const handleChange = useCallback(
(newCategory: string) => {
router.push(`/plugins/${newCategory}`)
// Preserve the current query string (e.g. ?languages=en) so manual
// filters survive a category change.
const search = typeof window !== 'undefined' ? window.location.search : ''
router.push(`/plugins/${newCategory}${search}`)
},
[router],
)
@ -69,7 +72,10 @@ export function useActiveTemplateCategory() {
const validatedCategory = getValidatedTemplateCategory(categoryFromPath)
const handleChange = useCallback(
(newCategory: string) => {
router.push(`/${CREATION_TYPE.templates}/${newCategory}`)
// Preserve the current query string (e.g. ?languages=en) so manual
// filters survive a category change.
const search = typeof window !== 'undefined' ? window.location.search : ''
router.push(`/${CREATION_TYPE.templates}/${newCategory}${search}`)
},
[router],
)

View File

@ -7,6 +7,7 @@ import type { Locale } from '@/i18n-config/language'
import { useLocale, useTranslation } from '#i18n'
import { RiArrowRightSLine } from '@remixicon/react'
import { useEffect, useMemo, useState } from 'react'
import { renderI18nObject } from '@/i18n-config'
import { getLanguage } from '@/i18n-config/language'
import { cn } from '@/utils/classnames'
import { useMarketplaceMoreClick } from '../atoms'
@ -72,14 +73,15 @@ export function CollectionHeader<TCollection extends BaseCollection>({
&& !!collection.search_params
&& itemsLength > GRID_DISPLAY_LIMIT
// The API only ships translations for a subset of locales (typically en_US
// and zh_Hans). For any other locale (e.g. ja_JP, pt_BR) the keyed lookup
// returns undefined and the title/description render as empty divs. Fall
// back to the en_US translation, then to whatever value is available, so
// the header always shows something meaningful.
// The API only ships translations for a subset of locales (e.g. en_US and
// zh_Hans). For any other locale (e.g. ja_JP, pt_BR, zh_Hant before fix)
// the keyed lookup returns undefined and the title/description render as
// empty divs. `renderI18nObject` from `@/i18n-config` handles the fallback
// chain (locale → en_US → first available value) consistently across the
// codebase.
const lang = getLanguage(locale)
const label = collection.label[lang] || collection.label.en_US || Object.values(collection.label)[0] || ''
const description = collection.description[lang] || collection.description.en_US || Object.values(collection.description)[0] || ''
const label = renderI18nObject(collection.label, lang)
const description = renderI18nObject(collection.description, lang)
return (
<div className="mb-2 flex items-end justify-between">

View File

@ -6,7 +6,6 @@ import Link from 'next/link'
import * as React from 'react'
import { useMemo } from 'react'
import AppIcon from '@/app/components/base/app-icon'
import CornerMark from '@/app/components/plugins/card/base/corner-mark'
import { MARKETPLACE_URL_PREFIX } from '@/config'
import useTheme from '@/hooks/use-theme'
import { cn } from '@/utils/classnames'
@ -32,8 +31,8 @@ const TemplateCardComponent = ({
const locale = useLocale()
const { t } = useTranslation()
const { theme } = useTheme()
const { id, template_name, overview, icon, publisher_handle, publisher_type, usage_count, icon_background, deps_plugins, kind } = template
const isSandbox = kind === 'sandboxed'
const { id, template_name, overview, icon, publisher_handle, publisher_type, usage_count, icon_background, deps_plugins } = template
// const isSandbox = kind === 'sandboxed'
const iconUrl = getTemplateIconUrl(template)
const href = useMemo(() => {
@ -63,7 +62,7 @@ const TemplateCardComponent = ({
className,
)}
>
{isSandbox && <CornerMark text="Sandbox" />}
{/* {isSandbox && <CornerMark text="Sandbox" />} */}
{/* Header */}
<div className="flex shrink-0 items-center gap-3 px-4 pb-2 pt-4">
{/* Avatar */}
@ -78,11 +77,11 @@ const TemplateCardComponent = ({
<div className="flex min-w-0 flex-1 flex-col justify-center gap-0.5">
<a
href={href}
className="system-md-medium truncate text-text-primary after:absolute after:inset-0"
className="truncate text-text-primary system-md-medium after:absolute after:inset-0"
>
{template_name}
</a>
<div className="system-xs-regular flex items-center gap-2 text-text-tertiary">
<div className="flex items-center gap-2 text-text-tertiary system-xs-regular">
<span className="relative z-[1] flex shrink-0 items-center gap-1">
<span className="shrink-0">{t('marketplace.templateCard.by', { ns: 'plugin' })}</span>
<Link
@ -105,7 +104,7 @@ const TemplateCardComponent = ({
{/* Description */}
<div className="shrink-0 px-4 pb-2 pt-1">
<p
className="system-xs-regular line-clamp-2 min-h-[32px] text-text-secondary"
className="line-clamp-2 min-h-[32px] text-text-secondary system-xs-regular"
title={overview}
>
{overview}
@ -131,7 +130,7 @@ const TemplateCardComponent = ({
))}
{remainingDepsPluginsCount > 0 && (
<div className="flex items-center justify-center p-0.5">
<span className="system-xs-regular text-text-tertiary">
<span className="text-text-tertiary system-xs-regular">
+
{remainingDepsPluginsCount}
</span>

View File

@ -17,7 +17,7 @@ export type Locale = 'ja_JP' | 'zh_Hans' | 'en_US' | (typeof languages[number])[
export const LanguagesSupported: Locale[] = languages.filter(item => item.supported).map(item => item.value)
export const getLanguage = (locale: Locale): Locale => {
if (['zh-Hans', 'ja-JP'].includes(locale))
if (['zh-Hans', 'zh-Hant', 'ja-JP'].includes(locale))
return locale.replace('-', '_') as Locale
return LanguagesSupported[0].replace('-', '_') as Locale