diff --git a/src/renderer/src/components/github-project/ProjectRoadmap.test.tsx b/src/renderer/src/components/github-project/ProjectRoadmap.test.tsx index 2b4c799b8612..0f5a0a2e115e 100644 --- a/src/renderer/src/components/github-project/ProjectRoadmap.test.tsx +++ b/src/renderer/src/components/github-project/ProjectRoadmap.test.tsx @@ -4,6 +4,9 @@ import type { ReactNode } from 'react' import { act, cleanup, fireEvent, render, screen } from '@testing-library/react' import { afterEach, describe, expect, it, vi } from 'vitest' import ProjectRoadmap from './ProjectRoadmap' +import { i18n, setRendererPluginLanguagePacks, setRendererUiLanguage } from '@/i18n/i18n' +import { DEFAULT_LOCALE } from '@/i18n/supported-languages' +import { pluginLanguageResourceId } from '../../../../shared/plugins/plugin-language-pack-artifact' import type { GitHubProjectField, GitHubProjectFieldValue, @@ -94,13 +97,68 @@ function table( } } -afterEach(() => { +afterEach(async () => { cleanup() vi.useRealTimers() window.localStorage.clear() + setRendererPluginLanguagePacks([]) + await setRendererUiLanguage(DEFAULT_LOCALE) }) describe('ProjectRoadmap', () => { + it.each([ + ['pt-BR', 'pt-BR'], + ['en-US-US', DEFAULT_LOCALE] + ])('renders date ticks and bars with plugin locale %s', async (packLocale, dateLocale) => { + const packId = 'plugin:stablyai.orca-portuguese/pt-BR' as const + const resourceLanguage = pluginLanguageResourceId(packId) + // The resource tag recorded in the Windows crash report on #25021. + expect(resourceLanguage).toBe( + 'plugin0070006c007500670069006e003a0073007400610062006c007900610069002e006f007200630061002d0070006f00720074007500670075006500730065002f00700074002d00420052' + ) + setRendererPluginLanguagePacks([ + { + id: packId, + resourceLanguage, + pluginKey: 'stablyai.orca-portuguese', + locale: packLocale, + catalog: { common: { cancel: 'Cancelar' } } + } + ]) + await setRendererUiLanguage(packId) + expect(i18n.resolvedLanguage).toBe(resourceLanguage) + + render( + list} + /> + ) + + const month = new Intl.DateTimeFormat(dateLocale, { + month: 'short', + timeZone: 'UTC' + }).format(new Date(Date.UTC(2026, 8, 1))) + expect(screen.getAllByText(month, { exact: false }).length).toBeGreaterThan(0) + const dateFormat = new Intl.DateTimeFormat(dateLocale, { + year: 'numeric', + month: 'short', + day: 'numeric', + timeZone: 'UTC' + }) + const start = dateFormat.format(new Date(Date.UTC(2026, 8, 1))) + const end = dateFormat.format(new Date(Date.UTC(2026, 9, 15))) + expect(screen.getByRole('button', { name: `Scheduled — ${start} – ${end}` })).toBeTruthy() + }) + it('moves the today marker across local midnight without resetting scroll and cleans up its timer', () => { vi.useFakeTimers() vi.setSystemTime(new Date(2026, 8, 5, 23, 59, 59)) diff --git a/src/renderer/src/components/github-project/ProjectRoadmap.tsx b/src/renderer/src/components/github-project/ProjectRoadmap.tsx index 5e06e41d8700..26c0c40824ee 100644 --- a/src/renderer/src/components/github-project/ProjectRoadmap.tsx +++ b/src/renderer/src/components/github-project/ProjectRoadmap.tsx @@ -3,7 +3,7 @@ import { CalendarClock } from 'lucide-react' import { Button } from '@/components/ui/button' import { usePrefersReducedMotion } from '@/hooks/usePrefersReducedMotion' import { cn } from '@/lib/utils' -import { i18n, translate } from '@/i18n/i18n' +import { getIntlLocale, translate } from '@/i18n/i18n' import ProjectGroupHeader from './ProjectGroupHeader' import ProjectRoadmapBar from './ProjectRoadmapBar' import { ProjectTitleCell } from './ProjectCellIdentity' @@ -48,7 +48,7 @@ export default function ProjectRoadmap({ }: Props): React.JSX.Element { const view = table.selectedView const prefersReducedMotion = usePrefersReducedMotion() - const locale = i18n.resolvedLanguage ?? i18n.language + const locale = getIntlLocale() // Why: the grid lives on UTC calendar days (parseRoadmapDate), so "today" // must be the viewer's LOCAL calendar date mapped to UTC midnight — the raw // instant would shift the marker into the wrong day off UTC.