Skip to content

Commit 08237df

Browse files
authored
fix locale review comments from PR 768
1 parent b9a33d1 commit 08237df

6 files changed

Lines changed: 63 additions & 12 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { render } from '@testing-library/react'
3+
import { useLocale } from './locale-provider'
4+
5+
function LocaleConsumer() {
6+
useLocale()
7+
return null
8+
}
9+
10+
describe('useLocale', () => {
11+
it('throws when used outside LocaleProvider', () => {
12+
expect(() => render(<LocaleConsumer />)).toThrow('useLocale must be used within a LocaleProvider')
13+
})
14+
})

src/ui/src/components/locale/locale-provider.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"
22

3-
type LocalePref = "auto" | string
3+
type LocaleTag = string & {}
4+
type LocalePref = "auto" | LocaleTag
45

56
type LocaleProviderProps = {
67
children: React.ReactNode
@@ -53,14 +54,7 @@ function writeStoredPref(storageKey: string, value: LocalePref): void {
5354
}
5455
}
5556

56-
const initialState: LocaleProviderState = {
57-
locale: "auto",
58-
setLocale: () => null,
59-
resolved: "en-US",
60-
auto: "en-US",
61-
}
62-
63-
const LocaleProviderContext = createContext<LocaleProviderState>(initialState)
57+
const LocaleProviderContext = createContext<LocaleProviderState | undefined>(undefined)
6458

6559
export function LocaleProvider({
6660
children,

src/ui/src/lib/datetime.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { withTimeZone } from './datetime'
3+
4+
describe('withTimeZone', () => {
5+
it('strips pre-existing option timezone when local is requested', () => {
6+
expect(withTimeZone({ hour: '2-digit', timeZone: 'UTC' }, 'local')).toEqual({
7+
hour: '2-digit',
8+
})
9+
})
10+
11+
it('overrides pre-existing option timezone when a specific timezone is requested', () => {
12+
expect(withTimeZone({ hour: '2-digit', timeZone: 'UTC' }, 'America/New_York')).toEqual({
13+
hour: '2-digit',
14+
timeZone: 'America/New_York',
15+
})
16+
})
17+
})

src/ui/src/lib/datetime.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import { useLocale } from '@/components/locale/locale-provider'
33

44
export type DateTimeFormatOptions = Intl.DateTimeFormatOptions
55

6-
function withTimeZone(opts: DateTimeFormatOptions, timeZone?: string): DateTimeFormatOptions {
7-
if (!timeZone || timeZone === 'local') return opts
8-
return { ...opts, timeZone }
6+
export function withTimeZone(opts: DateTimeFormatOptions, timeZone?: string): DateTimeFormatOptions {
7+
const { timeZone: _ignored, ...rest } = opts
8+
if (!timeZone || timeZone === 'local') return rest
9+
return { ...rest, timeZone }
910
}
1011

1112
/**
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, expect, it, vi } from 'vitest'
2+
import { render, screen } from '@testing-library/react'
3+
import ProfilePanel from './ProfilePanel'
4+
5+
vi.mock('@/components/locale/locale-provider', () => ({
6+
useLocale: () => ({
7+
locale: 'en',
8+
setLocale: vi.fn(),
9+
resolved: 'en',
10+
auto: 'en-US',
11+
}),
12+
}))
13+
14+
describe('ProfilePanel locale selector', () => {
15+
it('keeps an unknown stored locale selectable', () => {
16+
render(<ProfilePanel me={null} />)
17+
expect(screen.getByRole('combobox')).toHaveTextContent('· en')
18+
})
19+
})

src/ui/src/settings/ProfilePanel.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export default function ProfilePanel({
109109
.map((tag) => ({ value: tag, label: localeLabel(tag, resolved) }))
110110
.sort((a, b) => collator.compare(a.label, b.label))
111111
}, [resolved])
112+
const hasLocaleChoice = locale === 'auto' || LOCALE_TAGS.includes(locale)
112113
const sample = previewDate(resolved)
113114

114115
const saveProfile = async () => {
@@ -256,6 +257,11 @@ export default function ProfilePanel({
256257
</SelectTrigger>
257258
<SelectContent>
258259
<SelectItem value="auto">{`Auto · ${auto}`}</SelectItem>
260+
{!hasLocaleChoice && (
261+
<SelectItem value={locale}>
262+
{localeLabel(locale, resolved)} · {locale}
263+
</SelectItem>
264+
)}
259265
{localeChoices.map((c) => (
260266
<SelectItem key={c.value} value={c.value}>
261267
{c.label} · {c.value}

0 commit comments

Comments
 (0)