Dates : en anglais, l'ordre jour/mois suit la région du navigateur (#152)

This commit is contained in:
IliesAllali committed 2026-10-26 11:08:21 +01:00
1 parent 52a3ccd466
commit 3c4eef1c92
5 files changed
+40 -8

No files matched your search

+1 -1
View File
@@ -36,7 +36,7 @@ export default function DateField({ id, value, onChange, placeholder, className
else setText(dateToInputText(parsed))
}}
/>
{touched && invalid && <span className="pz-date-hint" role="status">{t('Une année (1950) ou une date (12/03/1950)')}</span>}
{touched && invalid && <span className="pz-date-hint" role="status">{t('Une année (1950) ou une date ({exemple})', { exemple: dateToInputText('1950-03-12') })}</span>}
</span>
)
}
+1 -1
View File
@@ -468,7 +468,7 @@ export default {
'Merci, c’est envoyé. Le moment apparaîtra dans sa vie quand la personne qui gère l’arbre l’aura accepté.': 'Thanks, it has been sent. The moment will show in their life once the person who manages the tree has accepted it.',
// Dates : année seule, décès sans date (issue #77)
'Année ou date': 'Year or date',
'Une année (1950) ou une date (12/03/1950)': 'A year (1950) or a date (12/03/1950)',
'Une année (1950) ou une date ({exemple})': 'A year (1950) or a date ({exemple})',
'Date inconnue': 'Date unknown',
'date inconnue': 'date unknown',
'Décédé(e), date inconnue': 'Deceased, date unknown',
+17 -2
View File
@@ -32,8 +32,23 @@ function detectLocale() {
export const locale = typeof window === 'undefined' ? 'fr' : detectLocale()
// Pour toLocaleDateString et consorts.
export const dateLocale = locale === 'fr' ? 'fr-FR' : 'en-GB'
// Pour toLocaleDateString et consorts. En anglais, la région du navigateur décide de l'ordre jour/mois
// (en-US : 10/25/2026) ; hors anglais (interface anglaise sur un navigateur allemand…), en-GB (issue #152).
function englishDateLocale() {
const languages = typeof navigator === 'undefined' ? [] : (navigator.languages?.length ? navigator.languages : [navigator.language])
const english = languages.find((lang) => /^en-[a-z]{2}$/i.test(String(lang)))
if (!english) return 'en-GB'
try { return Intl.DateTimeFormat.supportedLocalesOf(english)[0] || 'en-GB' } catch { return 'en-GB' }
}
export const dateLocale = locale === 'fr' ? 'fr-FR' : englishDateLocale()
// Le mois avant le jour dans les dates en chiffres de cette langue (en-US)
export const monthFirst = (() => {
try {
const parts = new Intl.DateTimeFormat(dateLocale, { day: '2-digit', month: '2-digit', year: 'numeric' }).formatToParts(new Date(Date.UTC(2026, 9, 25)))
return parts.findIndex((p) => p.type === 'month') < parts.findIndex((p) => p.type === 'day')
} catch { return false }
})()
if (typeof document !== 'undefined') document.documentElement.lang = locale
+8 -4
View File
@@ -1,14 +1,17 @@
// Saisie d'une date dans la fiche : une année seule (« 1950 ») ou une date complète (« 12/03/1950 »).
// L'année seule se range au 1er janvier, la convention de toute l'appli (issue #77).
// L'ordre jour/mois suit la langue : « 03/12/1950 » pour un navigateur en-US (issue #152).
import { monthFirst } from '../i18n/index.js'
const pad = (n) => String(n).padStart(2, '0')
// Valeur stockée (« 1950-01-01 », « 1950 », « 1950-03-12 ») vers le texte du champ
export function dateToInputText(value) {
export function dateToInputText(value, mdy = monthFirst) {
const raw = String(value ?? '').trim()
if (!raw) return ''
const full = raw.match(/^(\d{4})-(\d{2})-(\d{2})/)
if (full) return full[2] === '01' && full[3] === '01' ? full[1] : `${full[3]}/${full[2]}/${full[1]}`
if (full) if (full[2] === '01' && full[3] === '01') return full[1]
return mdy ? `${full[2]}/${full[3]}/${full[1]}` : `${full[3]}/${full[2]}/${full[1]}`
const year = raw.match(/^(\d{4})$/)
return year ? year[1] : raw
}
@@ -21,7 +24,7 @@ export function formatDigitsAsDate(text) {
}
// Texte du champ vers la valeur stockée : '' si vide, « AAAA-MM-JJ » si valable, undefined si on ne comprend pas
export function parseDateInput(text) {
export function parseDateInput(text, mdy = monthFirst) {
const raw = String(text ?? '').trim()
if (!raw) return ''
if (/^\d{4}$/.test(raw)) return `${raw}-01-01`
@@ -30,7 +33,8 @@ export function parseDateInput(text) {
let year
const dmy = raw.match(/^(\d{1,2})[/.\-\s](\d{1,2})[/.\-\s](\d{4})$/)
const iso = raw.match(/^(\d{4})-(\d{2})-(\d{2})$/)
if (dmy) [, day, month, year] = dmy
if (dmy && mdy) [, month, day, year] = dmy
else if (dmy) [, day, month, year] = dmy
else if (iso) [, year, month, day] = iso
else return undefined
const d = Number(day)
+13
View File
@@ -38,3 +38,16 @@ describe('formatDigitsAsDate', () => {
expect(formatDigitsAsDate('1/3/1950')).toBe('1/3/1950')
})
})
describe('ordre mois/jour d un navigateur en-US (issue #152)', () => {
it('affiche et lit le mois avant le jour', () => {
expect(dateToInputText('1950-03-12', true)).toBe('03/12/1950')
expect(parseDateInput('03/12/1950', true)).toBe('1950-03-12')
expect(parseDateInput('12/25/1950', true)).toBe('1950-12-25')
expect(parseDateInput('25/12/1950', true)).toBeUndefined()
})
it('une année seule ne change pas', () => {
expect(dateToInputText('1950-01-01', true)).toBe('1950')
expect(parseDateInput('1950', true)).toBe('1950-01-01')
})
})