diff --git a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx index 2352686a460..63658edd521 100644 --- a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx +++ b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.test.tsx @@ -179,4 +179,36 @@ describe('CoreMenuOptions Component', () => { // Check the trailing element is NOT rendered in the component as this is a bot expect(screen.queryByText(/John Doe/)).toBeNull(); }); + + it('should format teammate time according to user locale', () => { + setMockDate(2); // Tuesday + + const stateWithFrenchLocale = { + ...initialState, + entities: { + ...initialState.entities, + users: { + ...initialState.entities.users, + profiles: { + currentUserId: { + locale: 'fr', + }, + }, + }, + }, + }; + + mockedUseTimePostBoxIndicator.mockReturnValue({ + ...defaultUseTimePostBoxIndicatorReturnValue, + isDM: true, + isSelfDM: false, + isBot: false, + }); + + renderComponent(stateWithFrenchLocale); + + // Verify French format (no AM/PM) + const timeTexts = screen.getAllByText(/\d{2}:\d{2}(?!\s*[AP]M)/); + expect(timeTexts.length).toBeGreaterThan(0); + }); }); diff --git a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx index 95f869bb531..d55e5e7409d 100644 --- a/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx +++ b/webapp/channels/src/components/advanced_text_editor/send_button/send_post_options/core_menu_options.tsx @@ -4,6 +4,9 @@ import {DateTime} from 'luxon'; import React, {memo, useCallback} from 'react'; import {FormattedMessage} from 'react-intl'; +import {useSelector} from 'react-redux'; + +import {getCurrentLocale} from 'selectors/i18n'; import useTimePostBoxIndicator from 'components/advanced_text_editor/use_post_box_indicator'; import * as Menu from 'components/menu'; @@ -17,10 +20,23 @@ type Props = { channelId: string; } -function getScheduledTimeInTeammateTimezone(userCurrentTimestamp: number, teammateTimezoneString: string): string { +/** + * Formats a timestamp in the teammate's timezone using the current user's locale. + * @param userCurrentTimestamp - Timestamp in milliseconds (UTC) + * @param teammateTimezoneString - IANA timezone string (e.g., "America/New_York") + * @param userLocale - User's locale code (e.g., "fr", "en", "de") + * @returns Formatted time string respecting the user's locale + * @example + * // US locale: "8:00 AM" + * // French locale: "08:00" + * getScheduledTimeInTeammateTimezone(1635768000000, 'Europe/Paris', 'fr') + */ +function getScheduledTimeInTeammateTimezone(userCurrentTimestamp: number, teammateTimezoneString: string, userLocale: string): string { const scheduledTimeUTC = DateTime.fromMillis(userCurrentTimestamp, {zone: 'utc'}); const teammateScheduledTime = scheduledTimeUTC.setZone(teammateTimezoneString); - const formattedTime = teammateScheduledTime.toFormat('h:mm a'); + const formattedTime = teammateScheduledTime. + setLocale(userLocale). + toLocaleString(DateTime.TIME_SIMPLE); return formattedTime; } @@ -41,6 +57,7 @@ function CoreMenuOptions({handleOnSelect, channelId}: Props) { isBot, } = useTimePostBoxIndicator(channelId); + const locale = useSelector(getCurrentLocale); const now = DateTime.now().setZone(userCurrentTimezone); const tomorrow9amTime = DateTime.now(). setZone(userCurrentTimezone). @@ -66,7 +83,7 @@ function CoreMenuOptions({handleOnSelect, channelId}: Props) { if (isDM && !isBot && !isSelfDM) { const teammateTimezoneString = teammateTimezone.useAutomaticTimezone ? teammateTimezone.automaticTimezone : teammateTimezone.manualTimezone || 'UTC'; - const scheduledTimeInTeammateTimezone = getScheduledTimeInTeammateTimezone(tomorrow9amTime, teammateTimezoneString); + const scheduledTimeInTeammateTimezone = getScheduledTimeInTeammateTimezone(tomorrow9amTime, teammateTimezoneString, locale); const teammateTimeDisplay = (