Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shared-localization-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@youversion/platform-react-ui': patch
---

Use shared localization keys for equivalent UI labels, actions, and passage errors. Korean and Czech use English for shared keys that await translations.
8 changes: 5 additions & 3 deletions docs/i18n-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Use `useTranslation` + `t()` for simple strings and `Trans` with `i18nKey` for r
```tsx
const { t } = useTranslation(undefined, { i18n });

<button aria-label={t('shareAriaLabel')}>{t('share')}</button>
<button aria-label={t('share')}>{t('share')}</button>

<Trans
i18nKey="signInWithYouVersion"
Expand All @@ -74,6 +74,8 @@ This is app locale, not Bible translation language. Seed the version picker with

## Local checks

Known translation gaps from the shared-key migration are listed in [Shared localization migration](./shared-localization-migration.md).

```bash
# Hard fail: missing en keys, extra translation keys, interpolation tokens,
# stale resources.generated.ts (index.ts only imports that file)
Expand All @@ -96,6 +98,6 @@ pnpm test:ci-scripts

## Key naming

- Flat camelCase keys in locale JSON (e.g. `shareAriaLabel`, `verseOfTheDay`).
- In platform-localization source, prefix with `react.` (e.g. `react.shareAriaLabel`).
- Flat camelCase keys in locale JSON (e.g. `share`, `verseOfTheDay`).
- Prefer existing shared keys in platform-localization. Prefix React-only source keys with `react.` (e.g. `react.readerSettingsHeading`).
- Interpolation tokens use `{{tokenName}}` and must match across every bundle once translations land.
43 changes: 43 additions & 0 deletions docs/shared-localization-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Shared localization migration

The React UI uses existing shared translation keys for equivalent actions, labels, and messages.
Locale JSON files remain owned by the `platform-localization` sync.

## Missing Korean and Czech translations

At the initial locale inventory revision, `f1c55f10e71a0cd3851908bce31e856f50cd2ad7`, both `ko.json` and `cs.json` lack the shared keys below.
These keys fall back to English until approved translations arrive through the localization sync.
The direct migration accepts this fallback rather than retaining React-specific keys.

| Shared key | Previous React key | Affected UI |
| --- | --- | --- |
| `cancel` | `genericCancel` | Highlights permission dialog |
| `close` | `closeAriaLabel` | Popover close control |
| `error` | `errorHeading` | Bible card and missing app key headings |
| `font` | `fontLabel` | Reader font controls |
| `passageUnavailable` | `passageNotFoundError` | Passage unavailable error |
| `search` | `searchPlaceholder` | Chapter picker and Bible search placeholders |
| `searchLanguages` | `languageSearchAriaLabel` | Language search controls |
| `searchVersions` | `versionSearchAriaLabel` | Version search field |
| `selectLanguage` | `selectLanguageAriaLabel` | Language selector control |
| `regional` | `regionalHeading` | Regional language headings |
| `suggested` | `suggestedTab` | Suggested languages tab |
| `bibleApp` | `bibleAppTitle` | Bible App logo title |

The previous `versionSearchAriaLabel` was also missing in Korean and Czech, so version search already used English.
The other eleven replacements newly fall back to English.
This changes text for eleven keys in Korean and ten in Czech, where the previous Bible App title was already English.
The shared `share` key is present in both locales and replaces `shareAriaLabel` without that gap.

The shared wording also changes some translations in other locales.
English language search labels use "Search Languages", and version search uses "Search Versions".
Distinct messages such as "Reader Settings" retain their existing keys.

## Investigation references

The missing entries belong to the shared keys in `platform-localization/sources/common/en.json` and its Korean and Czech translations.
Translation approval and distribution follow [the i18n workflow](./i18n-guidelines.md).
This migration does not establish why those translations are missing upstream.

Run `node scripts/migrate-shared-i18n-keys.mjs` to check for remaining legacy callers and print the current Korean and Czech gaps.
The optional `--write` argument applies the key substitutions to production TypeScript files.
2 changes: 1 addition & 1 deletion packages/ui/src/components/bible-app-logo-lockup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function BibleAppLogoLockup(props: SVGProps<SVGSVGElement>): React.ReactE
fill="none"
className={cn('yv:text-foreground yv:dark:text-(--yv-yellow-10)', props.className)}
>
<title>{t('bibleAppTitle')}</title>
<title>{t('bibleApp')}</title>
<path
fill="currentColor"
d="M90.856 8.839c.646 0 1.206.111 1.677.336.471.222.866.544 1.184.961v-.001c.318.417.558.921.716 1.51.158.591.237 1.249.237 1.98 0 1.013-.16 1.89-.477 2.633-.318.742-.778 1.316-1.377 1.722-.6.407-1.307.609-2.12.609-.39 0-.771-.065-1.149-.187a3.128 3.128 0 0 1-1.538-1.111v4.444h-2.227V9.121h1.84l.183 1.404c.333-.506.724-.909 1.178-1.191.53-.331 1.155-.495 1.873-.495Zm10.441 0c.646 0 1.206.111 1.677.336.471.222.867.544 1.184.961.318.418.556.923.716 1.511l.056.223c.121.532.182 1.115.182 1.755 0 1.013-.16 1.89-.478 2.633-.318.742-.778 1.316-1.378 1.722-.6.407-1.306.609-2.119.609a3.65 3.65 0 0 1-1.15-.187 3.125 3.125 0 0 1-1.537-1.111v4.444h-2.226V9.121h1.84l.181 1.404c.334-.506.725-.909 1.178-1.191.531-.331 1.156-.495 1.874-.495Zm-53.093 1.37c.3-.372.633-.675 1.006-.9.518-.313 1.132-.468 1.838-.468.507 0 .963.074 1.37.22.406.147.761.355 1.068.626.306.271.562.6.768.99l.003.002c.207.388.36.828.46 1.324.1.495.15 1.038.15 1.627 0 .764-.09 1.453-.273 2.066-.182.613-.448 1.136-.795 1.565a3.54 3.54 0 0 1-1.256.988 3.87 3.87 0 0 1-1.653.345c-.611 0-1.186-.15-1.722-.443-.409-.224-.768-.564-1.077-1.015l-.163 1.175h-1.95V5.697h2.226v4.513ZM64.69 8.84c.706 0 1.322.11 1.846.327.523.218.96.526 1.307.926l.005-.002c.346.4.606.88.777 1.44.17.56.256 1.182.256 1.864v.83h-6.54c.02.33.06.634.125.912.096.406.24.748.433 1.024.195.276.44.485.733.627.293.14.642.21 1.042.21.66 0 1.143-.126 1.45-.379.304-.253.51-.598.617-1.033h2.013c-.166.93-.582 1.665-1.247 2.2-.664.535-1.604.804-2.817.804-.707 0-1.338-.107-1.89-.318a3.627 3.627 0 0 1-1.405-.944 4.061 4.061 0 0 1-.866-1.52c-.194-.593-.292-1.233-.292-2.022 0-.789.107-1.49.318-2.103a4.33 4.33 0 0 1 .911-1.554 3.846 3.846 0 0 1 1.413-.962 4.862 4.862 0 0 1 1.81-.327Zm-20.567 9.47h-2.226V9.121h2.226v9.188Zm14.541-.003h-2.226V5.692h2.226v12.614Zm26.182 0h-2.42l-1.12-3.126h-4.861l-1.12 3.127H72.99l4.806-12.615h2.26l4.789 12.614ZM35.688 5.647c1.144 0 2.037.14 2.685.415.647.278 1.107.659 1.378 1.14.271.483.407 1.043.407 1.678 0 .67-.178 1.267-.53 1.785-.254.37-.645.677-1.17.922.378.15.703.328.958.535h.002c.4.324.687.696.858 1.113.17.418.255.869.255 1.35 0 .72-.157 1.357-.468 1.91-.314.553-.811.987-1.493 1.298-.685.313-1.58.469-2.687.469H31.06V5.647h4.629ZM50.48 10.64c-.46 0-.86.109-1.202.327-.343.217-.61.533-.805.944-.193.413-.291.913-.291 1.502v.513c0 .495.053.922.16 1.282.107.36.253.658.441.893.19.238.419.412.69.523.27.113.578.169.92.169.317 0 .61-.058.875-.17.264-.112.498-.295.698-.548.2-.253.353-.576.46-.972l-.003-.002c.105-.393.158-.857.158-1.421 0-.565-.056-1.043-.167-1.432-.113-.389-.267-.7-.46-.935a1.74 1.74 0 0 0-.67-.513 2.054 2.054 0 0 0-.804-.16Zm39.811 0c-.506 0-.931.118-1.273.353a2.138 2.138 0 0 0-.769.98c-.17.417-.256.898-.256 1.44v.513c0 .435.045.83.134 1.184.09.354.224.658.406.911.183.253.411.445.689.574.276.128.603.193.98.193.436 0 .816-.102 1.14-.309.324-.204.58-.538.769-.998v-.002c.188-.46.282-1.05.282-1.802 0-.753-.096-1.351-.291-1.793-.196-.44-.451-.76-.769-.953a1.967 1.967 0 0 0-1.042-.291Zm10.439 0c-.507 0-.93.118-1.273.353a2.138 2.138 0 0 0-.77.98c-.17.417-.254.898-.254 1.44v.513c0 .435.044.83.133 1.184.089.354.225.658.407.911.182.253.41.445.688.574.276.128.602.193.98.193.435 0 .816-.102 1.14-.309.325-.204.58-.538.769-.998v-.002c.189-.46.282-1.05.282-1.802 0-.753-.097-1.351-.291-1.793-.195-.44-.452-.76-.769-.953a1.97 1.97 0 0 0-1.042-.291Zm-67.498 5.836h2.508c.66 0 1.176-.076 1.547-.23.371-.152.629-.372.778-.661v-.002c.146-.289.22-.634.22-1.033 0-.436-.082-.8-.247-1.096-.164-.293-.425-.515-.778-.662-.353-.147-.83-.22-1.43-.22h-2.598v3.904Zm43.82-3.204h3.627l-1.82-5.145-1.807 5.145Zm-12.38-2.877c-.46 0-.843.082-1.15.246-.306.165-.548.399-.724.699v-.002c-.178.3-.3.653-.371 1.06-.02.12-.031.25-.047.38h4.424a8.022 8.022 0 0 0-.067-.628c-.06-.382-.164-.702-.317-.962a1.494 1.494 0 0 0-.653-.59c-.282-.134-.636-.203-1.096-.203Zm-31.437.426h2.455c.529 0 .958-.064 1.289-.193.328-.13.57-.323.723-.582.151-.258.23-.585.23-.972 0-.386-.08-.7-.238-.935-.16-.236-.418-.413-.778-.53l.002-.006c-.36-.115-.84-.175-1.44-.175h-2.243v3.393Zm9.774-5.428c.378 0 .693.116.938.342.246.227.37.523.37.878 0 .356-.124.647-.37.87-.245.22-.56.33-.938.33-.378 0-.693-.11-.938-.33-.246-.22-.37-.514-.37-.87 0-.355.124-.651.37-.878.245-.224.56-.34.938-.34v-.002Z"
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/components/bible-card.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import i18n from '@/i18n';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { within, expect, userEvent, screen, waitFor } from 'storybook/test';
import { http, HttpResponse } from 'msw';
Expand Down Expand Up @@ -186,7 +187,7 @@ export const WithVersionPicker: Story = {

// Search for Amplified Bible
const searchInput = within(await screen.findByRole('dialog')).getByRole('textbox', {
name: /search bible versions/i,
name: i18n.t('searchVersions'),
});
await userEvent.type(searchInput, 'amplified bible');

Expand Down Expand Up @@ -290,7 +291,7 @@ export const Error: Story = {
await userEvent.click(versionPickerButton);

const dialog = await screen.findByRole('dialog');
const searchInput = within(dialog).getByRole('textbox', { name: /search bible versions/i });
const searchInput = within(dialog).getByRole('textbox', { name: i18n.t('searchVersions') });

await userEvent.type(searchInput, 'amplified bible');

Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/bible-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function BibleCardHeaderError(): React.ReactNode {
const { t } = useTranslation(undefined, { i18n });
return (
<h2 className="yv:font-bold yv:tracking-widest yv:text-xs yv:uppercase yv:text-foreground">
{t('errorHeading')}
{t('error')}
</h2>
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/bible-chapter-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ function Content({ onRequestClose, onSelect }: BibleChapterPickerContentProps) {
<InputGroupInput
tabIndex={1}
type="text"
placeholder={t('searchPlaceholder')}
placeholder={t('search')}
dir="auto"
className="yv:text-base yv:leading-normal"
value={searchQuery}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/bible-reader-search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ function SearchPanel({
enterKeyHint="search"
value={search.query}
autoFocus
placeholder={t('searchPlaceholder')}
placeholder={t('search')}
aria-label={t('bibleSearchAriaLabel', 'Search the Bible')}
onChange={(event) => search.setQuery(event.target.value)}
onKeyDown={(event) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/src/components/bible-reader.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import i18n from '@/i18n';
import { expandPassageId } from '@/lib/highlight-projection';
import { INTER_FONT, SOURCE_SERIF_FONT, UNTITLED_SERIF_FONT } from '@/lib/verse-html-utils';
import type { Meta, StoryObj } from '@storybook/react-vite';
Expand Down Expand Up @@ -420,7 +421,7 @@ export const ForcedRtlChromeGeometry: Story = {
);
await expect(firstVersion.querySelector('bdi')).toHaveAttribute('dir', 'auto');
await expect(
versionCanvas.getByRole('textbox', { name: 'Search Bible versions' }),
versionCanvas.getByRole('textbox', { name: i18n.t('searchVersions') }),
).toHaveAttribute('dir', 'auto');

await userEvent.click(versionCanvas.getByRole('button', { name: 'Close' }));
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/bible-reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ export function BibleThemeSettingsContent({
: '',
)}
>
{t('fontLabel')}
{t('font')}
</span>
<span className="yv:sm:text-xl yv:text-base">{INTER_FONT_NAME}</span>
</div>
Expand All @@ -1547,7 +1547,7 @@ export function BibleThemeSettingsContent({
: '',
)}
>
{t('fontLabel')}
{t('font')}
</span>
<span className="yv:sm:text-xl yv:text-base yv:font-serif">
{UNTITLED_SERIF_FONT_NAME}
Expand Down
10 changes: 5 additions & 5 deletions packages/ui/src/components/bible-version-picker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const tabletJourney: Story = {
await userEvent.click(screen.getByRole('button', { name: /^back$/i }));
await expect(screen.getByRole('tab', { name: /suggested/i })).toBeVisible();
await userEvent.click(screen.getByRole('button', { name: /back to bible versions/i }));
await expect(screen.getByRole('textbox', { name: /search bible versions/i })).toBeVisible();
await expect(screen.getByRole('textbox', { name: i18n.t('searchVersions') })).toBeVisible();
await userEvent.click(screen.getByRole('button', { name: /^Language\b/ }));
await userEvent.click(screen.getByRole('tab', { name: /^All\b/ }));
await userEvent.click(await screen.findByRole('listitem', { name: /Spanish/ }));
Expand Down Expand Up @@ -510,7 +510,7 @@ export const InteractiveVersionSearch: Story = {
await userEvent.click(trigger);

// Type in search
const searchInput = screen.getByRole('textbox', { name: /search bible versions/i });
const searchInput = screen.getByRole('textbox', { name: i18n.t('searchVersions') });
await userEvent.type(searchInput, 'NIV', { delay: 50 });

// Verify search is working (versions should be filtered)
Expand Down Expand Up @@ -613,7 +613,7 @@ export const SearchResetsAfterSelection: Story = {
await userEvent.click(trigger);

// Type in search
const searchInput = screen.getByRole('textbox', { name: /search bible versions/i });
const searchInput = screen.getByRole('textbox', { name: i18n.t('searchVersions') });
await userEvent.type(searchInput, 'Amplified', { delay: 50 });
await expect(searchInput).toHaveValue('Amplified');

Expand All @@ -626,7 +626,7 @@ export const SearchResetsAfterSelection: Story = {
await userEvent.click(updatedTrigger);

// Verify search input is cleared
const resetSearchInput = screen.getByRole('textbox', { name: /search bible versions/i });
const resetSearchInput = screen.getByRole('textbox', { name: i18n.t('searchVersions') });
await expect(resetSearchInput).toHaveValue('');
},
};
Expand Down Expand Up @@ -662,7 +662,7 @@ export const RecentVersionsSearchFilter: Story = {
).toBeInTheDocument();

// Search for "ASV"
const searchInput = screen.getByRole('textbox', { name: /search bible versions/i });
const searchInput = screen.getByRole('textbox', { name: i18n.t('searchVersions') });
await userEvent.type(searchInput, 'ASV', { delay: 50 });

// Verify only ASV appears in recent versions after filtering
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/components/bible-version-picker.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* @vitest-environment jsdom
*/
import i18n from '@/i18n';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, within } from '@testing-library/react';
import type { ReactElement } from 'react';
Expand Down Expand Up @@ -193,7 +194,7 @@ function getLanguageSearchInput() {
}

function getVersionSearchInput() {
return screen.getByRole('textbox', { name: /search bible versions/i });
return screen.getByRole('textbox', { name: i18n.t('searchVersions') });
}

/** Ready-to-run setup for new/edited picker workflows (see docs/testing.md). */
Expand Down Expand Up @@ -728,7 +729,7 @@ describe('BibleVersionPicker', () => {

expect(screen.queryByRole('button', { name: /select a language/i })).not.toBeInTheDocument();
expect(screen.getByRole('button', { name: /^language /i })).toBeInTheDocument();
expect(screen.getAllByRole('textbox', { name: /search bible versions/i })).toHaveLength(1);
expect(screen.getAllByRole('textbox', { name: i18n.t('searchVersions') })).toHaveLength(1);
});

it('mounts one language view, then a search view, and returns to versions', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/bible-version-picker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ export function BibleVersionPickerLanguageTrigger({

return (
<Button
aria-label={ariaLabel ?? t('selectLanguageAriaLabel')}
aria-label={ariaLabel ?? t('selectLanguage')}
className={cn(
'yv:ms-auto yv:bg-card yv:border yv:border-transparent yv:hover:bg-card yv:hover:border-border yv:max-w-40',
className,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const LanguageSearchButton = forwardRef<HTMLButtonElement>(
variant="ghost"
size="icon"
className="yv:w-6 yv:h-6 yv:text-muted-foreground"
aria-label={t('languageSearchAriaLabel')}
aria-label={t('searchLanguages')}
data-slot="language-search-open"
onClick={() => setView('languageSearch')}
>
Expand Down Expand Up @@ -221,7 +221,7 @@ export function BibleLanguagePickerContent({
>
<TabsList className="yv:mx-4 yv:w-[calc(100%-4*var(--spacing)*2)] yv:rounded-full yv:border yv:border-border yv:bg-transparent yv:p-0.5">
<TabsTrigger className={languageTabClassName} value="suggested">
{t('suggestedTab')}
{t('suggested')}
</TabsTrigger>
<TabsTrigger className={languageTabClassName} value="all">
{t('allLanguagesTab', { count: totalLanguages })}
Expand All @@ -232,7 +232,7 @@ export function BibleLanguagePickerContent({
{suggestedLanguages.length > 0 ? (
<>
<h3 className="yv:bg-popover yv:px-4 yv:pb-2 yv:text-xl yv:font-bold">
{t('regionalHeading')}
{t('regional')}
</h3>
<LanguageRows
languages={suggestedLanguages}
Expand Down Expand Up @@ -304,7 +304,7 @@ function LanguageSearchView({
<InputGroup className="yv:h-auto yv:rounded-full yv:border-0 yv:bg-muted yv:py-1 yv:shadow-none">
<InputGroupInput
ref={searchInputRef}
aria-label={t('languageSearchAriaLabel')}
aria-label={t('searchLanguages')}
type="text"
placeholder={t('searchLanguages')}
dir="auto"
Expand Down Expand Up @@ -337,7 +337,7 @@ function LanguageSearchView({
) : suggestedLanguages.length > 0 ? (
<>
<h3 className="yv:bg-popover yv:px-4 yv:pb-2 yv:text-xl yv:font-bold">
{t('regionalHeading')}
{t('regional')}
</h3>
<LanguageRows
languages={suggestedLanguages}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export function VersionList({
<section className="yv:px-4 yv:pt-4">
<InputGroup className="yv:h-auto yv:rounded-full yv:border-0 yv:bg-muted yv:py-1 yv:shadow-none">
<InputGroupInput
aria-label={t('versionSearchAriaLabel')}
aria-label={t('searchVersions')}
type="text"
placeholder={t('searchVersions')}
dir="auto"
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/highlight-permission-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const HighlightPermissionDialog: FC<HighlightPermissionDialogProps> = ({

<div className="yv:flex yv:justify-end yv:gap-2">
<Button variant="secondary" onClick={onCancel}>
{t('genericCancel')}
{t('cancel')}
</Button>
<Button variant="default" onClick={onConfirm}>
{t('dataExchangeContinue')}
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/missing-app-key.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function MissingAppKey({
>
<ExclamationCircle className="yv:size-5 yv:shrink-0 yv:text-foreground" aria-hidden="true" />
<div className="yv:flex yv:flex-col yv:gap-1">
<p className="yv:m-0 yv:text-sm yv:font-semibold yv:leading-tight">{t('errorHeading')}</p>
<p className="yv:m-0 yv:text-sm yv:font-semibold yv:leading-tight">{t('error')}</p>
<p className="yv:m-0 yv:text-[13px] yv:font-medium yv:leading-snug yv:text-muted-foreground">
{t('invalidAppKeyError')}
</p>
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/ui/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function PopoverContent({
className={cn('yv:w-6 yv:h-6 yv:text-muted-foreground', closeButtonClassName)}
>
<XIcon className="yv:size-5" />
<span className="yv:sr-only">{t('closeAriaLabel')}</span>
<span className="yv:sr-only">{t('close')}</span>
</Button>
</PopoverClose>
) : null}
Expand Down
Loading
Loading