From bc1099b130fa7bf08f9e87b896cb42be4d65a6ff Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Thu, 13 Jun 2024 12:49:01 +0530 Subject: [PATCH 01/25] feat: global date time formatting through i18n --- .../guides/date-time-formatting.mdx | 85 ++++++++++++++ .../message-edited-timestamp.mdx | 32 +---- .../ui-components/message-footer.mdx | 10 ++ docusaurus/sidebars-react-native.json | 1 + package/package.json | 3 +- package/src/components/Channel/Channel.tsx | 7 +- .../Channel/hooks/useCreateMessagesContext.ts | 2 + .../ChannelPreview/ChannelPreviewStatus.tsx | 18 ++- .../hooks/useLatestMessagePreview.ts | 35 ++---- .../components/ImageGalleryHeader.tsx | 20 +++- .../MessageSimple/MessageEditedTimestamp.tsx | 15 ++- .../Message/MessageSimple/MessageFooter.tsx | 17 +-- .../MessageSimple/MessageTimestamp.tsx | 28 ++--- .../MessageList/InlineDateSeparator.tsx | 22 +++- .../components/MessageList/MessageList.tsx | 39 ++----- .../components/MessageList/MessageSystem.tsx | 14 ++- .../components/MessageList/StickyHeader.tsx | 57 +++++++++ package/src/components/index.ts | 1 + .../channelContext/ChannelContext.tsx | 3 +- .../messagesContext/MessagesContext.tsx | 6 + package/src/i18n/calendarFormats.ts | 110 ++++++++++++++++++ package/src/i18n/en.json | 11 +- package/src/i18n/es.json | 11 +- package/src/i18n/fr.json | 11 +- package/src/i18n/he.json | 11 +- package/src/i18n/hi.json | 11 +- package/src/i18n/it.json | 11 +- package/src/i18n/ja.json | 11 +- package/src/i18n/ko.json | 11 +- package/src/i18n/nl.json | 11 +- package/src/i18n/pt-BR.json | 11 +- package/src/i18n/ru.json | 11 +- package/src/i18n/tr.json | 11 +- package/src/index.ts | 3 + package/src/utils/Streami18n.ts | 99 +++++++--------- package/src/utils/getDateString.ts | 71 ++++++----- package/src/utils/predefinedFormatters.ts | 59 ++++++++++ package/yarn.lock | 26 +++-- 38 files changed, 665 insertions(+), 250 deletions(-) create mode 100644 docusaurus/docs/reactnative/guides/date-time-formatting.mdx create mode 100644 package/src/components/MessageList/StickyHeader.tsx create mode 100644 package/src/i18n/calendarFormats.ts create mode 100644 package/src/utils/predefinedFormatters.ts diff --git a/docusaurus/docs/reactnative/guides/date-time-formatting.mdx b/docusaurus/docs/reactnative/guides/date-time-formatting.mdx new file mode 100644 index 0000000000..acc8b8288c --- /dev/null +++ b/docusaurus/docs/reactnative/guides/date-time-formatting.mdx @@ -0,0 +1,85 @@ +--- +id: date-time-formatting +title: Date and time formatting +--- + +In this guide we will learn how date a time formatting can be customized within SDK's components. + +## SDK components displaying date & time + +The following components provided by the SDK display datetime: + +- `ChannelPreviewStatus` - Component showing last message date and time in `ChannelList`. +- `ImageGalleryHeader` - Component showing the header in the `ImageGallery`. +- `InlineDateSeparator` - Component separating groups of messages in `MessageList`. +- `MessageEditedTimestamp` - Component showing edited message time when clicked on an edited message. +- `MessageSystem` - Component showing system message. +- `MessageTimestamp` - Component showing message timestamp. +- `StickyHeader` - Component showing sticky header on the top of the `MessageList`/`Channel`. + +## Format Customization + +The datetime format can be customized by providing date format through the `i18n` JSON. + +### Date & time formatting with i18n service + +Formatting via i18n service allows for SDK wide configuration. The configuration is stored with other translations in JSON files. Formatting with i18n service has the following advantages: + +- It is centralized. +- It takes into consideration the locale out of the box. +- Allows for high granularity - formatting per string, not component (opposed to props approach). +- Allows for high re-usability - apply the same configuration in multiple places via the same translation key. +- Allows for custom formatting logic. + +The default datetime formatting configuration is stored in the JSON translation files. The default translation keys are namespaced with prefix `timestamp/` followed by the component name. For example, the message date formatting can be targeted via `timestamp/MessageTimestamp`, because the underlying component is called `MessageTimestamp`. + +We can apply custom configuration in all the translation JSON files. It could look similar to the following example key-value pair. + +```json +"timestamp/SystemMessage": "{{ timestamp, timestampFormatter(format: YYYY) }}", +``` + +Besides overriding the formatting parameters above, we can customize the translation key via `timestampTranslationKey` prop. All the above components (`ChannelPreviewStatus`, `ImageGalleryHeader`, `InlineDateSeparator`, `MessageEditedTimestamp`, `MessageSystem`, `MessageTimestamp`, `StickyHeader`) accept this prop. + +```tsx +import { MessageTimestampProps, MessageTimestamp } from 'stream-chat-react-native'; + +const CustomMessageTimestamp = (props: MessageTimestampProps) => ( + +); +``` + +### Understanding the formatting syntax + +Once the default prop values are nullified, we override the default formatting rules in the JSON translation value. We can take a look at an example: + +```json +"timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", +``` + +or + +```json +"timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", +``` + +Let's dissect the example: + +- The curly brackets (`{{`, `}}`) indicate the place where a value will be interpolated (inserted) into the string. +- Variable `timestamp` is the name of variable which value will be inserted into the string +- The `timestampFormatter` is the name of the formatting function that is used to convert the `timestamp` value into desired format +- The `timestampFormatter` can be passed the same parameters as the React components (`calendar`, `calendarFormats`, `format`) as if the function was called with these values. + +:::note +For `calendarFormats`, you don't have to provide all the formats. Provide only the formats you want to customize. +::: + +Params: + +- `calendar` - This is a boolean field to decide if the date format should be in calendar format or not. The default value is `false`. +- `calendarFormats` - This is an object that contains the formats for the calendar. The default value is `{ sameDay: 'LT', nextDay: 'LT', nextWeek: 'dddd', lastDay: 'dddd', lastWeek: 'dddd', sameElse: 'L' }`. +- `format` - This is a string that contains the format of the date. + +:::note +The described rules follow the formatting rules required by the i18n library used under the hood - `i18next`. You can learn more about the rules in [the formatting section of the `i18next` documentation](https://www.i18next.com/translation-function/formatting#basic-usage). +::: diff --git a/docusaurus/docs/reactnative/ui-components/message-edited-timestamp.mdx b/docusaurus/docs/reactnative/ui-components/message-edited-timestamp.mdx index 904b7185c7..c09292a6f7 100644 --- a/docusaurus/docs/reactnative/ui-components/message-edited-timestamp.mdx +++ b/docusaurus/docs/reactnative/ui-components/message-edited-timestamp.mdx @@ -11,38 +11,16 @@ This is the default component provided to the prop [`MessageEditedTimestamp`](.. ## Props -###
_overrides the value from [MessageContext](../../contexts/message-context#message)_
`message` {#message} +###
_overrides the value from [MessageContext](../../contexts/message-context#message)_
`message` `{#message}` -### `calendar` +## UI components -Whether to show the time in Calendar time format. Calendar time displays time relative to a today's date. +### `MessageTimestamp` -| Type | Default | -| ---------------------- | ----------- | -| `Boolean`\|`undefined` | `undefined` | - -### `format` - -Format of the date. - -| Type | Default | -| --------------------- | ----------- | -| `String`\|`undefined` | `undefined` | - -### `formatDate` - -Function to format the date. - -| Type | Default | -| ----------------------- | ----------- | -| `Function`\|`undefined` | `undefined` | - -### `timestamp` - -The date to be shown after formatting. +The Component that renders the message timestamp. | Type | Default | | ----------------------------- | ----------- | -| `String`\|`Date`\|`undefined` | `undefined` | +| `ComponentType` \|`undefined` | `undefined` | diff --git a/docusaurus/docs/reactnative/ui-components/message-footer.mdx b/docusaurus/docs/reactnative/ui-components/message-footer.mdx index d43a276d27..45ada17548 100644 --- a/docusaurus/docs/reactnative/ui-components/message-footer.mdx +++ b/docusaurus/docs/reactnative/ui-components/message-footer.mdx @@ -77,3 +77,13 @@ Weather message is deleted or not. In case of deleted message, `'Only visible to ###
_overrides the value from [MessageContext](../../contexts/message-context#showmessagestatus)_
`showMessageStatus` {#showmessagestatus} + +## UI Components + +### `MessageTimestamp` + +The Component that renders the message timestamp. + +| Type | Default | +| ----------------------------- | ----------- | +| `ComponentType` \|`undefined` | `undefined` | diff --git a/docusaurus/sidebars-react-native.json b/docusaurus/sidebars-react-native.json index b4879ebd97..fc4f57a716 100644 --- a/docusaurus/sidebars-react-native.json +++ b/docusaurus/sidebars-react-native.json @@ -129,6 +129,7 @@ ], "Advanced Guides": [ "guides/audio-messages-support", + "guides/date-time-formatting", "customization/typescript", "basics/troubleshooting", "basics/stream_chat_with_navigation", diff --git a/package/package.json b/package/package.json index be811213a9..c0be6e36b4 100644 --- a/package/package.json +++ b/package/package.json @@ -71,7 +71,8 @@ "@gorhom/bottom-sheet": "4.4.8", "dayjs": "1.10.5", "emoji-regex": "^10.3.0", - "i18next": "20.2.4", + "i18next": "^21.6.14", + "intl-pluralrules": "^2.0.1", "linkifyjs": "^4.1.1", "lodash-es": "4.17.21", "mime-types": "^2.1.34", diff --git a/package/src/components/Channel/Channel.tsx b/package/src/components/Channel/Channel.tsx index 25a38793ea..b42bfe0c50 100644 --- a/package/src/components/Channel/Channel.tsx +++ b/package/src/components/Channel/Channel.tsx @@ -127,6 +127,7 @@ import { MessageReplies as MessageRepliesDefault } from '../Message/MessageSimpl import { MessageRepliesAvatars as MessageRepliesAvatarsDefault } from '../Message/MessageSimple/MessageRepliesAvatars'; import { MessageSimple as MessageSimpleDefault } from '../Message/MessageSimple/MessageSimple'; import { MessageStatus as MessageStatusDefault } from '../Message/MessageSimple/MessageStatus'; +import { MessageTimestamp as MessageTimestampDefault } from '../Message/MessageSimple/MessageTimestamp'; import { ReactionList as ReactionListDefault } from '../Message/MessageSimple/ReactionList'; import { AttachButton as AttachButtonDefault } from '../MessageInput/AttachButton'; import { CommandsButton as CommandsButtonDefault } from '../MessageInput/CommandsButton'; @@ -156,6 +157,7 @@ import { MessageList as MessageListDefault } from '../MessageList/MessageList'; import { MessageSystem as MessageSystemDefault } from '../MessageList/MessageSystem'; import { NetworkDownIndicator as NetworkDownIndicatorDefault } from '../MessageList/NetworkDownIndicator'; import { ScrollToBottomButton as ScrollToBottomButtonDefault } from '../MessageList/ScrollToBottomButton'; +import { StickyHeader as StickyHeaderDefault } from '../MessageList/StickyHeader'; import { TypingIndicator as TypingIndicatorDefault } from '../MessageList/TypingIndicator'; import { TypingIndicatorContainer as TypingIndicatorContainerDefault } from '../MessageList/TypingIndicatorContainer'; import { OverlayReactionList as OverlayReactionListDefault } from '../MessageOverlay/OverlayReactionList'; @@ -305,6 +307,7 @@ export type ChannelPropsWithContext< | 'MessageStatus' | 'MessageSystem' | 'MessageText' + | 'MessageTimestamp' | 'myMessageTheme' | 'onLongPressMessage' | 'onPressInMessage' @@ -542,6 +545,7 @@ const ChannelWithContext = < MessageStatus = MessageStatusDefault, MessageSystem = MessageSystemDefault, MessageText, + MessageTimestamp = MessageTimestampDefault, MoreOptionsButton = MoreOptionsButtonDefault, myMessageTheme, NetworkDownIndicator = NetworkDownIndicatorDefault, @@ -573,7 +577,7 @@ const ChannelWithContext = < ShowThreadMessageInChannelButton = ShowThreadMessageInChannelButtonDefault, StartAudioRecordingButton = AudioRecordingButtonDefault, stateUpdateThrottleInterval = defaultThrottleInterval, - StickyHeader, + StickyHeader = StickyHeaderDefault, supportedReactions = reactionData, t, thread: threadProps, @@ -2328,6 +2332,7 @@ const ChannelWithContext = < MessageStatus, MessageSystem, MessageText, + MessageTimestamp, myMessageTheme, onLongPressMessage, onPressInMessage, diff --git a/package/src/components/Channel/hooks/useCreateMessagesContext.ts b/package/src/components/Channel/hooks/useCreateMessagesContext.ts index 87c33be1e1..caeab52edc 100644 --- a/package/src/components/Channel/hooks/useCreateMessagesContext.ts +++ b/package/src/components/Channel/hooks/useCreateMessagesContext.ts @@ -69,6 +69,7 @@ export const useCreateMessagesContext = < MessageStatus, MessageSystem, MessageText, + MessageTimestamp, myMessageTheme, onLongPressMessage, onPressInMessage, @@ -165,6 +166,7 @@ export const useCreateMessagesContext = < MessageStatus, MessageSystem, MessageText, + MessageTimestamp, myMessageTheme, onLongPressMessage, onPressInMessage, diff --git a/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx b/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx index ec0a4142ed..9a65763155 100644 --- a/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx +++ b/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { ChannelPreviewProps } from './ChannelPreview'; @@ -6,9 +6,11 @@ import type { ChannelPreviewMessengerPropsWithContext } from './ChannelPreviewMe import { MessageReadStatus } from './hooks/useLatestMessagePreview'; import { useTheme } from '../../contexts/themeContext/ThemeContext'; +import { useTranslationContext } from '../../contexts/translationContext/TranslationContext'; import { Check, CheckAll } from '../../icons'; import type { DefaultStreamChatGenerics } from '../../types/types'; +import { getDateString } from '../../utils/getDateString'; const styles = StyleSheet.create({ date: { @@ -35,6 +37,7 @@ export const ChannelPreviewStatus = < props: ChannelPreviewStatusProps, ) => { const { formatLatestMessageDate, latestMessagePreview } = props; + const { t, tDateTimeParser } = useTranslationContext(); const { theme: { channelPreview: { checkAllIcon, checkIcon, date }, @@ -44,6 +47,17 @@ export const ChannelPreviewStatus = < const created_at = latestMessagePreview.messageObject?.created_at; const latestMessageDate = created_at ? new Date(created_at) : new Date(); + + const formattedDate = useMemo( + () => + getDateString({ + date: created_at, + t, + tDateTimeParser, + timestampTranslationKey: 'timestamp/ChannelPreviewStatus', + }), + [created_at, t, tDateTimeParser], + ); const status = latestMessagePreview.status; return ( @@ -56,7 +70,7 @@ export const ChannelPreviewStatus = < {formatLatestMessageDate && latestMessageDate ? formatLatestMessageDate(latestMessageDate).toString() - : latestMessagePreview.created_at.toString()} + : formattedDate} ); diff --git a/package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts b/package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts index 0238cf9f5f..29c69a5622 100644 --- a/package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts +++ b/package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts @@ -1,13 +1,10 @@ import { useEffect, useState } from 'react'; +import { TFunction } from 'i18next'; import type { Channel, ChannelState, MessageResponse, StreamChat, UserResponse } from 'stream-chat'; import { useChatContext } from '../../../contexts/chatContext/ChatContext'; -import { - isDayOrMoment, - TDateTimeParser, - useTranslationContext, -} from '../../../contexts/translationContext/TranslationContext'; +import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext'; import { useTranslatedMessage } from '../../../hooks/useTranslatedMessage'; import type { DefaultStreamChatGenerics } from '../../../types/types'; @@ -21,13 +18,13 @@ type LatestMessage< export type LatestMessagePreview< StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, > = { - created_at: string | number | Date; messageObject: LatestMessage | undefined; previews: { bold: boolean; text: string; }[]; status: number; + created_at?: string | Date; }; const getMessageSenderName = < @@ -131,22 +128,6 @@ const getLatestMessageDisplayText = < ]; }; -const getLatestMessageDisplayDate = < - StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, ->( - message: LatestMessage | undefined, - tDateTimeParser: TDateTimeParser, -) => { - const parserOutput = tDateTimeParser(message?.created_at); - if (isDayOrMoment(parserOutput)) { - if (parserOutput.isSame(new Date(), 'day')) { - return parserOutput.format('LT'); - } - return parserOutput.format('L'); - } - return parserOutput; -}; - export enum MessageReadStatus { NOT_SENT_BY_CURRENT_USER = 0, UNREAD = 1, @@ -190,13 +171,12 @@ const getLatestMessagePreview = < channel: Channel; client: StreamChat; readEvents: boolean; - t: (key: string) => string; - tDateTimeParser: TDateTimeParser; + t: TFunction; lastMessage?: | ReturnType['formatMessage']> | MessageResponse; }) => { - const { channel, client, lastMessage, readEvents, t, tDateTimeParser } = params; + const { channel, client, lastMessage, readEvents, t } = params; const messages = channel.state.messages; @@ -219,7 +199,7 @@ const getLatestMessagePreview = < const message = lastMessage !== undefined ? lastMessage : channelStateLastMessage; return { - created_at: getLatestMessageDisplayDate(message, tDateTimeParser), + created_at: message?.created_at, messageObject: message, previews: getLatestMessageDisplayText(channel, client, message, t), status: getLatestMessageReadStatus(channel, client, message, readEvents), @@ -240,7 +220,7 @@ export const useLatestMessagePreview = < forceUpdate: number, ) => { const { client } = useChatContext(); - const { t, tDateTimeParser } = useTranslationContext(); + const { t } = useTranslationContext(); const channelConfigExists = typeof channel?.getConfig === 'function'; @@ -286,7 +266,6 @@ export const useLatestMessagePreview = < lastMessage: translatedLastMessage, readEvents, t, - tDateTimeParser, }), ), [channelLastMessageString, forceUpdate, readEvents, readStatus], diff --git a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx index 834eb6ba61..50123c4e4e 100644 --- a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +++ b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx @@ -70,6 +70,8 @@ type Props; visible: Animated.SharedValue; photo?: Photo; + /* Lookup key in the language corresponding translations sheet to perform date formatting */ + timestampTranslationKey?: string; }; export const ImageGalleryHeader = < @@ -77,7 +79,16 @@ export const ImageGalleryHeader = < >( props: Props, ) => { - const { centerElement, CloseIcon, leftElement, opacity, photo, rightElement, visible } = props; + const { + centerElement, + CloseIcon, + leftElement, + opacity, + photo, + rightElement, + timestampTranslationKey = 'timestamp/ImageGalleryHeader', + visible, + } = props; const [height, setHeight] = useState(200); const { theme: { @@ -98,7 +109,12 @@ export const ImageGalleryHeader = < const { t, tDateTimeParser } = useTranslationContext(); const { setOverlay } = useOverlayContext(); - const date = getDateString({ calendar: true, date: photo?.created_at, tDateTimeParser }); + const date = getDateString({ + date: photo?.created_at, + t, + tDateTimeParser, + timestampTranslationKey, + }); const headerStyle = useAnimatedStyle(() => ({ opacity: opacity.value, diff --git a/package/src/components/Message/MessageSimple/MessageEditedTimestamp.tsx b/package/src/components/Message/MessageSimple/MessageEditedTimestamp.tsx index 7db27bf123..2ce2963a96 100644 --- a/package/src/components/Message/MessageSimple/MessageEditedTimestamp.tsx +++ b/package/src/components/Message/MessageSimple/MessageEditedTimestamp.tsx @@ -1,12 +1,11 @@ import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; -import { MessageTimestamp, MessageTimestampProps } from './MessageTimestamp'; - import { MessageContextValue, useMessageContext, } from '../../../contexts/messageContext/MessageContext'; +import { MessagesContextValue } from '../../../contexts/messagesContext/MessagesContext'; import { useTheme } from '../../../contexts/themeContext/ThemeContext'; import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext'; import { DefaultStreamChatGenerics } from '../../../types/types'; @@ -14,14 +13,15 @@ import { isEditedMessage } from '../../../utils/utils'; export type MessageEditedTimestampProps< StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, -> = Partial, 'message'>> & MessageTimestampProps; +> = Partial, 'message'>> & + Partial, 'MessageTimestamp'>>; export const MessageEditedTimestamp = < StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, >( props: MessageEditedTimestampProps, ) => { - const { message: propMessage, timestamp } = props; + const { message: propMessage, MessageTimestamp } = props; const { theme: { colors: { grey }, @@ -41,7 +41,12 @@ export const MessageEditedTimestamp = < return ( {t('Edited') + ' '} - + {MessageTimestamp && ( + + )} ); }; diff --git a/package/src/components/Message/MessageSimple/MessageFooter.tsx b/package/src/components/Message/MessageSimple/MessageFooter.tsx index 3f048e5a7b..b16e2dcf6f 100644 --- a/package/src/components/Message/MessageSimple/MessageFooter.tsx +++ b/package/src/components/Message/MessageSimple/MessageFooter.tsx @@ -5,8 +5,6 @@ import type { Attachment } from 'stream-chat'; import type { MessageStatusProps } from './MessageStatus'; -import { MessageTimestamp } from './MessageTimestamp'; - import type { ChannelContextValue } from '../../../contexts/channelContext/ChannelContext'; import { Alignment, @@ -46,7 +44,10 @@ type MessageFooterPropsWithContext< > & Pick< MessagesContextValue, - 'deletedMessagesVisibilityType' | 'MessageEditedTimestamp' | 'MessageStatus' + | 'deletedMessagesVisibilityType' + | 'MessageEditedTimestamp' + | 'MessageStatus' + | 'MessageTimestamp' > & MessageFooterComponentProps; @@ -98,6 +99,7 @@ const MessageFooterWithContext = < message, MessageEditedTimestamp, MessageStatus, + MessageTimestamp, otherAttachments, showMessageStatus, } = props; @@ -118,7 +120,7 @@ const MessageFooterWithContext = < {deletedMessagesVisibilityType === 'sender' && ( )} - + ); } @@ -137,7 +139,7 @@ const MessageFooterWithContext = < {message.user.name} ) : null} {showMessageStatus && } - + {isEditedMessage(message) && !isEditedMessageOpen && ( <> @@ -160,7 +162,7 @@ const MessageFooterWithContext = < )} {isEditedMessageOpen && ( - + )} ); @@ -270,7 +272,7 @@ export const MessageFooter = < showMessageStatus, } = useMessageContext(); - const { deletedMessagesVisibilityType, MessageEditedTimestamp, MessageStatus } = + const { deletedMessagesVisibilityType, MessageEditedTimestamp, MessageStatus, MessageTimestamp } = useMessagesContext(); return ( @@ -284,6 +286,7 @@ export const MessageFooter = < message, MessageEditedTimestamp, MessageStatus, + MessageTimestamp, otherAttachments, showMessageStatus, }} diff --git a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx index f1ccc2afd4..639b86dab3 100644 --- a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx +++ b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx @@ -3,25 +3,12 @@ import { StyleSheet, Text } from 'react-native'; import { useTheme } from '../../../contexts/themeContext/ThemeContext'; import { - TDateTimeParserInput, TranslationContextValue, useTranslationContext, } from '../../../contexts/translationContext/TranslationContext'; import { getDateString } from '../../../utils/getDateString'; export type MessageTimestampProps = Partial> & { - /** - * Whether to show the time in Calendar time format. Calendar time displays time relative to a today's date. - */ - calendar?: boolean; - /** - * The format in which the date should be displayed. - */ - format?: string; - /** - * A function to format the date. - */ - formatDate?: (date: TDateTimeParserInput) => string; /** * Already Formatted date */ @@ -30,16 +17,18 @@ export type MessageTimestampProps = Partial { const { - calendar, - format, - formatDate, formattedDate, tDateTimeParser: propsTDateTimeParser, timestamp, + timestampTranslationKey = 'timestamp/MessageTimestamp', } = props; const { @@ -50,7 +39,7 @@ export const MessageTimestamp = (props: MessageTimestampProps) => { }, }, } = useTheme(); - const { tDateTimeParser: contextTDateTimeParser } = useTranslationContext(); + const { t, tDateTimeParser: contextTDateTimeParser } = useTranslationContext(); if (formattedDate) { return ( @@ -61,11 +50,10 @@ export const MessageTimestamp = (props: MessageTimestampProps) => { if (!timestamp) return null; const dateString = getDateString({ - calendar, date: timestamp, - format, - formatDate, + t, tDateTimeParser: propsTDateTimeParser || contextTDateTimeParser, + timestampTranslationKey, }); if (!dateString) return null; diff --git a/package/src/components/MessageList/InlineDateSeparator.tsx b/package/src/components/MessageList/InlineDateSeparator.tsx index 19444cfcca..1c90090318 100644 --- a/package/src/components/MessageList/InlineDateSeparator.tsx +++ b/package/src/components/MessageList/InlineDateSeparator.tsx @@ -22,29 +22,41 @@ const styles = StyleSheet.create({ }, }); +/** + * Props for the `InlineDateSeparator` component. + */ export type InlineDateSeparatorProps = { + /** + * Date to be displayed. + */ date?: Date; + /* + * Lookup key in the language corresponding translations sheet to perform date formatting + */ + timestampTranslationKey?: string; }; -export const InlineDateSeparator = ({ date }: InlineDateSeparatorProps) => { +export const InlineDateSeparator = ({ + date, + timestampTranslationKey = 'timestamp/InlineDateSeparator', +}: InlineDateSeparatorProps) => { const { theme: { colors: { overlay, white }, inlineDateSeparator: { container, text }, }, } = useTheme(); - const { tDateTimeParser } = useTranslationContext(); + const { t, tDateTimeParser } = useTranslationContext(); if (!date) { return null; } - const dateFormat = date.getFullYear() === new Date().getFullYear() ? 'MMM D' : 'MMM D, YYYY'; - const dateString = getDateString({ date, - format: dateFormat, + t, tDateTimeParser, + timestampTranslationKey, }); return ( diff --git a/package/src/components/MessageList/MessageList.tsx b/package/src/components/MessageList/MessageList.tsx index cf2d384095..e3734bd19e 100644 --- a/package/src/components/MessageList/MessageList.tsx +++ b/package/src/components/MessageList/MessageList.tsx @@ -51,13 +51,8 @@ import { } from '../../contexts/paginatedMessageListContext/PaginatedMessageListContext'; import { mergeThemes, ThemeProvider, useTheme } from '../../contexts/themeContext/ThemeContext'; import { ThreadContextValue, useThreadContext } from '../../contexts/threadContext/ThreadContext'; -import { - TranslationContextValue, - useTranslationContext, -} from '../../contexts/translationContext/TranslationContext'; import type { DefaultStreamChatGenerics } from '../../types/types'; -import { getDateString } from '../../utils/getDateString'; const WAIT_FOR_SCROLL_TO_OFFSET_TIMEOUT = 150; const MAX_RETRIES_AFTER_SCROLL_FAILURE = 10; @@ -156,8 +151,7 @@ type MessageListPropsWithContext< | 'TypingIndicator' | 'TypingIndicatorContainer' > & - Pick, 'loadMoreThread' | 'thread'> & - Pick & { + Pick, 'loadMoreThread' | 'thread'> & { /** * Besides existing (default) UX behavior of underlying FlatList of MessageList component, if you want * to attach some additional props to underlying FlatList, you can add it to following prop. @@ -278,7 +272,6 @@ const MessageListWithContext = < setTargetedMessage, StickyHeader, targetedMessage, - tDateTimeParser, thread, threadList = false, TypingIndicator, @@ -1025,18 +1018,6 @@ const MessageListWithContext = < threadList, ]); - const stickyHeaderDateFormat = - stickyHeaderDate?.getFullYear() === new Date().getFullYear() ? 'MMM D' : 'MMM D, YYYY'; - - const stickyHeaderDateString = useMemo(() => { - if (!stickyHeaderDate) return null; - return getDateString({ - date: stickyHeaderDate, - format: stickyHeaderDateFormat, - tDateTimeParser, - }); - }, [stickyHeaderDate, stickyHeaderDateFormat]); - const dismissImagePicker = () => { if (!hasMoved && selectedPicker) { setSelectedPicker(undefined); @@ -1092,13 +1073,6 @@ const MessageListWithContext = < [shouldApplyAndroidWorkaround, HeaderComponent], ); - const StickyHeaderComponent = () => { - if (!stickyHeaderDateString) return null; - if (StickyHeader) return ; - if (messageListLengthAfterUpdate) return ; - return null; - }; - // We need to omit the style related props from the additionalFlatListProps and add them directly instead of spreading let additionalFlatListPropsExcludingStyle: | Omit, 'style' | 'contentContainerStyle'> @@ -1183,7 +1157,13 @@ const MessageListWithContext = < {!loading && ( <> - + {StickyHeader && ( + + )} {!disableTypingIndicator && TypingIndicator && ( @@ -1253,7 +1233,6 @@ export const MessageList = < usePaginatedMessageListContext(); const { overlay } = useOverlayContext(); const { loadMoreThread, thread } = useThreadContext(); - const { t, tDateTimeParser } = useTranslationContext(); return ( = { /** Current [message object](https://getstream.io/chat/docs/#message_format) */ message: MessageType; + /** + * Additional styles for the system message container. + */ style?: StyleProp; + /* + * Lookup key in the language corresponding translations sheet to perform date formatting + */ + timestampTranslationKey?: string; }; /** @@ -27,7 +34,7 @@ export const MessageSystem = < >( props: MessageSystemProps, ) => { - const { message, style } = props; + const { message, style, timestampTranslationKey = 'timestamp/MessageSystem' } = props; const { theme: { @@ -37,13 +44,14 @@ export const MessageSystem = < }, }, } = useTheme(); - const { tDateTimeParser } = useTranslationContext(); + const { t, tDateTimeParser } = useTranslationContext(); const createdAt = message.created_at; const formattedDate = getDateString({ - calendar: true, date: createdAt, + t, tDateTimeParser, + timestampTranslationKey, }); return ( diff --git a/package/src/components/MessageList/StickyHeader.tsx b/package/src/components/MessageList/StickyHeader.tsx new file mode 100644 index 0000000000..fe4b36a938 --- /dev/null +++ b/package/src/components/MessageList/StickyHeader.tsx @@ -0,0 +1,57 @@ +import React, { useMemo } from 'react'; + +import { MessagesContextValue } from '../../contexts/messagesContext/MessagesContext'; +import { useTranslationContext } from '../../contexts/translationContext/TranslationContext'; + +import { DefaultStreamChatGenerics } from '../../types/types'; +import { getDateString } from '../../utils/getDateString'; + +/** + * Props for the StickyHeader component. + */ +export type StickyHeaderProps< + StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, +> = Pick, 'DateHeader'> & { + /** + * Date to be displayed in the sticky header. + */ + date?: Date; + /** + * The formatted date string to be displayed in the sticky header. + */ + dateString?: string | number; + /** + * The length of the message list after the update. + */ + messageListLengthAfterUpdate?: number; + /* + * Lookup key in the language corresponding translations sheet to perform date formatting + */ + timestampTranslationKey?: string; +}; + +export const StickyHeader = ({ + date, + DateHeader, + dateString, + messageListLengthAfterUpdate, + timestampTranslationKey = 'timestamp/StickyHeader', +}: StickyHeaderProps) => { + const { t, tDateTimeParser } = useTranslationContext(); + + const stickyHeaderDateString = useMemo(() => { + if (!date) return null; + if (dateString) return dateString; + + return getDateString({ + date, + t, + tDateTimeParser, + timestampTranslationKey, + }); + }, [date]); + + if (!stickyHeaderDateString) return null; + if (messageListLengthAfterUpdate) return ; + return null; +}; diff --git a/package/src/components/index.ts b/package/src/components/index.ts index eb3e342f27..3a43e98a15 100644 --- a/package/src/components/index.ts +++ b/package/src/components/index.ts @@ -108,6 +108,7 @@ export * from './Message/MessageSimple/MessageRepliesAvatars'; export * from './Message/MessageSimple/MessageSimple'; export * from './Message/MessageSimple/MessageStatus'; export * from './Message/MessageSimple/MessageTextContainer'; +export * from './Message/MessageSimple/MessageTimestamp'; export * from './Message/MessageSimple/ReactionList'; export * from './Message/MessageSimple/utils/renderText'; export * from './Message/utils/messageActions'; diff --git a/package/src/contexts/channelContext/ChannelContext.tsx b/package/src/contexts/channelContext/ChannelContext.tsx index e317e3cc6d..6e276058aa 100644 --- a/package/src/contexts/channelContext/ChannelContext.tsx +++ b/package/src/contexts/channelContext/ChannelContext.tsx @@ -4,6 +4,7 @@ import type { Channel, ChannelState } from 'stream-chat'; import type { EmptyStateProps } from '../../components/Indicators/EmptyStateIndicator'; import type { LoadingProps } from '../../components/Indicators/LoadingIndicator'; +import { StickyHeaderProps } from '../../components/MessageList/StickyHeader'; import type { DefaultStreamChatGenerics, UnknownType } from '../../types/types'; import { DEFAULT_BASE_CONTEXT_VALUE } from '../utils/defaultBaseContextValue'; @@ -180,7 +181,7 @@ export type ChannelContextValue< * * **Default** [DateHeader](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/MessageList/DateHeader.tsx) */ - StickyHeader?: React.ComponentType<{ dateString: string | number }>; + StickyHeader?: React.ComponentType; /** * Id of message, around which Channel/MessageList gets loaded when opened. * You will see a highlighted background for targetted message, when opened. diff --git a/package/src/contexts/messagesContext/MessagesContext.tsx b/package/src/contexts/messagesContext/MessagesContext.tsx index 3f5dae13b9..ed62a3c8e4 100644 --- a/package/src/contexts/messagesContext/MessagesContext.tsx +++ b/package/src/contexts/messagesContext/MessagesContext.tsx @@ -33,6 +33,7 @@ import type { MessageRepliesAvatarsProps } from '../../components/Message/Messag import type { MessageSimpleProps } from '../../components/Message/MessageSimple/MessageSimple'; import type { MessageStatusProps } from '../../components/Message/MessageSimple/MessageStatus'; import type { MessageTextProps } from '../../components/Message/MessageSimple/MessageTextContainer'; +import { MessageTimestampProps } from '../../components/Message/MessageSimple/MessageTimestamp'; import type { ReactionListProps } from '../../components/Message/MessageSimple/ReactionList'; import type { MarkdownRules } from '../../components/Message/MessageSimple/utils/renderText'; import type { MessageActionsParams } from '../../components/Message/utils/messageActions'; @@ -217,6 +218,11 @@ export type MessagesContextValue< * Defaults to: [MessageSystem](https://getstream.io/chat/docs/sdk/reactnative/ui-components/message-system/) */ MessageSystem: React.ComponentType>; + /** + * UI component for MessageTimestamp + * Defaults to: [MessageTimestamp](https://github.com/GetStream/stream-chat-react-native/blob/develop/package/src/components/Message/MessageSimple/MessageTimestamp.tsx) + */ + MessageTimestamp: React.ComponentType; /** * UI component for OverlayReactionList */ diff --git a/package/src/i18n/calendarFormats.ts b/package/src/i18n/calendarFormats.ts new file mode 100644 index 0000000000..74995e7d02 --- /dev/null +++ b/package/src/i18n/calendarFormats.ts @@ -0,0 +1,110 @@ +type CalendarFormats = { + lastDay: string; + lastWeek: string; + nextDay: string; + nextWeek: string; + sameDay: string; + sameElse: string; +}; + +/** + * Calendar formats for different languages. + */ +export const calendarFormats: Record = { + en: { + lastDay: '[Yesterday]', + lastWeek: 'dddd', + nextDay: '[Tomorrow]', + nextWeek: 'dddd [at] LT', + sameDay: '[Today]', + sameElse: 'L', + }, + es: { + lastDay: '[Ayer]', + lastWeek: 'dddd', + nextDay: '[Mañana]', + nextWeek: 'dddd [a las] LT', + sameDay: '[Hoy]', + sameElse: 'L', + }, + fr: { + lastDay: '[Hier]', + lastWeek: 'dddd', + nextDay: '[Demain]', + nextWeek: 'dddd [à] LT', + sameDay: "[Aujourd'hui]", + sameElse: 'L', + }, + he: { + lastDay: '[אתמול]', + lastWeek: 'dddd', + nextDay: '[מחר]', + nextWeek: 'dddd [בשעה] LT', + sameDay: '[היום]', + sameElse: 'L', + }, + hi: { + lastDay: '[कल]', + lastWeek: 'dddd', + nextDay: '[कल]', + nextWeek: 'dddd [को] LT', + sameDay: '[आज]', + sameElse: 'L', + }, + it: { + lastDay: '[Ieri]', + lastWeek: 'dddd', + nextDay: '[Domani]', + nextWeek: 'dddd [alle] LT', + sameDay: '[Oggi]', + sameElse: 'L', + }, + ja: { + lastDay: '[昨日]', + lastWeek: 'dddd', + nextDay: '[明日]', + nextWeek: 'dddd [の] LT', + sameDay: '[今日]', + sameElse: 'L', + }, + ko: { + lastDay: '[어제]', + lastWeek: 'dddd', + nextDay: '[내일]', + nextWeek: 'dddd [LT에]', + sameDay: '[오늘]', + sameElse: 'L', + }, + nl: { + lastDay: '[Gisteren]', + lastWeek: 'dddd', + nextDay: '[Morgen]', + nextWeek: 'dddd [om] LT', + sameDay: '[Vandaag]', + sameElse: 'L', + }, + 'pt-br': { + lastDay: '[Ontem]', + lastWeek: 'dddd', + nextDay: '[Amanhã]', + nextWeek: 'dddd [às] LT', + sameDay: '[Hoje]', + sameElse: 'L', + }, + ru: { + lastDay: '[Вчера]', + lastWeek: 'dddd', + nextDay: '[Завтра]', + nextWeek: 'dddd [в] LT', + sameDay: '[Сегодня]', + sameElse: 'L', // L is the localized date format + }, + tr: { + lastDay: '[Dün]', + lastWeek: 'dddd', + nextDay: '[Yarın]', + nextWeek: 'dddd [saat] LT', + sameDay: '[Bugün]', + sameElse: 'L', + }, +}; diff --git a/package/src/i18n/en.json b/package/src/i18n/en.json index c26caade32..6aaefbce43 100644 --- a/package/src/i18n/en.json +++ b/package/src/i18n/en.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Error loading channel list...", "Error loading messages for this channel...": "Error loading messages for this channel...", "Error while loading, please reload/refresh": "Error while loading, please reload/refresh", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "File is too large: {{ size }}, maximum upload size is {{ limit }}", + "File type not supported": "File type not supported", "Flag": "Flag", "Flag Message": "Flag Message", "Flag action failed either due to a network issue or the message is already flagged": "Flag action failed either due to a network issue or the message is already flagged.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "File is too large: {{ size }}, maximum upload size is {{ limit }}", - "File type not supported": "File type not supported", "Hold to start recording.": "Hold to start recording.", "How about sending your first message to a friend?": "How about sending your first message to a friend?", "Instant Commands": "Instant Commands", @@ -66,6 +66,13 @@ "Slow mode ON": "Slow mode ON", "The message has been reported to a moderator.": "The message has been reported to a moderator.", "Thread Reply": "Thread Reply", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Unblock User", "Unknown User": "Unknown User", "Unmute User": "Unmute User", diff --git a/package/src/i18n/es.json b/package/src/i18n/es.json index feea498cc7..d4f764e870 100644 --- a/package/src/i18n/es.json +++ b/package/src/i18n/es.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Error al cargar la lista de canales...", "Error loading messages for this channel...": "Error al cargar los mensajes de este canal...", "Error while loading, please reload/refresh": "Error al cargar, por favor recarga/actualiza", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "El archivo es demasiado grande: {{ size }}, el tamaño máximo de carga es de {{ limit }}", + "File type not supported": "Tipo de archivo no admitido", "Flag": "Reportar", "Flag Message": "Reportar mensaje", "Flag action failed either due to a network issue or the message is already flagged": "El reporte falló debido a un problema de red o el mensaje ya fue reportado.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "El archivo es demasiado grande: {{ size }}, el tamaño máximo de carga es de {{ limit }}", - "File type not supported": "Tipo de archivo no admitido", "Hold to start recording.": "Mantén presionado para comenzar a grabar.", "How about sending your first message to a friend?": "¿Qué tal enviar tu primer mensaje a un amigo?", "Instant Commands": "Comandos instantáneos", @@ -66,6 +66,13 @@ "Slow mode ON": "Modo lento ACTIVADO", "The message has been reported to a moderator.": "El mensaje ha sido reportado a un moderador.", "Thread Reply": "Respuesta de hilo", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Desbloquear usuario", "Unknown User": "Usuario desconocido", "Unmute User": "Activar sonido del usuario", diff --git a/package/src/i18n/fr.json b/package/src/i18n/fr.json index 5030980d02..6a13b963a1 100644 --- a/package/src/i18n/fr.json +++ b/package/src/i18n/fr.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Erreur lors du chargement de la liste de canaux...", "Error loading messages for this channel...": "Erreur lors du chargement des messages de ce canal...", "Error while loading, please reload/refresh": "Erreur lors du chargement, veuillez recharger/rafraîchir", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Le fichier est trop volumineux : {{ size }}, la taille de téléchargement maximale est de {{ limit }}", + "File type not supported": "Le type de fichier n'est pas pris en charge", "Flag": "Signaler", "Flag Message": "Signaler le message", "Flag action failed either due to a network issue or the message is already flagged": "L'action de signalisation a échoué en raison d'un problème de réseau ou le message est déjà signalé.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Le fichier est trop volumineux : {{ size }}, la taille de téléchargement maximale est de {{ limit }}", - "File type not supported": "Le type de fichier n'est pas pris en charge", "Hold to start recording.": "Hold to start recording.", "How about sending your first message to a friend?": "Et si vous envoyiez votre premier message à un ami ?", "Instant Commands": "Commandes Instantanées", @@ -66,6 +66,13 @@ "Slow mode ON": "Mode lent activé", "The message has been reported to a moderator.": "Le message a été signalé à un modérateur.", "Thread Reply": "Réponse à la discussion", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Débloquer Utilisateur", "Unknown User": "Utilisateur inconnu", "Unmute User": "Activer le son de Utilisateur", diff --git a/package/src/i18n/he.json b/package/src/i18n/he.json index 75df209d31..cb91f73efe 100644 --- a/package/src/i18n/he.json +++ b/package/src/i18n/he.json @@ -24,11 +24,11 @@ "Error loading channel list...": "שגיאה ארעה בטעינת השיחות...", "Error loading messages for this channel...": "שגיאה ארעה בטעינת הודעות עבור שיחה זאת...", "Error while loading, please reload/refresh": "שגיאה ארעה בזמן הטעינה, אנא טען מחדש/רענן", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "הקובץ גדול מדי: {{ size }}, גודל העלאה מקסימלי הוא {{ limit }}", + "File type not supported": "סוג הקובץ אינו נתמך", "Flag": "סמן", "Flag Message": "סמן הודעה", "Flag action failed either due to a network issue or the message is already flagged": "פעולת הסימון נכשלה בגלל בעיית רשת או שההודעה כבר סומנה.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "הקובץ גדול מדי: {{ size }}, גודל העלאה מקסימלי הוא {{ limit }}", - "File type not supported": "סוג הקובץ אינו נתמך", "Hold to start recording.": "לחץ והחזק כדי להתחיל להקליט.", "How about sending your first message to a friend?": "מה דעתך לשלוח את ההודעה הראשונה שלך לחבר?", "Instant Commands": "פעולות מיידיות", @@ -66,6 +66,13 @@ "Slow mode ON": "מצב איטי מופעל", "The message has been reported to a moderator.": "ההודעה דווחה למנהל", "Thread Reply": "הגב/י בשרשור", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "בטל/י חסימת משתמש", "Unknown User": "משתמש לא ידוע", "Unmute User": "בטל/י השתקת משתמש", diff --git a/package/src/i18n/hi.json b/package/src/i18n/hi.json index 8beab108c4..2f7a986a84 100644 --- a/package/src/i18n/hi.json +++ b/package/src/i18n/hi.json @@ -24,11 +24,11 @@ "Error loading channel list...": "चैनल सूची लोड करने में त्रुटि...", "Error loading messages for this channel...": "इस चैनल के लिए मेसेजेस लोड करने में त्रुटि हुई...", "Error while loading, please reload/refresh": "एरर, रिफ्रेश करे", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "फ़ाइल बहुत बड़ी है: {{ size }}, अधिकतम अपलोड साइज़ {{ limit }} है", + "File type not supported": "फ़ाइल प्रकार समर्थित नहीं है", "Flag": "झंडा", "Flag Message": "झंडा संदेश", "Flag action failed either due to a network issue or the message is already flagged": "फ़्लैग कार्रवाई या तो नेटवर्क समस्या के कारण विफल हो गई या संदेश पहले से फ़्लैग किया गया है।", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "फ़ाइल बहुत बड़ी है: {{ size }}, अधिकतम अपलोड साइज़ {{ limit }} है", - "File type not supported": "फ़ाइल प्रकार समर्थित नहीं है", "Hold to start recording.": "रिकॉर्डिंग शुरू करने के लिए दबाएं।", "How about sending your first message to a friend?": "किसी मित्र को अपना पहला संदेश भेजने के बारे में क्या ख़याल है?", "Instant Commands": "त्वरित कमांड", @@ -66,6 +66,13 @@ "Slow mode ON": "स्लो मोड चालू", "The message has been reported to a moderator.": "संदेश एक मॉडरेटर को सूचित किया गया है।", "Thread Reply": "धागा जवाब", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "उपयोगकर्ता को अनब्लॉक करें", "Unknown User": "अज्ञात उपयोगकर्ता", "Unmute User": "उपयोगकर्ता को अनम्यूट करें", diff --git a/package/src/i18n/it.json b/package/src/i18n/it.json index 6f5399fa3c..4ef28a5e65 100644 --- a/package/src/i18n/it.json +++ b/package/src/i18n/it.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Errore durante il caricamento della lista dei canali...", "Error loading messages for this channel...": "Errore durante il caricamento dei messaggi per questo canale...", "Error while loading, please reload/refresh": "Errore durante il caricamento, per favore ricarica la pagina", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Il file è troppo grande: {{ size }}, la dimensione massima di caricamento è {{ limit }}", + "File type not supported": "Tipo di file non supportato", "Flag": "Contrassegna", "Flag Message": "Contrassegna Messaggio", "Flag action failed either due to a network issue or the message is already flagged": "L'azione di segnalazione non è riuscita a causa di un problema di rete o il messaggio è già segnalato.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Il file è troppo grande: {{ size }}, la dimensione massima di caricamento è {{ limit }}", - "File type not supported": "Tipo di file non supportato", "Hold to start recording.": "Tieni premuto per avviare la registrazione.", "How about sending your first message to a friend?": "Che ne dici di inviare il tuo primo messaggio ad un amico?", "Instant Commands": "Comandi Istantanei", @@ -66,6 +66,13 @@ "Slow mode ON": "Slowmode attiva", "The message has been reported to a moderator.": "Il messaggio è stato segnalato a un moderatore.", "Thread Reply": "Rispondi alla Discussione", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Sblocca utente", "Unknown User": "Utente sconosciuto", "Unmute User": "Riattiva utente", diff --git a/package/src/i18n/ja.json b/package/src/i18n/ja.json index 3c2ce9364c..598f1f0bf0 100644 --- a/package/src/i18n/ja.json +++ b/package/src/i18n/ja.json @@ -24,11 +24,11 @@ "Error loading channel list...": "チャネルリストの読み込み中にエラーが発生しました。。。", "Error loading messages for this channel...": "このチャネルのメッセージの読み込み中にエラーが発生しました。。。", "Error while loading, please reload/refresh": "ロード中にエラーが発生しました。更新してください", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "ファイルが大きすぎます:{{ size }}、最大アップロードサイズは{{ limit }}です", + "File type not supported": "サポートされていないファイルです", "Flag": "フラグ", "Flag Message": "メッセージをフラグする", "Flag action failed either due to a network issue or the message is already flagged": "ネットワーク接続に問題があるか、すでにフラグが設定されているため、フラグが失敗しました。", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "ファイルが大きすぎます:{{ size }}、最大アップロードサイズは{{ limit }}です", - "File type not supported": "サポートされていないファイルです", "Hold to start recording.": "録音を開始するには押し続けてください。", "How about sending your first message to a friend?": "初めてのメッセージを友達に送ってみてはいかがでしょうか?", "Instant Commands": "インスタントコマンド", @@ -66,6 +66,13 @@ "Slow mode ON": "スローモードオン", "The message has been reported to a moderator.": "メッセージはモデレーターに報告されました。", "Thread Reply": "スレッドの返信", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "ユーザーのブロックを解除する", "Unknown User": "不明なユーザー", "Unmute User": "ユーザーのミュートを解除する", diff --git a/package/src/i18n/ko.json b/package/src/i18n/ko.json index cf3e5bb894..362489bd79 100644 --- a/package/src/i18n/ko.json +++ b/package/src/i18n/ko.json @@ -24,11 +24,11 @@ "Error loading channel list...": "채널리스트 을로드하는 동안 오류가 발생했습니다...", "Error loading messages for this channel...": "이 채널의 메시지를로드하는 동안 오류가 발생했습니다...", "Error while loading, please reload/refresh": "로드하는 동안 오류가 발생했습니다. 다시로드하십시오", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "파일이 너무 큽니다: {{ size }}, 최대 업로드 크기는 {{ limit }}입니다", + "File type not supported": "지원하지 않는 파일입니다.", "Flag": "플래그", "Flag Message": "메시지를 플래그하기", "Flag action failed either due to a network issue or the message is already flagged": "네트워크 연결에 문제가 있거나 이미 플래그 되어서 플래그에 실패했습니다.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "파일이 너무 큽니다: {{ size }}, 최대 업로드 크기는 {{ limit }}입니다", - "File type not supported": "지원하지 않는 파일입니다.", "Hold to start recording.": "녹음을 시작하려면 눌러주세요.", "How about sending your first message to a friend?": "친구에게 첫 번째 메시지를 보내는 것은 어떻습니까?", "Instant Commands": "인스턴트 명령", @@ -66,6 +66,13 @@ "Slow mode ON": "슬로모드 켜짐", "The message has been reported to a moderator.": "메시지는 운영자에보고되었습니다.", "Thread Reply": "스레드 답장", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "사용자 차단 해제", "Unknown User": "알 수없는 사용자", "Unmute User": "사용자 음소거 해제", diff --git a/package/src/i18n/nl.json b/package/src/i18n/nl.json index 30690dacb9..edd58654a7 100644 --- a/package/src/i18n/nl.json +++ b/package/src/i18n/nl.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Probleem bij het laden van de kanalen...", "Error loading messages for this channel...": "Probleem bij het laden van de berichten in dit kanaal...", "Error while loading, please reload/refresh": "Probleem bij het laden, probeer opnieuw", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Bestand is te groot: {{ size }}, maximale uploadgrootte is {{ limit }}", + "File type not supported": "Bestandstype niet ondersteund", "Flag": "Markeer", "Flag Message": "Markeer bericht", "Flag action failed either due to a network issue or the message is already flagged": "Rapporteren mislukt door een netwerk fout of het berich is al gerapporteerd", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Bestand is te groot: {{ size }}, maximale uploadgrootte is {{ limit }}", - "File type not supported": "Bestandstype niet ondersteund", "Hold to start recording.": "Houd vast om opname te starten.", "How about sending your first message to a friend?": "Wat dacht je ervan om je eerste bericht naar een vriend te sturen?", "Instant Commands": "Directe Opdrachten", @@ -66,6 +66,13 @@ "Slow mode ON": "Langzame modus aan", "The message has been reported to a moderator.": "Het bericht is gerapporteerd aan een moderator.", "Thread Reply": "Discussie beantwoorden", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Deblokkeer gebruiker", "Unknown User": "Onbekende gebruiker", "Unmute User": "Dempen van gebruiker opheffen", diff --git a/package/src/i18n/pt-BR.json b/package/src/i18n/pt-BR.json index 83ea8215cd..6ecba7ff8f 100644 --- a/package/src/i18n/pt-BR.json +++ b/package/src/i18n/pt-BR.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Erro ao carregar lista de canais...", "Error loading messages for this channel...": "Erro ao carregar mensagens para este canal...", "Error while loading, please reload/refresh": "Erro ao carregar, por favor recarregue/atualize", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "O arquivo é muito grande: {{ size }}, o tamanho máximo de upload é {{ limit }}", + "File type not supported": "Tipo de arquivo não suportado", "Flag": "Reportar", "Flag Message": "Reportar Mensagem", "Flag action failed either due to a network issue or the message is already flagged": "A ação para reportar a mensagem falhou devido a um problema de rede ou a mensagem já foi reportada.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "O arquivo é muito grande: {{ size }}, o tamanho máximo de upload é {{ limit }}", - "File type not supported": "Tipo de arquivo não suportado", "Hold to start recording.": "Mantenha pressionado para começar a gravar.", "How about sending your first message to a friend?": "Que tal enviar sua primeira mensagem para um amigo?", "Instant Commands": "Comandos Instantâneos", @@ -66,6 +66,13 @@ "Slow mode ON": "Modo Lento ATIVADO", "The message has been reported to a moderator.": "A mensagem foi relatada a um moderador.", "Thread Reply": "Respostas de Tópico", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Desbloquear Usuário", "Unknown User": "Usuário Desconhecido", "Unmute User": "Remover usuário do modo silencioso", diff --git a/package/src/i18n/ru.json b/package/src/i18n/ru.json index dea08ec299..481013cab8 100644 --- a/package/src/i18n/ru.json +++ b/package/src/i18n/ru.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Ошибка загрузки списка каналов...", "Error loading messages for this channel...": "Ошибка загрузки сообщений для этого канала...", "Error while loading, please reload/refresh": "Ошибка загрузки, пожалуйста перезагрузите или обновите", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Файл слишком большой: {{ size }}, максимальный размер загрузки составляет {{ limit }}", + "File type not supported": "Тип файла не поддерживается", "Flag": "Пометить", "Flag Message": "Пометить сообщение", "Flag action failed either due to a network issue or the message is already flagged": "Не удалось отправить жалобу. Возможные причины: проблема с подключением к интернету или ваша жалоба уже была принята.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Файл слишком большой: {{ size }}, максимальный размер загрузки составляет {{ limit }}", - "File type not supported": "Тип файла не поддерживается", "Hold to start recording.": "Удерживайте, чтобы начать запись.", "How about sending your first message to a friend?": "Как насчет отправки первого сообщения другу?", "Instant Commands": "Мгновенные Команды", @@ -66,6 +66,13 @@ "Slow mode ON": "Медленный режим включен", "The message has been reported to a moderator.": "Сообщение отправлено модератору.", "Thread Reply": "Тема Ответить", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Разблокировать пользователя", "Unknown User": "Неизвестный пользователь", "Unmute User": "Включить микрофон", diff --git a/package/src/i18n/tr.json b/package/src/i18n/tr.json index aca6f73703..f3689a451d 100644 --- a/package/src/i18n/tr.json +++ b/package/src/i18n/tr.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Kanal listesi yüklenirken hata oluştu...", "Error loading messages for this channel...": "Bu kanal için mesajlar yüklenirken hata oluştu...", "Error while loading, please reload/refresh": "Yüklenirken hata oluştu, lütfen tekrar deneyiniz", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Dosya çok büyük: {{ size }}, maksimum yükleme boyutu {{ limit }}", + "File type not supported": "Dosya türü desteklenmiyor", "Flag": "Raporla", "Flag Message": "Mesajı Raporla", "Flag action failed either due to a network issue or the message is already flagged": "Mesajın daha önce raporlanmış olması veya bir ağ bağlantısı sorunu nedeniyle raporlama işlemi başarısız oldu.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Dosya çok büyük: {{ size }}, maksimum yükleme boyutu {{ limit }}", - "File type not supported": "Dosya türü desteklenmiyor", "Hold to start recording.": "Kayıt yapmak için basılı tutun.", "How about sending your first message to a friend?": "İlk mesajınızı bir arkadaşınıza göndermeye ne dersiniz?", "Instant Commands": "Anlık Komutlar", @@ -66,6 +66,13 @@ "Slow mode ON": "Yavaş Mod Açık", "The message has been reported to a moderator.": "Mesaj moderatöre bildirildi.", "Thread Reply": "Konu Yanıtı", + "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", "Unblock User": "Kullanıcının engelini kaldır", "Unknown User": "Bilinmeyen kullanıcı", "Unmute User": "Kullanıcının sesini aç", diff --git a/package/src/index.ts b/package/src/index.ts index 2a302bc343..a22e001350 100644 --- a/package/src/index.ts +++ b/package/src/index.ts @@ -1,3 +1,6 @@ +/** i18next polyfill to handle intl format for pluralization. For more info see https://www.i18next.com/misc/json-format#i-18-next-json-v4 */ +import 'intl-pluralrules'; + export * from './components'; export * from './hooks'; export { registerNativeHandlers, NetInfo, iOS14RefreshGallerySelection } from './native'; diff --git a/package/src/utils/Streami18n.ts b/package/src/utils/Streami18n.ts index 5a78fefec4..551429b01c 100644 --- a/package/src/utils/Streami18n.ts +++ b/package/src/utils/Streami18n.ts @@ -8,7 +8,14 @@ import i18n, { FallbackLng, TFunction } from 'i18next'; import type moment from 'moment'; +import { + CustomFormatters, + PredefinedFormatters, + predefinedFormatters, +} from './predefinedFormatters'; + import type { TDateTimeParser } from '../contexts/translationContext/TranslationContext'; +import { calendarFormats } from '../i18n/calendarFormats'; import enTranslations from '../i18n/en.json'; import esTranslations from '../i18n/es.json'; import frTranslations from '../i18n/fr.json'; @@ -49,6 +56,7 @@ const defaultLng = 'en'; Dayjs.extend(updateLocale); Dayjs.updateLocale('en', { + calendar: calendarFormats.en, format: { L: 'DD/MM/YYYY', LL: 'D MMMM YYYY', @@ -59,37 +67,18 @@ Dayjs.updateLocale('en', { }, }); -Dayjs.updateLocale('nl', { - calendar: { - lastDay: '[gisteren om] LT', - lastWeek: '[afgelopen] dddd [om] LT', - nextDay: '[morgen om] LT', - nextWeek: 'dddd [om] LT', - sameDay: '[vandaag om] LT', - sameElse: 'L', - }, +Dayjs.updateLocale('es', { + calendar: calendarFormats.es, }); - -Dayjs.updateLocale('it', { - calendar: { - lastDay: '[Ieri alle] LT', - lastWeek: '[lo scorso] dddd [alle] LT', - nextDay: '[Domani alle] LT', - nextWeek: 'dddd [alle] LT', - sameDay: '[Oggi alle] LT', - sameElse: 'L', - }, +Dayjs.updateLocale('fr', { + calendar: calendarFormats.fr, +}); +Dayjs.updateLocale('he', { + calendar: calendarFormats.he, }); Dayjs.updateLocale('hi', { - calendar: { - lastDay: '[कल] LT', - lastWeek: '[पिछले] dddd, LT', - nextDay: '[कल] LT', - nextWeek: 'dddd, LT', - sameDay: '[आज] LT', - sameElse: 'L', - }, + calendar: calendarFormats.hi, /** * Hindi notation for meridiems are quite fuzzy in practice. While there exists @@ -116,35 +105,26 @@ Dayjs.updateLocale('hi', { meridiemParse: /रात|सुबह|दोपहर|शाम/, }); - -Dayjs.updateLocale('fr', { - calendar: { - lastDay: '[Hier à] LT', - lastWeek: 'dddd [dernier à] LT', - nextDay: '[Demain à] LT', - nextWeek: 'dddd [à] LT', - sameDay: '[Aujourd’hui à] LT', - sameElse: 'L', - }, +Dayjs.updateLocale('it', { + calendar: calendarFormats.it, }); - -Dayjs.updateLocale('tr', { - calendar: { - lastDay: '[dün] LT', - lastWeek: '[geçen] dddd [saat] LT', - nextDay: '[yarın saat] LT', - nextWeek: '[gelecek] dddd [saat] LT', - sameDay: '[bugün saat] LT', - sameElse: 'L', - }, +Dayjs.updateLocale('ja', { + calendar: calendarFormats.ja, +}); +Dayjs.updateLocale('ko', { + calendar: calendarFormats.ko, +}); +Dayjs.updateLocale('nl', { + calendar: calendarFormats.nl, +}); +Dayjs.updateLocale('pt-br', { + calendar: calendarFormats['pt-br'], }); - Dayjs.updateLocale('ru', { - calendar: { - lastDay: '[Вчера, в] LT', - nextDay: '[Завтра, в] LT', - sameDay: '[Сегодня, в] LT', - }, + calendar: calendarFormats.ru, +}); +Dayjs.updateLocale('tr', { + calendar: calendarFormats.tr, }); const en_locale = { @@ -171,11 +151,12 @@ const en_locale = { const isDayJs = (dateTimeParser: typeof Dayjs | typeof moment): dateTimeParser is typeof Dayjs => (dateTimeParser as typeof Dayjs).extend !== undefined; -type Options = { +type Streami18nOptions = { DateTimeParser?: typeof Dayjs | typeof moment; dayjsLocaleConfigForLanguage?: Partial; debug?: boolean; disableDateTimeTranslations?: boolean; + formatters?: Partial & CustomFormatters; language?: string; logger?: (msg?: string) => void; translationsForLanguage?: Partial; @@ -405,6 +386,7 @@ export class Streami18n { logger: (msg?: string) => void; currentLanguage: string; DateTimeParser: typeof Dayjs | typeof moment; + formatters: PredefinedFormatters & CustomFormatters = predefinedFormatters; isCustomDateTimeParser: boolean; i18nextConfig: I18NextConfig; @@ -434,7 +416,7 @@ export class Streami18n { * * @param {*} options */ - constructor(options: Options = {}, i18nextConfig: Partial = {}) { + constructor(options: Streami18nOptions = {}, i18nextConfig: Partial = {}) { const finalOptions = { ...defaultStreami18nOptions, ...options, @@ -445,6 +427,7 @@ export class Streami18n { this.currentLanguage = finalOptions.language; this.DateTimeParser = finalOptions.DateTimeParser; + this.formatters = { ...predefinedFormatters, ...options?.formatters }; try { /** @@ -556,6 +539,12 @@ export class Streami18n { this.onTFunctionOverrideListeners.forEach((listener) => listener(this.t)); } this.initialized = true; + if (this.formatters) { + Object.entries(this.formatters).forEach(([name, formatterFactory]) => { + if (!formatterFactory) return; + this.i18nInstance.services.formatter?.add(name, formatterFactory(this)); + }); + } } catch (error) { this.logger(`Something went wrong with init: ${JSON.stringify(error)}`); } diff --git a/package/src/utils/getDateString.ts b/package/src/utils/getDateString.ts index 04966f8d7f..96a7183da3 100644 --- a/package/src/utils/getDateString.ts +++ b/package/src/utils/getDateString.ts @@ -1,58 +1,65 @@ +import type { TimestampFormatterOptions } from './predefinedFormatters'; + import { isDayOrMoment, - TDateTimeParser, - TDateTimeParserInput, + TranslatorFunctions, } from '../contexts/translationContext/TranslationContext'; -interface DateFormatterOptions { - /** - * Whether to show the time in Calendar time format. Calendar time displays time relative to a today's date. - */ - calendar?: boolean; - /** - * The timestamp to be formatted. - */ - date?: string | Date; - /** - * The format in which the date should be displayed. - */ - format?: string; - /** - * A function to format the date. - */ - formatDate?: (date: TDateTimeParserInput) => string; - /** - * The datetime parsing function. - */ - tDateTimeParser?: TDateTimeParser; -} +type DateFormatterOptions = TimestampFormatterOptions & + Partial & { + /** + * The timestamp to be formatted. + */ + date?: string | Date; + /* + * Lookup key in the language corresponding translations sheet to perform date formatting + */ + timestampTranslationKey?: string; + }; export const noParsingFunctionWarning = 'MessageTimestamp was called but there is no datetime parsing function available'; /** - * Utility funcyion to format the date string. + * Utility function to format the date string. */ export function getDateString({ calendar, + calendarFormats, date, format, - formatDate, + t, tDateTimeParser, + timestampTranslationKey, }: DateFormatterOptions): string | number | undefined { if (!date || (typeof date === 'string' && !Date.parse(date))) { return; } - if (typeof formatDate === 'function') { - return formatDate(new Date(date)); - } - if (!tDateTimeParser) { console.log(noParsingFunctionWarning); return; } + if (t && timestampTranslationKey) { + const options: TimestampFormatterOptions = {}; + if (typeof calendar !== 'undefined' && calendar !== null) { + options.calendar = calendar; + } + if (typeof calendarFormats !== 'undefined' && calendarFormats !== null) { + options.calendarFormats = calendarFormats; + } + if (typeof format !== 'undefined' && format !== null) { + options.format = format; + } + const translatedTimestamp = t(timestampTranslationKey, { + ...options, + timestamp: new Date(date), + }); + const translationKeyFound = timestampTranslationKey !== translatedTimestamp; + if (translationKeyFound) return translatedTimestamp; + } + const parsedTime = tDateTimeParser(date); if (isDayOrMoment(parsedTime)) { @@ -60,7 +67,9 @@ export function getDateString({ * parsedTime.calendar is guaranteed on the type but is only * available when a user calls dayjs.extend(calendar) */ - return calendar && parsedTime.calendar ? parsedTime.calendar() : parsedTime.format(format); + return calendar && parsedTime.calendar + ? parsedTime.calendar(undefined, calendarFormats) + : parsedTime.format(format); } return new Date(date).toDateString(); diff --git a/package/src/utils/predefinedFormatters.ts b/package/src/utils/predefinedFormatters.ts new file mode 100644 index 0000000000..f48ebd71bc --- /dev/null +++ b/package/src/utils/predefinedFormatters.ts @@ -0,0 +1,59 @@ +import { getDateString } from './getDateString'; +import { Streami18n } from './Streami18n'; + +import { calendarFormats as calendarFormatsDefault } from '../i18n/calendarFormats'; + +export type TimestampFormatterOptions = { + /* If true, call the `Day.js` calendar function to get the date string to display (e.g. "Yesterday at 3:58 PM"). */ + calendar?: boolean | null; + /* Object specifying date display formats for dates formatted with calendar extension. Active only if calendar prop enabled. */ + calendarFormats?: Record; + /* Overrides the default timestamp format if calendar is disabled. */ + format?: string; +}; + +export type FormatterFactory = ( + streamI18n: Streami18n, +) => (value: V, lng: string | undefined, options: Record) => string; + +// Here is any used, because we do not want to enforce any specific rules and +// want to leave the type declaration to the integrator +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +export type CustomFormatters = Record>; + +export type PredefinedFormatters = { + timestampFormatter: FormatterFactory; +}; + +export const predefinedFormatters: PredefinedFormatters = { + timestampFormatter: + (streamI18n) => + (value, _, { calendarFormats, ...options }: TimestampFormatterOptions) => { + let parsedCalendarFormats; + try { + if (!options.calendar) { + parsedCalendarFormats = {}; + } else if (typeof calendarFormats === 'string') { + parsedCalendarFormats = JSON.parse(calendarFormats); + } else if (typeof calendarFormats === 'object') { + parsedCalendarFormats = calendarFormats; + } + } catch (e) { + console.error('[TIMESTAMP FORMATTER]', e); + } + + const result = getDateString({ + ...options, + calendarFormats: { + ...calendarFormatsDefault[streamI18n.currentLanguage || 'en'], + ...parsedCalendarFormats, + }, + date: value, + tDateTimeParser: streamI18n.tDateTimeParser, + }); + if (!result || typeof result === 'number') { + return JSON.stringify(value); + } + return result; + }, +}; diff --git a/package/yarn.lock b/package/yarn.lock index 320f74906e..4572bc0ce1 100644 --- a/package/yarn.lock +++ b/package/yarn.lock @@ -1781,6 +1781,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.17.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.20.0": version "7.24.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd" @@ -6473,13 +6480,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -i18next@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.2.4.tgz#972220f19dfef0075a70890d3e8b1f7cf64c5bd6" - integrity sha512-goE1LCA/IZOGG26PkkqoOl2KWR7YP606SvokVQZ29J6QwE02KycrzNetoMUJeqYrTxs4rmiiZgZp+q8qofQL6Q== - dependencies: - "@babel/runtime" "^7.12.0" - i18next@^19.8.3: version "19.9.2" resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.9.2.tgz#ea5a124416e3c5ab85fddca2c8e3c3669a8da397" @@ -6487,6 +6487,13 @@ i18next@^19.8.3: dependencies: "@babel/runtime" "^7.12.0" +i18next@^21.6.14: + version "21.10.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.10.0.tgz#85429af55fdca4858345d0e16b584ec29520197d" + integrity sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg== + dependencies: + "@babel/runtime" "^7.17.2" + ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -6604,6 +6611,11 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +intl-pluralrules@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/intl-pluralrules/-/intl-pluralrules-2.0.1.tgz#de16c3df1e09437635829725e88ea70c9ad79569" + integrity sha512-astxTLzIdXPeN0K9Rumi6LfMpm3rvNO0iJE+h/k8Kr/is+wPbRe4ikyDjlLr6VTh/mEfNv8RjN+gu3KwDiuhqg== + invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" From 0a9bbb88244613cd907eee50a3a468abcfa91839 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Thu, 13 Jun 2024 15:06:36 +0530 Subject: [PATCH 02/25] fix: build and lint issues --- .../Attachment/__tests__/Giphy.test.js | 2 +- .../ChannelPreview/ChannelPreviewStatus.tsx | 2 +- package/src/components/Chat/Chat.tsx | 2 +- .../components/Chat/__tests__/Chat.test.js | 2 +- .../components/ImageGalleryHeader.tsx | 2 +- .../MessageSimple/MessageTimestamp.tsx | 2 +- .../__tests__/MessageStatus.test.js | 2 +- .../MessageList/InlineDateSeparator.tsx | 2 +- .../components/MessageList/MessageSystem.tsx | 2 +- .../components/MessageList/StickyHeader.tsx | 2 +- .../__tests__/MessageSystem.test.js | 2 +- .../__tests__/ScrollToBottomButton.test.js | 2 +- .../__tests__/TypingIndicator.test.js | 2 +- .../Thread/__tests__/Thread.test.js | 2 +- .../overlayContext/OverlayContext.tsx | 2 +- package/src/hooks/useStreami18n.ts | 2 +- package/src/index.ts | 2 +- .../src/utils/__tests__/Streami18n.test.js | 2 +- package/src/utils/{ => i18n}/Streami18n.ts | 30 +++++++++---------- .../src/{ => utils}/i18n/calendarFormats.ts | 0 package/src/utils/{ => i18n}/getDateString.ts | 2 +- .../utils/{ => i18n}/predefinedFormatters.ts | 3 +- 22 files changed, 35 insertions(+), 36 deletions(-) rename package/src/utils/{ => i18n}/Streami18n.ts (96%) rename package/src/{ => utils}/i18n/calendarFormats.ts (100%) rename package/src/utils/{ => i18n}/getDateString.ts (97%) rename package/src/utils/{ => i18n}/predefinedFormatters.ts (96%) diff --git a/package/src/components/Attachment/__tests__/Giphy.test.js b/package/src/components/Attachment/__tests__/Giphy.test.js index 1b7681af4f..df2060d89f 100644 --- a/package/src/components/Attachment/__tests__/Giphy.test.js +++ b/package/src/components/Attachment/__tests__/Giphy.test.js @@ -23,7 +23,7 @@ import { generateMember } from '../../../mock-builders/generator/member'; import { generateMessage } from '../../../mock-builders/generator/message'; import { generateUser } from '../../../mock-builders/generator/user'; import { getTestClientWithUser } from '../../../mock-builders/mock'; -import { Streami18n } from '../../../utils/Streami18n'; +import { Streami18n } from '../../../utils/i18n/Streami18n'; import { ImageLoadingFailedIndicator } from '../../Attachment/ImageLoadingFailedIndicator'; import { ImageLoadingIndicator } from '../../Attachment/ImageLoadingIndicator'; import { Channel } from '../../Channel/Channel'; diff --git a/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx b/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx index 9a65763155..21b904ae2c 100644 --- a/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx +++ b/package/src/components/ChannelPreview/ChannelPreviewStatus.tsx @@ -10,7 +10,7 @@ import { useTranslationContext } from '../../contexts/translationContext/Transla import { Check, CheckAll } from '../../icons'; import type { DefaultStreamChatGenerics } from '../../types/types'; -import { getDateString } from '../../utils/getDateString'; +import { getDateString } from '../../utils/i18n/getDateString'; const styles = StyleSheet.create({ date: { diff --git a/package/src/components/Chat/Chat.tsx b/package/src/components/Chat/Chat.tsx index 8f35376dee..017bce93f0 100644 --- a/package/src/components/Chat/Chat.tsx +++ b/package/src/components/Chat/Chat.tsx @@ -27,8 +27,8 @@ import { SDK } from '../../native'; import { QuickSqliteClient } from '../../store/QuickSqliteClient'; import type { DefaultStreamChatGenerics } from '../../types/types'; import { DBSyncManager } from '../../utils/DBSyncManager'; +import type { Streami18n } from '../../utils/i18n/Streami18n'; import { StreamChatRN } from '../../utils/StreamChatRN'; -import type { Streami18n } from '../../utils/Streami18n'; import { version } from '../../version.json'; init(); diff --git a/package/src/components/Chat/__tests__/Chat.test.js b/package/src/components/Chat/__tests__/Chat.test.js index 2df56e57f4..07b7850f75 100644 --- a/package/src/components/Chat/__tests__/Chat.test.js +++ b/package/src/components/Chat/__tests__/Chat.test.js @@ -10,7 +10,7 @@ import { useTranslationContext } from '../../../contexts/translationContext/Tran import dispatchConnectionChangedEvent from '../../../mock-builders/event/connectionChanged'; import dispatchConnectionRecoveredEvent from '../../../mock-builders/event/connectionRecovered'; import { getTestClient } from '../../../mock-builders/mock'; -import { Streami18n } from '../../../utils/Streami18n'; +import { Streami18n } from '../../../utils/i18n/Streami18n'; import { Chat } from '../Chat'; const ChatContextConsumer = ({ fn }) => { diff --git a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx index 50123c4e4e..667ce65175 100644 --- a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +++ b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx @@ -8,7 +8,7 @@ import { useTranslationContext } from '../../../contexts/translationContext/Tran import { Close } from '../../../icons'; import type { DefaultStreamChatGenerics } from '../../../types/types'; -import { getDateString } from '../../../utils/getDateString'; +import { getDateString } from '../../../utils/i18n/getDateString'; import type { Photo } from '../ImageGallery'; const ReanimatedSafeAreaView = Animated.createAnimatedComponent diff --git a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx index 639b86dab3..585035891f 100644 --- a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx +++ b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx @@ -6,7 +6,7 @@ import { TranslationContextValue, useTranslationContext, } from '../../../contexts/translationContext/TranslationContext'; -import { getDateString } from '../../../utils/getDateString'; +import { getDateString } from '../../../utils/i18n/getDateString'; export type MessageTimestampProps = Partial> & { /** diff --git a/package/src/components/Message/MessageSimple/__tests__/MessageStatus.test.js b/package/src/components/Message/MessageSimple/__tests__/MessageStatus.test.js index 650d9de55e..9049de8d4f 100644 --- a/package/src/components/Message/MessageSimple/__tests__/MessageStatus.test.js +++ b/package/src/components/Message/MessageSimple/__tests__/MessageStatus.test.js @@ -5,7 +5,7 @@ import { cleanup, render, waitFor } from '@testing-library/react-native'; import { generateMessage } from '../../../../mock-builders/generator/message'; import { generateStaticUser, generateUser } from '../../../../mock-builders/generator/user'; import { getTestClientWithUser } from '../../../../mock-builders/mock'; -import { Streami18n } from '../../../../utils/Streami18n'; +import { Streami18n } from '../../../../utils/i18n/Streami18n'; import { Chat } from '../../../Chat/Chat'; import { MessageStatus } from '../MessageStatus'; diff --git a/package/src/components/MessageList/InlineDateSeparator.tsx b/package/src/components/MessageList/InlineDateSeparator.tsx index 1c90090318..a7f91e55b2 100644 --- a/package/src/components/MessageList/InlineDateSeparator.tsx +++ b/package/src/components/MessageList/InlineDateSeparator.tsx @@ -3,7 +3,7 @@ import { StyleSheet, Text, View } from 'react-native'; import { useTheme } from '../../contexts/themeContext/ThemeContext'; import { useTranslationContext } from '../../contexts/translationContext/TranslationContext'; -import { getDateString } from '../../utils/getDateString'; +import { getDateString } from '../../utils/i18n/getDateString'; const styles = StyleSheet.create({ container: { diff --git a/package/src/components/MessageList/MessageSystem.tsx b/package/src/components/MessageList/MessageSystem.tsx index a768eec22d..6f61cacdc7 100644 --- a/package/src/components/MessageList/MessageSystem.tsx +++ b/package/src/components/MessageList/MessageSystem.tsx @@ -7,7 +7,7 @@ import { useTheme } from '../../contexts/themeContext/ThemeContext'; import { useTranslationContext } from '../../contexts/translationContext/TranslationContext'; import type { DefaultStreamChatGenerics } from '../../types/types'; -import { getDateString } from '../../utils/getDateString'; +import { getDateString } from '../../utils/i18n/getDateString'; export type MessageSystemProps< StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics, diff --git a/package/src/components/MessageList/StickyHeader.tsx b/package/src/components/MessageList/StickyHeader.tsx index fe4b36a938..755c0a170d 100644 --- a/package/src/components/MessageList/StickyHeader.tsx +++ b/package/src/components/MessageList/StickyHeader.tsx @@ -4,7 +4,7 @@ import { MessagesContextValue } from '../../contexts/messagesContext/MessagesCon import { useTranslationContext } from '../../contexts/translationContext/TranslationContext'; import { DefaultStreamChatGenerics } from '../../types/types'; -import { getDateString } from '../../utils/getDateString'; +import { getDateString } from '../../utils/i18n/getDateString'; /** * Props for the StickyHeader component. diff --git a/package/src/components/MessageList/__tests__/MessageSystem.test.js b/package/src/components/MessageList/__tests__/MessageSystem.test.js index 1367142d28..f742e767eb 100644 --- a/package/src/components/MessageList/__tests__/MessageSystem.test.js +++ b/package/src/components/MessageList/__tests__/MessageSystem.test.js @@ -8,7 +8,7 @@ import { TranslationProvider } from '../../../contexts/translationContext/Transl import { generateMessage, generateStaticMessage } from '../../../mock-builders/generator/message'; import { generateStaticUser } from '../../../mock-builders/generator/user'; -import { Streami18n } from '../../../utils/Streami18n'; +import { Streami18n } from '../../../utils/i18n/Streami18n'; import { MessageSystem } from '../MessageSystem'; afterEach(cleanup); diff --git a/package/src/components/MessageList/__tests__/ScrollToBottomButton.test.js b/package/src/components/MessageList/__tests__/ScrollToBottomButton.test.js index 0a2d9fd9da..ad84ff3755 100644 --- a/package/src/components/MessageList/__tests__/ScrollToBottomButton.test.js +++ b/package/src/components/MessageList/__tests__/ScrollToBottomButton.test.js @@ -4,7 +4,7 @@ import { cleanup, fireEvent, render, waitFor } from '@testing-library/react-nati import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext'; import { TranslationProvider } from '../../../contexts/translationContext/TranslationContext'; -import { Streami18n } from '../../../utils/Streami18n'; +import { Streami18n } from '../../../utils/i18n/Streami18n'; import { ScrollToBottomButton } from '../ScrollToBottomButton'; afterEach(cleanup); diff --git a/package/src/components/MessageList/__tests__/TypingIndicator.test.js b/package/src/components/MessageList/__tests__/TypingIndicator.test.js index 3072c9d063..3afe6fbb94 100644 --- a/package/src/components/MessageList/__tests__/TypingIndicator.test.js +++ b/package/src/components/MessageList/__tests__/TypingIndicator.test.js @@ -7,7 +7,7 @@ import { TypingProvider } from '../../../contexts/typingContext/TypingContext'; import { generateStaticUser, generateUser } from '../../../mock-builders/generator/user'; import { getTestClientWithUser } from '../../../mock-builders/mock'; -import { Streami18n } from '../../../utils/Streami18n'; +import { Streami18n } from '../../../utils/i18n/Streami18n'; import { Chat } from '../../Chat/Chat'; import { TypingIndicator } from '../TypingIndicator'; diff --git a/package/src/components/Thread/__tests__/Thread.test.js b/package/src/components/Thread/__tests__/Thread.test.js index 1fef3a5519..edb8fedefe 100644 --- a/package/src/components/Thread/__tests__/Thread.test.js +++ b/package/src/components/Thread/__tests__/Thread.test.js @@ -15,7 +15,7 @@ import { generateMember } from '../../../mock-builders/generator/member'; import { generateMessage, generateStaticMessage } from '../../../mock-builders/generator/message'; import { generateStaticUser } from '../../../mock-builders/generator/user'; import { getTestClientWithUser } from '../../../mock-builders/mock'; -import { Streami18n } from '../../../utils/Streami18n'; +import { Streami18n } from '../../../utils/i18n/Streami18n'; import { Channel } from '../../Channel/Channel'; import { Chat } from '../../Chat/Chat'; import { Thread } from '../Thread'; diff --git a/package/src/contexts/overlayContext/OverlayContext.tsx b/package/src/contexts/overlayContext/OverlayContext.tsx index 7dfbd2d77b..56004f8281 100644 --- a/package/src/contexts/overlayContext/OverlayContext.tsx +++ b/package/src/contexts/overlayContext/OverlayContext.tsx @@ -8,7 +8,7 @@ import type { ImageGalleryCustomComponents } from '../../components/ImageGallery import type { MessageType } from '../../components/MessageList/hooks/useMessageList'; import type { DefaultStreamChatGenerics } from '../../types/types'; -import type { Streami18n } from '../../utils/Streami18n'; +import type { Streami18n } from '../../utils/i18n/Streami18n'; import type { AttachmentPickerContextValue } from '../attachmentPickerContext/AttachmentPickerContext'; import type { MessageOverlayContextValue } from '../messageOverlayContext/MessageOverlayContext'; import type { DeepPartial } from '../themeContext/ThemeContext'; diff --git a/package/src/hooks/useStreami18n.ts b/package/src/hooks/useStreami18n.ts index d123f930aa..46c0b1f809 100644 --- a/package/src/hooks/useStreami18n.ts +++ b/package/src/hooks/useStreami18n.ts @@ -5,7 +5,7 @@ import Dayjs from 'dayjs'; import { useIsMountedRef } from './useIsMountedRef'; import type { TranslatorFunctions } from '../contexts/translationContext/TranslationContext'; -import { Streami18n } from '../utils/Streami18n'; +import { Streami18n } from '../utils/i18n/Streami18n'; export const useStreami18n = (i18nInstance?: Streami18n) => { const [translators, setTranslators] = useState({ diff --git a/package/src/index.ts b/package/src/index.ts index a22e001350..24edca108c 100644 --- a/package/src/index.ts +++ b/package/src/index.ts @@ -12,7 +12,7 @@ export * from './icons'; export * from './types/types'; export * from './utils/patchMessageTextCommand'; -export * from './utils/Streami18n'; +export * from './utils/i18n/Streami18n'; export * from './utils/utils'; export * from './utils/StreamChatRN'; diff --git a/package/src/utils/__tests__/Streami18n.test.js b/package/src/utils/__tests__/Streami18n.test.js index b923ed10aa..7e2b26f927 100644 --- a/package/src/utils/__tests__/Streami18n.test.js +++ b/package/src/utils/__tests__/Streami18n.test.js @@ -4,7 +4,7 @@ import localeData from 'dayjs/plugin/localeData'; import frTranslations from '../../i18n/fr.json'; import nlTranslations from '../../i18n/nl.json'; -import { Streami18n } from '../Streami18n'; +import { Streami18n } from '../i18n/Streami18n'; Dayjs.extend(localeData); diff --git a/package/src/utils/Streami18n.ts b/package/src/utils/i18n/Streami18n.ts similarity index 96% rename from package/src/utils/Streami18n.ts rename to package/src/utils/i18n/Streami18n.ts index 551429b01c..a1a971906c 100644 --- a/package/src/utils/Streami18n.ts +++ b/package/src/utils/i18n/Streami18n.ts @@ -8,26 +8,26 @@ import i18n, { FallbackLng, TFunction } from 'i18next'; import type moment from 'moment'; +import { calendarFormats } from './calendarFormats'; import { CustomFormatters, PredefinedFormatters, predefinedFormatters, } from './predefinedFormatters'; -import type { TDateTimeParser } from '../contexts/translationContext/TranslationContext'; -import { calendarFormats } from '../i18n/calendarFormats'; -import enTranslations from '../i18n/en.json'; -import esTranslations from '../i18n/es.json'; -import frTranslations from '../i18n/fr.json'; -import heTranslations from '../i18n/he.json'; -import hiTranslations from '../i18n/hi.json'; -import itTranslations from '../i18n/it.json'; -import jaTranslations from '../i18n/ja.json'; -import koTranslations from '../i18n/ko.json'; -import nlTranslations from '../i18n/nl.json'; -import ptBRTranslations from '../i18n/pt-BR.json'; -import ruTranslations from '../i18n/ru.json'; -import trTranslations from '../i18n/tr.json'; +import type { TDateTimeParser } from '../../contexts/translationContext/TranslationContext'; +import enTranslations from '../../i18n/en.json'; +import esTranslations from '../../i18n/es.json'; +import frTranslations from '../../i18n/fr.json'; +import heTranslations from '../../i18n/he.json'; +import hiTranslations from '../../i18n/hi.json'; +import itTranslations from '../../i18n/it.json'; +import jaTranslations from '../../i18n/ja.json'; +import koTranslations from '../../i18n/ko.json'; +import nlTranslations from '../../i18n/nl.json'; +import ptBRTranslations from '../../i18n/pt-BR.json'; +import ruTranslations from '../../i18n/ru.json'; +import trTranslations from '../../i18n/tr.json'; import 'dayjs/locale/es'; import 'dayjs/locale/fr'; @@ -48,7 +48,7 @@ import 'dayjs/locale/tr'; */ import 'dayjs/locale/en'; -import type { DefaultStreamChatGenerics } from '../types/types'; +import type { DefaultStreamChatGenerics } from '../../types/types'; const defaultNS = 'translation'; const defaultLng = 'en'; diff --git a/package/src/i18n/calendarFormats.ts b/package/src/utils/i18n/calendarFormats.ts similarity index 100% rename from package/src/i18n/calendarFormats.ts rename to package/src/utils/i18n/calendarFormats.ts diff --git a/package/src/utils/getDateString.ts b/package/src/utils/i18n/getDateString.ts similarity index 97% rename from package/src/utils/getDateString.ts rename to package/src/utils/i18n/getDateString.ts index 96a7183da3..6b16e8f943 100644 --- a/package/src/utils/getDateString.ts +++ b/package/src/utils/i18n/getDateString.ts @@ -3,7 +3,7 @@ import type { TimestampFormatterOptions } from './predefinedFormatters'; import { isDayOrMoment, TranslatorFunctions, -} from '../contexts/translationContext/TranslationContext'; +} from '../../contexts/translationContext/TranslationContext'; type DateFormatterOptions = TimestampFormatterOptions & Partial & { diff --git a/package/src/utils/predefinedFormatters.ts b/package/src/utils/i18n/predefinedFormatters.ts similarity index 96% rename from package/src/utils/predefinedFormatters.ts rename to package/src/utils/i18n/predefinedFormatters.ts index f48ebd71bc..c0e0494da5 100644 --- a/package/src/utils/predefinedFormatters.ts +++ b/package/src/utils/i18n/predefinedFormatters.ts @@ -1,8 +1,7 @@ +import { calendarFormats as calendarFormatsDefault } from './calendarFormats'; import { getDateString } from './getDateString'; import { Streami18n } from './Streami18n'; -import { calendarFormats as calendarFormatsDefault } from '../i18n/calendarFormats'; - export type TimestampFormatterOptions = { /* If true, call the `Day.js` calendar function to get the date string to display (e.g. "Yesterday at 3:58 PM"). */ calendar?: boolean | null; From 9e3dc12ecd8947004609fb0c423fd01a80bf7627 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Thu, 13 Jun 2024 18:14:23 +0530 Subject: [PATCH 03/25] fix: StickyHeader code --- .../guides/date-time-formatting.mdx | 49 ++++++++++++++++--- .../src/components/MessageList/DateHeader.tsx | 2 +- .../components/MessageList/MessageList.tsx | 8 +-- .../components/MessageList/StickyHeader.tsx | 12 ++--- .../src/utils/i18n/predefinedFormatters.ts | 9 ++-- 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/docusaurus/docs/reactnative/guides/date-time-formatting.mdx b/docusaurus/docs/reactnative/guides/date-time-formatting.mdx index acc8b8288c..d9b2b11852 100644 --- a/docusaurus/docs/reactnative/guides/date-time-formatting.mdx +++ b/docusaurus/docs/reactnative/guides/date-time-formatting.mdx @@ -54,7 +54,7 @@ const CustomMessageTimestamp = (props: MessageTimestampProps) => ( Once the default prop values are nullified, we override the default formatting rules in the JSON translation value. We can take a look at an example: ```json -"timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", +"timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"lastDay: \"[gestern um] LT\", \"lastWeek\": \"[letzten] dddd [um] LT\", \"nextDay\": \"[morgen um] LT\", \"nextWeek\": \"dddd [um] LT\", \"sameDay\": \"[heute um] LT\", \"sameElse\": \"L\"}) }}", ``` or @@ -70,16 +70,53 @@ Let's dissect the example: - The `timestampFormatter` is the name of the formatting function that is used to convert the `timestamp` value into desired format - The `timestampFormatter` can be passed the same parameters as the React components (`calendar`, `calendarFormats`, `format`) as if the function was called with these values. -:::note -For `calendarFormats`, you don't have to provide all the formats. Provide only the formats you want to customize. -::: - -Params: +**Params**: - `calendar` - This is a boolean field to decide if the date format should be in calendar format or not. The default value is `false`. - `calendarFormats` - This is an object that contains the formats for the calendar. The default value is `{ sameDay: 'LT', nextDay: 'LT', nextWeek: 'dddd', lastDay: 'dddd', lastWeek: 'dddd', sameElse: 'L' }`. - `format` - This is a string that contains the format of the date. +If calendar formatting is enabled, the dates are formatted with time-relative words ("yesterday at ...", "last ..."). The calendar strings can be further customized with `calendarFormats` object. The `calendarFormats` object has to cover all the formatting cases as shows the example below: + +```js +{ + lastDay: '[gestern um] LT', + lastWeek: '[letzten] dddd [um] LT', + nextDay: '[morgen um] LT', + nextWeek: 'dddd [um] LT', + sameDay: '[heute um] LT', + sameElse: 'L', +} +``` + +:::important +If any of the `calendarFormats` keys are missing, then the underlying library will fall back to hard-coded english equivalents +::: + +If `calendar` formatting is enabled, the `format` prop would be ignored. So to apply the `format` string, the `calendar` has to be disabled. + :::note The described rules follow the formatting rules required by the i18n library used under the hood - `i18next`. You can learn more about the rules in [the formatting section of the `i18next` documentation](https://www.i18next.com/translation-function/formatting#basic-usage). ::: + +### Custom datetime formatter functions + +Besides overriding the configuration parameters, we can override the default `timestampFormatter` function by providing custom `Streami18n` instance: + +```tsx +import { Chat, Streami18n } from 'stream-chat-react-native'; + +const chatClient = 'Your Chat client here'; + +const i18n = new Streami18n({ + formatters: { + timestampFormatter: () => (val: string | Date) => { + return new Date(val).getTime() + ''; + }, + }, +}); + +export const ChatApp = ({ apiKey, userId, userToken }) => { + return ; +}; +``` diff --git a/package/src/components/MessageList/DateHeader.tsx b/package/src/components/MessageList/DateHeader.tsx index 52c8025765..3530f97ca7 100644 --- a/package/src/components/MessageList/DateHeader.tsx +++ b/package/src/components/MessageList/DateHeader.tsx @@ -21,7 +21,7 @@ const styles = StyleSheet.create({ }); export type DateHeaderProps = { - dateString: string | number; + dateString?: string | number; }; export const DateHeader = ({ dateString }: DateHeaderProps) => { diff --git a/package/src/components/MessageList/MessageList.tsx b/package/src/components/MessageList/MessageList.tsx index e3734bd19e..fa218def00 100644 --- a/package/src/components/MessageList/MessageList.tsx +++ b/package/src/components/MessageList/MessageList.tsx @@ -1157,12 +1157,8 @@ const MessageListWithContext = < {!loading && ( <> - {StickyHeader && ( - + {messageListLengthAfterUpdate && StickyHeader && ( + )} {!disableTypingIndicator && TypingIndicator && ( diff --git a/package/src/components/MessageList/StickyHeader.tsx b/package/src/components/MessageList/StickyHeader.tsx index 755c0a170d..2388ae4d4f 100644 --- a/package/src/components/MessageList/StickyHeader.tsx +++ b/package/src/components/MessageList/StickyHeader.tsx @@ -20,10 +20,6 @@ export type StickyHeaderProps< * The formatted date string to be displayed in the sticky header. */ dateString?: string | number; - /** - * The length of the message list after the update. - */ - messageListLengthAfterUpdate?: number; /* * Lookup key in the language corresponding translations sheet to perform date formatting */ @@ -34,13 +30,11 @@ export const StickyHeader = ({ date, DateHeader, dateString, - messageListLengthAfterUpdate, timestampTranslationKey = 'timestamp/StickyHeader', }: StickyHeaderProps) => { const { t, tDateTimeParser } = useTranslationContext(); const stickyHeaderDateString = useMemo(() => { - if (!date) return null; if (dateString) return dateString; return getDateString({ @@ -51,7 +45,7 @@ export const StickyHeader = ({ }); }, [date]); - if (!stickyHeaderDateString) return null; - if (messageListLengthAfterUpdate) return ; - return null; + if (!date) return; + + return ; }; diff --git a/package/src/utils/i18n/predefinedFormatters.ts b/package/src/utils/i18n/predefinedFormatters.ts index c0e0494da5..4da9b841dc 100644 --- a/package/src/utils/i18n/predefinedFormatters.ts +++ b/package/src/utils/i18n/predefinedFormatters.ts @@ -1,4 +1,3 @@ -import { calendarFormats as calendarFormatsDefault } from './calendarFormats'; import { getDateString } from './getDateString'; import { Streami18n } from './Streami18n'; @@ -6,7 +5,7 @@ export type TimestampFormatterOptions = { /* If true, call the `Day.js` calendar function to get the date string to display (e.g. "Yesterday at 3:58 PM"). */ calendar?: boolean | null; /* Object specifying date display formats for dates formatted with calendar extension. Active only if calendar prop enabled. */ - calendarFormats?: Record; + calendarFormats?: Record | string; /* Overrides the default timestamp format if calendar is disabled. */ format?: string; }; @@ -28,6 +27,7 @@ export const predefinedFormatters: PredefinedFormatters = { timestampFormatter: (streamI18n) => (value, _, { calendarFormats, ...options }: TimestampFormatterOptions) => { + console.log(calendarFormats); let parsedCalendarFormats; try { if (!options.calendar) { @@ -43,10 +43,7 @@ export const predefinedFormatters: PredefinedFormatters = { const result = getDateString({ ...options, - calendarFormats: { - ...calendarFormatsDefault[streamI18n.currentLanguage || 'en'], - ...parsedCalendarFormats, - }, + calendarFormats: parsedCalendarFormats, date: value, tDateTimeParser: streamI18n.tDateTimeParser, }); From 0aca0127b619597e143fdc191fc69427f2a43191 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 12:32:51 +0530 Subject: [PATCH 04/25] fix: broken translations for date time --- .../reactnative/guides/date-time-formatting.mdx | 17 ++++++++++++----- package/src/i18n/en.json | 14 +++++++------- package/src/i18n/es.json | 14 +++++++------- package/src/i18n/fr.json | 14 +++++++------- package/src/i18n/he.json | 14 +++++++------- package/src/i18n/hi.json | 14 +++++++------- package/src/i18n/it.json | 14 +++++++------- package/src/i18n/ja.json | 14 +++++++------- package/src/i18n/ko.json | 14 +++++++------- package/src/i18n/nl.json | 14 +++++++------- package/src/i18n/pt-BR.json | 14 +++++++------- package/src/i18n/ru.json | 14 +++++++------- package/src/i18n/tr.json | 14 +++++++------- package/src/utils/i18n/Streami18n.ts | 1 + package/src/utils/i18n/predefinedFormatters.ts | 14 +++++++++++--- 15 files changed, 108 insertions(+), 92 deletions(-) diff --git a/docusaurus/docs/reactnative/guides/date-time-formatting.mdx b/docusaurus/docs/reactnative/guides/date-time-formatting.mdx index d9b2b11852..073c1161f8 100644 --- a/docusaurus/docs/reactnative/guides/date-time-formatting.mdx +++ b/docusaurus/docs/reactnative/guides/date-time-formatting.mdx @@ -36,7 +36,7 @@ The default datetime formatting configuration is stored in the JSON translation We can apply custom configuration in all the translation JSON files. It could look similar to the following example key-value pair. ```json -"timestamp/SystemMessage": "{{ timestamp, timestampFormatter(format: YYYY) }}", +"timestamp/SystemMessage": "{{ timestamp | timestampFormatter(format: YYYY) }}", ``` Besides overriding the formatting parameters above, we can customize the translation key via `timestampTranslationKey` prop. All the above components (`ChannelPreviewStatus`, `ImageGalleryHeader`, `InlineDateSeparator`, `MessageEditedTimestamp`, `MessageSystem`, `MessageTimestamp`, `StickyHeader`) accept this prop. @@ -54,19 +54,26 @@ const CustomMessageTimestamp = (props: MessageTimestampProps) => ( Once the default prop values are nullified, we override the default formatting rules in the JSON translation value. We can take a look at an example: ```json -"timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"lastDay: \"[gestern um] LT\", \"lastWeek\": \"[letzten] dddd [um] LT\", \"nextDay\": \"[morgen um] LT\", \"nextWeek\": \"dddd [um] LT\", \"sameDay\": \"[heute um] LT\", \"sameElse\": \"L\"}) }}", +"timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", ``` -or +or with custom calendar formats: ```json -"timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", +"timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay: \"[gestern um] LT\", \"lastWeek\": \"[letzten] dddd [um] LT\", \"nextDay\": \"[morgen um] LT\", \"nextWeek\": \"dddd [um] LT\", \"sameDay\": \"[heute um] LT\", \"sameElse\": \"L\"}) }}", +``` + +or with custom format: + +```json +"timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", ``` Let's dissect the example: - The curly brackets (`{{`, `}}`) indicate the place where a value will be interpolated (inserted) into the string. -- Variable `timestamp` is the name of variable which value will be inserted into the string +- Variable `timestamp` is the name of variable which value will be inserted into the string. +- The `|` character is a pipe that separates the variable from the formatting function. - The `timestampFormatter` is the name of the formatting function that is used to convert the `timestamp` value into desired format - The `timestampFormatter` can be passed the same parameters as the React components (`calendar`, `calendarFormats`, `format`) as if the function was called with these values. diff --git a/package/src/i18n/en.json b/package/src/i18n/en.json index 6aaefbce43..c6a3a77562 100644 --- a/package/src/i18n/en.json +++ b/package/src/i18n/en.json @@ -66,13 +66,13 @@ "Slow mode ON": "Slow mode ON", "The message has been reported to a moderator.": "The message has been reported to a moderator.", "Thread Reply": "Thread Reply", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Yesterday]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[Tomorrow]\", \"nextWeek\":\"dddd [at] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Unblock User", "Unknown User": "Unknown User", "Unmute User": "Unmute User", diff --git a/package/src/i18n/es.json b/package/src/i18n/es.json index d4f764e870..63d1fc70ff 100644 --- a/package/src/i18n/es.json +++ b/package/src/i18n/es.json @@ -66,13 +66,13 @@ "Slow mode ON": "Modo lento ACTIVADO", "The message has been reported to a moderator.": "El mensaje ha sido reportado a un moderador.", "Thread Reply": "Respuesta de hilo", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Ayer]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[Mañana]\", \"nextWeek\":\"dddd [a las] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Desbloquear usuario", "Unknown User": "Usuario desconocido", "Unmute User": "Activar sonido del usuario", diff --git a/package/src/i18n/fr.json b/package/src/i18n/fr.json index 6a13b963a1..c036abe962 100644 --- a/package/src/i18n/fr.json +++ b/package/src/i18n/fr.json @@ -66,13 +66,13 @@ "Slow mode ON": "Mode lent activé", "The message has been reported to a moderator.": "Le message a été signalé à un modérateur.", "Thread Reply": "Réponse à la discussion", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Hier]\", \"lastWeek\":\"dddd\", \"nextDay\":\"[Demain]\", \"nextWeek\":\"dddd [à] LT\", \"sameDay\":\"LT\", \"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Débloquer Utilisateur", "Unknown User": "Utilisateur inconnu", "Unmute User": "Activer le son de Utilisateur", diff --git a/package/src/i18n/he.json b/package/src/i18n/he.json index cb91f73efe..fb60537769 100644 --- a/package/src/i18n/he.json +++ b/package/src/i18n/he.json @@ -66,13 +66,13 @@ "Slow mode ON": "מצב איטי מופעל", "The message has been reported to a moderator.": "ההודעה דווחה למנהל", "Thread Reply": "הגב/י בשרשור", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[אתמול]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[מחר]\",\"nextWeek\":\"dddd [בשעה] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "בטל/י חסימת משתמש", "Unknown User": "משתמש לא ידוע", "Unmute User": "בטל/י השתקת משתמש", diff --git a/package/src/i18n/hi.json b/package/src/i18n/hi.json index 2f7a986a84..171f2b5934 100644 --- a/package/src/i18n/hi.json +++ b/package/src/i18n/hi.json @@ -66,13 +66,13 @@ "Slow mode ON": "स्लो मोड चालू", "The message has been reported to a moderator.": "संदेश एक मॉडरेटर को सूचित किया गया है।", "Thread Reply": "धागा जवाब", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[कल]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[कल]\",\"nextWeek\":\"dddd [को] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "उपयोगकर्ता को अनब्लॉक करें", "Unknown User": "अज्ञात उपयोगकर्ता", "Unmute User": "उपयोगकर्ता को अनम्यूट करें", diff --git a/package/src/i18n/it.json b/package/src/i18n/it.json index 4ef28a5e65..a156bae365 100644 --- a/package/src/i18n/it.json +++ b/package/src/i18n/it.json @@ -66,13 +66,13 @@ "Slow mode ON": "Slowmode attiva", "The message has been reported to a moderator.": "Il messaggio è stato segnalato a un moderatore.", "Thread Reply": "Rispondi alla Discussione", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Ieri]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[Domani]\",\"nextWeek\":\"dddd [alle] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Sblocca utente", "Unknown User": "Utente sconosciuto", "Unmute User": "Riattiva utente", diff --git a/package/src/i18n/ja.json b/package/src/i18n/ja.json index 598f1f0bf0..c6dd915403 100644 --- a/package/src/i18n/ja.json +++ b/package/src/i18n/ja.json @@ -66,13 +66,13 @@ "Slow mode ON": "スローモードオン", "The message has been reported to a moderator.": "メッセージはモデレーターに報告されました。", "Thread Reply": "スレッドの返信", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[昨日]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[明日]\",\"nextWeek\":\"dddd [の] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "ユーザーのブロックを解除する", "Unknown User": "不明なユーザー", "Unmute User": "ユーザーのミュートを解除する", diff --git a/package/src/i18n/ko.json b/package/src/i18n/ko.json index 362489bd79..cdad551e7e 100644 --- a/package/src/i18n/ko.json +++ b/package/src/i18n/ko.json @@ -66,13 +66,13 @@ "Slow mode ON": "슬로모드 켜짐", "The message has been reported to a moderator.": "메시지는 운영자에보고되었습니다.", "Thread Reply": "스레드 답장", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[어제]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[내일]\",\"nextWeek\":\"dddd [LT에]\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "사용자 차단 해제", "Unknown User": "알 수없는 사용자", "Unmute User": "사용자 음소거 해제", diff --git a/package/src/i18n/nl.json b/package/src/i18n/nl.json index edd58654a7..093bac412c 100644 --- a/package/src/i18n/nl.json +++ b/package/src/i18n/nl.json @@ -66,13 +66,13 @@ "Slow mode ON": "Langzame modus aan", "The message has been reported to a moderator.": "Het bericht is gerapporteerd aan een moderator.", "Thread Reply": "Discussie beantwoorden", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Gisteren]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[Morgen]\",\"nextWeek\":\"dddd [om] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Deblokkeer gebruiker", "Unknown User": "Onbekende gebruiker", "Unmute User": "Dempen van gebruiker opheffen", diff --git a/package/src/i18n/pt-BR.json b/package/src/i18n/pt-BR.json index 6ecba7ff8f..1e25fde674 100644 --- a/package/src/i18n/pt-BR.json +++ b/package/src/i18n/pt-BR.json @@ -66,13 +66,13 @@ "Slow mode ON": "Modo Lento ATIVADO", "The message has been reported to a moderator.": "A mensagem foi relatada a um moderador.", "Thread Reply": "Respostas de Tópico", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Ontem]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[Amanhã]\",\"nextWeek\":\"dddd [às] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Desbloquear Usuário", "Unknown User": "Usuário Desconhecido", "Unmute User": "Remover usuário do modo silencioso", diff --git a/package/src/i18n/ru.json b/package/src/i18n/ru.json index 481013cab8..d562997c86 100644 --- a/package/src/i18n/ru.json +++ b/package/src/i18n/ru.json @@ -66,13 +66,13 @@ "Slow mode ON": "Медленный режим включен", "The message has been reported to a moderator.": "Сообщение отправлено модератору.", "Thread Reply": "Тема Ответить", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Вчера]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[Завтра]\",\"nextWeek\":\"dddd [в] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Разблокировать пользователя", "Unknown User": "Неизвестный пользователь", "Unmute User": "Включить микрофон", diff --git a/package/src/i18n/tr.json b/package/src/i18n/tr.json index f3689a451d..b31fca995a 100644 --- a/package/src/i18n/tr.json +++ b/package/src/i18n/tr.json @@ -66,13 +66,13 @@ "Slow mode ON": "Yavaş Mod Açık", "The message has been reported to a moderator.": "Mesaj moderatöre bildirildi.", "Thread Reply": "Konu Yanıtı", - "timestamp/ChannelPreviewStatus": "{{ timestamp, timestampFormatter(calendar: true; calendarFormats: {\"sameDay\": \"LT\"}) }}", - "timestamp/ImageGalleryHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/InlineDateSeparator": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageEditedTimestamp": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageSystem": "{{ timestamp, timestampFormatter(calendar: true) }}", - "timestamp/MessageTimestamp": "{{ timestamp, timestampFormatter(format: LT) }}", - "timestamp/StickyHeader": "{{ timestamp, timestampFormatter(calendar: true) }}", + "timestamp/ChannelPreviewStatus": "{{ timestamp | timestampFormatter(calendar: true; calendarFormats: {\"lastDay\":\"[Dün]\",\"lastWeek\":\"dddd\",\"nextDay\":\"[Yarın]\",\"nextWeek\":\"dddd [saat] LT\",\"sameDay\":\"LT\",\"sameElse\":\"L\"}) }}", + "timestamp/ImageGalleryHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/InlineDateSeparator": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageEditedTimestamp": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageSystem": "{{ timestamp | timestampFormatter(calendar: true) }}", + "timestamp/MessageTimestamp": "{{ timestamp | timestampFormatter(format: LT) }}", + "timestamp/StickyHeader": "{{ timestamp | timestampFormatter(calendar: true) }}", "Unblock User": "Kullanıcının engelini kaldır", "Unknown User": "Bilinmeyen kullanıcı", "Unmute User": "Kullanıcının sesini aç", diff --git a/package/src/utils/i18n/Streami18n.ts b/package/src/utils/i18n/Streami18n.ts index a1a971906c..87324045d8 100644 --- a/package/src/utils/i18n/Streami18n.ts +++ b/package/src/utils/i18n/Streami18n.ts @@ -529,6 +529,7 @@ export class Streami18n { try { this.t = await this.i18nInstance.init({ ...this.i18nextConfig, + interpolation: { escapeValue: false, formatSeparator: '|' }, lng: this.currentLanguage, resources: this.translations, }); diff --git a/package/src/utils/i18n/predefinedFormatters.ts b/package/src/utils/i18n/predefinedFormatters.ts index 4da9b841dc..3b1c3998ec 100644 --- a/package/src/utils/i18n/predefinedFormatters.ts +++ b/package/src/utils/i18n/predefinedFormatters.ts @@ -5,7 +5,7 @@ export type TimestampFormatterOptions = { /* If true, call the `Day.js` calendar function to get the date string to display (e.g. "Yesterday at 3:58 PM"). */ calendar?: boolean | null; /* Object specifying date display formats for dates formatted with calendar extension. Active only if calendar prop enabled. */ - calendarFormats?: Record | string; + calendarFormats?: Record; /* Overrides the default timestamp format if calendar is disabled. */ format?: string; }; @@ -26,8 +26,16 @@ export type PredefinedFormatters = { export const predefinedFormatters: PredefinedFormatters = { timestampFormatter: (streamI18n) => - (value, _, { calendarFormats, ...options }: TimestampFormatterOptions) => { - console.log(calendarFormats); + ( + value, + _, + { + calendarFormats, + ...options + }: Pick & { + calendarFormats?: Record | string; + }, + ) => { let parsedCalendarFormats; try { if (!options.calendar) { From 942849f69487457838b43ba2141147a4db6a909c Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 14:17:18 +0530 Subject: [PATCH 05/25] fix: broken translations for date time --- package/src/utils/i18n/Streami18n.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package/src/utils/i18n/Streami18n.ts b/package/src/utils/i18n/Streami18n.ts index 87324045d8..a5b26d4093 100644 --- a/package/src/utils/i18n/Streami18n.ts +++ b/package/src/utils/i18n/Streami18n.ts @@ -165,7 +165,7 @@ type Streami18nOptions = { type I18NextConfig = { debug: boolean; fallbackLng: false | FallbackLng; - interpolation: { escapeValue: boolean }; + interpolation: { escapeValue: boolean; formatSeparator: string }; keySeparator: false | string; lng: string; nsSeparator: false | string; @@ -474,7 +474,7 @@ export class Streami18n { this.i18nextConfig = { debug: finalOptions.debug, fallbackLng: false, - interpolation: { escapeValue: false }, + interpolation: { escapeValue: false, formatSeparator: '|' }, keySeparator: false, lng: this.currentLanguage, nsSeparator: false, @@ -529,7 +529,6 @@ export class Streami18n { try { this.t = await this.i18nInstance.init({ ...this.i18nextConfig, - interpolation: { escapeValue: false, formatSeparator: '|' }, lng: this.currentLanguage, resources: this.translations, }); From 5c9e47fe2c4a8226006e9dd9429caa39415473ab Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 14:27:30 +0530 Subject: [PATCH 06/25] fix: build issues --- package/src/components/MessageList/StickyHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/src/components/MessageList/StickyHeader.tsx b/package/src/components/MessageList/StickyHeader.tsx index 2388ae4d4f..0876f111b6 100644 --- a/package/src/components/MessageList/StickyHeader.tsx +++ b/package/src/components/MessageList/StickyHeader.tsx @@ -45,7 +45,7 @@ export const StickyHeader = ({ }); }, [date]); - if (!date) return; + if (!date) return null; return ; }; From a48156ac5578af96a15a93ae20059296bd9bd57b Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 15:34:51 +0530 Subject: [PATCH 07/25] fix: remove timestampTranslationKey prop --- .../ImageGallery/components/ImageGalleryHeader.tsx | 14 ++------------ .../components/MessageList/InlineDateSeparator.tsx | 11 ++--------- .../src/components/MessageList/MessageSystem.tsx | 5 ++--- .../src/components/MessageList/StickyHeader.tsx | 13 ++----------- 4 files changed, 8 insertions(+), 35 deletions(-) diff --git a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx index 667ce65175..16776d7561 100644 --- a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +++ b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx @@ -71,7 +71,6 @@ type Props; photo?: Photo; /* Lookup key in the language corresponding translations sheet to perform date formatting */ - timestampTranslationKey?: string; }; export const ImageGalleryHeader = < @@ -79,16 +78,7 @@ export const ImageGalleryHeader = < >( props: Props, ) => { - const { - centerElement, - CloseIcon, - leftElement, - opacity, - photo, - rightElement, - timestampTranslationKey = 'timestamp/ImageGalleryHeader', - visible, - } = props; + const { centerElement, CloseIcon, leftElement, opacity, photo, rightElement, visible } = props; const [height, setHeight] = useState(200); const { theme: { @@ -113,7 +103,7 @@ export const ImageGalleryHeader = < date: photo?.created_at, t, tDateTimeParser, - timestampTranslationKey, + timestampTranslationKey: 'timestamp/ImageGalleryHeader', }); const headerStyle = useAnimatedStyle(() => ({ diff --git a/package/src/components/MessageList/InlineDateSeparator.tsx b/package/src/components/MessageList/InlineDateSeparator.tsx index a7f91e55b2..a44543de75 100644 --- a/package/src/components/MessageList/InlineDateSeparator.tsx +++ b/package/src/components/MessageList/InlineDateSeparator.tsx @@ -30,16 +30,9 @@ export type InlineDateSeparatorProps = { * Date to be displayed. */ date?: Date; - /* - * Lookup key in the language corresponding translations sheet to perform date formatting - */ - timestampTranslationKey?: string; }; -export const InlineDateSeparator = ({ - date, - timestampTranslationKey = 'timestamp/InlineDateSeparator', -}: InlineDateSeparatorProps) => { +export const InlineDateSeparator = ({ date }: InlineDateSeparatorProps) => { const { theme: { colors: { overlay, white }, @@ -56,7 +49,7 @@ export const InlineDateSeparator = ({ date, t, tDateTimeParser, - timestampTranslationKey, + timestampTranslationKey: 'timestamp/InlineDateSeparator', }); return ( diff --git a/package/src/components/MessageList/MessageSystem.tsx b/package/src/components/MessageList/MessageSystem.tsx index 6f61cacdc7..82daf7ba13 100644 --- a/package/src/components/MessageList/MessageSystem.tsx +++ b/package/src/components/MessageList/MessageSystem.tsx @@ -21,7 +21,6 @@ export type MessageSystemProps< /* * Lookup key in the language corresponding translations sheet to perform date formatting */ - timestampTranslationKey?: string; }; /** @@ -34,7 +33,7 @@ export const MessageSystem = < >( props: MessageSystemProps, ) => { - const { message, style, timestampTranslationKey = 'timestamp/MessageSystem' } = props; + const { message, style } = props; const { theme: { @@ -51,7 +50,7 @@ export const MessageSystem = < date: createdAt, t, tDateTimeParser, - timestampTranslationKey, + timestampTranslationKey: 'timestamp/MessageSystem', }); return ( diff --git a/package/src/components/MessageList/StickyHeader.tsx b/package/src/components/MessageList/StickyHeader.tsx index 0876f111b6..472c6b709c 100644 --- a/package/src/components/MessageList/StickyHeader.tsx +++ b/package/src/components/MessageList/StickyHeader.tsx @@ -20,18 +20,9 @@ export type StickyHeaderProps< * The formatted date string to be displayed in the sticky header. */ dateString?: string | number; - /* - * Lookup key in the language corresponding translations sheet to perform date formatting - */ - timestampTranslationKey?: string; }; -export const StickyHeader = ({ - date, - DateHeader, - dateString, - timestampTranslationKey = 'timestamp/StickyHeader', -}: StickyHeaderProps) => { +export const StickyHeader = ({ date, DateHeader, dateString }: StickyHeaderProps) => { const { t, tDateTimeParser } = useTranslationContext(); const stickyHeaderDateString = useMemo(() => { @@ -41,7 +32,7 @@ export const StickyHeader = ({ date, t, tDateTimeParser, - timestampTranslationKey, + timestampTranslationKey: 'timestamp/StickyHeader', }); }, [date]); From eb90df346c5ee485f697e6e03255a77f8cf013c9 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 16:18:03 +0530 Subject: [PATCH 08/25] tests: fix broken tests --- .../__snapshots__/MessageSystem.test.js.snap | 2 +- .../__snapshots__/TypingIndicator.test.js.snap | 2 +- .../__tests__/__snapshots__/Thread.test.js.snap | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap b/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap index 54d72de778..186ee4f396 100644 --- a/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap +++ b/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap @@ -73,7 +73,7 @@ exports[`MessageSystem should match the snapshot for message system 1`] = ` ] } > - 04/27/2020 + 2020-04-27T13:39:49+00:00 - Arthur and 1 more are typing + {{ firstUser }} and {{ nonSelfUserLength }} more are typing `; diff --git a/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap b/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap index c1bac1bb85..34f5c1c98c 100644 --- a/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +++ b/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap @@ -488,7 +488,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2:50 PM + 2020-05-05T14:50:00+00:00 @@ -768,7 +768,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2:50 PM + 2020-05-05T14:50:00+00:00 @@ -1048,7 +1048,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2:50 PM + 2020-05-05T14:50:00+00:00 @@ -1092,7 +1092,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - May 5, 2020 + 2020-05-05T14:50:00+00:00 @@ -1368,7 +1368,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2:50 PM + 2020-05-05T14:50:00+00:00 @@ -1473,7 +1473,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - Replies + {{ replyCount }} Replies From a8ba201c0a5a0b21d28d243357846a07de4a063c Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 16:31:46 +0530 Subject: [PATCH 09/25] tests: fix broken tests --- .../__snapshots__/MessageSystem.test.js.snap | 2 +- .../__snapshots__/TypingIndicator.test.js.snap | 2 +- .../__tests__/__snapshots__/Thread.test.js.snap | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap b/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap index 186ee4f396..54d72de778 100644 --- a/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap +++ b/package/src/components/MessageList/__tests__/__snapshots__/MessageSystem.test.js.snap @@ -73,7 +73,7 @@ exports[`MessageSystem should match the snapshot for message system 1`] = ` ] } > - 2020-04-27T13:39:49+00:00 + 04/27/2020 - {{ firstUser }} and {{ nonSelfUserLength }} more are typing + Arthur and 1 more are typing `; diff --git a/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap b/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap index 34f5c1c98c..16e3adedd6 100644 --- a/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +++ b/package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap @@ -488,7 +488,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2020-05-05T14:50:00+00:00 + 2:50 PM @@ -768,7 +768,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2020-05-05T14:50:00+00:00 + 2:50 PM @@ -1048,7 +1048,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2020-05-05T14:50:00+00:00 + 2:50 PM @@ -1092,7 +1092,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2020-05-05T14:50:00+00:00 + 05/05/2020 @@ -1368,7 +1368,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - 2020-05-05T14:50:00+00:00 + 2:50 PM @@ -1473,7 +1473,7 @@ exports[`Thread should match thread snapshot 1`] = ` ] } > - {{ replyCount }} Replies + Replies From 85b2d8d0ac6bbc531b19d556869b26628c3e701d Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 21:47:57 +0530 Subject: [PATCH 10/25] fix: memoize the getDatestring logic --- .../components/ImageGalleryHeader.tsx | 18 +++++++------ .../MessageSimple/MessageTimestamp.tsx | 25 +++++++++++-------- .../MessageList/InlineDateSeparator.tsx | 22 ++++++++-------- .../components/MessageList/MessageSystem.tsx | 19 ++++++++------ package/src/utils/i18n/getDateString.ts | 3 +-- 5 files changed, 49 insertions(+), 38 deletions(-) diff --git a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx index 16776d7561..f83b1eacb8 100644 --- a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +++ b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { Pressable, SafeAreaView, StyleSheet, Text, View, ViewStyle } from 'react-native'; import Animated, { Extrapolate, interpolate, useAnimatedStyle } from 'react-native-reanimated'; @@ -99,12 +99,16 @@ export const ImageGalleryHeader = < const { t, tDateTimeParser } = useTranslationContext(); const { setOverlay } = useOverlayContext(); - const date = getDateString({ - date: photo?.created_at, - t, - tDateTimeParser, - timestampTranslationKey: 'timestamp/ImageGalleryHeader', - }); + const date = useMemo( + () => + getDateString({ + date: photo?.created_at, + t, + tDateTimeParser, + timestampTranslationKey: 'timestamp/ImageGalleryHeader', + }), + [photo?.created_at, t, tDateTimeParser], + ); const headerStyle = useAnimatedStyle(() => ({ opacity: opacity.value, diff --git a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx index 585035891f..0f59f6c2af 100644 --- a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx +++ b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { StyleSheet, Text } from 'react-native'; import { useTheme } from '../../../contexts/themeContext/ThemeContext'; @@ -30,6 +30,8 @@ export const MessageTimestamp = (props: MessageTimestampProps) => { timestamp, timestampTranslationKey = 'timestamp/MessageTimestamp', } = props; + const { t, tDateTimeParser: contextTDateTimeParser } = useTranslationContext(); + const tDateTimeParser = propsTDateTimeParser || contextTDateTimeParser; const { theme: { @@ -39,7 +41,17 @@ export const MessageTimestamp = (props: MessageTimestampProps) => { }, }, } = useTheme(); - const { t, tDateTimeParser: contextTDateTimeParser } = useTranslationContext(); + + const dateString = useMemo( + () => + getDateString({ + date: timestamp, + t, + tDateTimeParser, + timestampTranslationKey, + }), + [], + ); if (formattedDate) { return ( @@ -47,15 +59,6 @@ export const MessageTimestamp = (props: MessageTimestampProps) => { ); } - if (!timestamp) return null; - - const dateString = getDateString({ - date: timestamp, - t, - tDateTimeParser: propsTDateTimeParser || contextTDateTimeParser, - timestampTranslationKey, - }); - if (!dateString) return null; return {dateString.toString()}; diff --git a/package/src/components/MessageList/InlineDateSeparator.tsx b/package/src/components/MessageList/InlineDateSeparator.tsx index a44543de75..d1f1f63e34 100644 --- a/package/src/components/MessageList/InlineDateSeparator.tsx +++ b/package/src/components/MessageList/InlineDateSeparator.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { useTheme } from '../../contexts/themeContext/ThemeContext'; @@ -41,16 +41,16 @@ export const InlineDateSeparator = ({ date }: InlineDateSeparatorProps) => { } = useTheme(); const { t, tDateTimeParser } = useTranslationContext(); - if (!date) { - return null; - } - - const dateString = getDateString({ - date, - t, - tDateTimeParser, - timestampTranslationKey: 'timestamp/InlineDateSeparator', - }); + const dateString = useMemo( + () => + getDateString({ + date, + t, + tDateTimeParser, + timestampTranslationKey: 'timestamp/InlineDateSeparator', + }), + [date, t, tDateTimeParser], + ); return ( + getDateString({ + date: createdAt, + t, + tDateTimeParser, + timestampTranslationKey: 'timestamp/MessageSystem', + }), + [createdAt, t, tDateTimeParser], + ); return ( diff --git a/package/src/utils/i18n/getDateString.ts b/package/src/utils/i18n/getDateString.ts index 6b16e8f943..fc0bda2ed7 100644 --- a/package/src/utils/i18n/getDateString.ts +++ b/package/src/utils/i18n/getDateString.ts @@ -56,8 +56,7 @@ export function getDateString({ ...options, timestamp: new Date(date), }); - const translationKeyFound = timestampTranslationKey !== translatedTimestamp; - if (translationKeyFound) return translatedTimestamp; + return translatedTimestamp; } const parsedTime = tDateTimeParser(date); From cafd039f21478cec8999739cdcd4c4e188580783 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 21:48:07 +0530 Subject: [PATCH 11/25] fix: memoize the getDatestring logic --- .../src/components/Message/MessageSimple/MessageTimestamp.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx index 0f59f6c2af..79958a18bd 100644 --- a/package/src/components/Message/MessageSimple/MessageTimestamp.tsx +++ b/package/src/components/Message/MessageSimple/MessageTimestamp.tsx @@ -50,7 +50,7 @@ export const MessageTimestamp = (props: MessageTimestampProps) => { tDateTimeParser, timestampTranslationKey, }), - [], + [timestamp, t, tDateTimeParser, timestampTranslationKey], ); if (formattedDate) { From 559c993ac6f97c7a4fc3d7ffc9279728658f92c0 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 21:56:23 +0530 Subject: [PATCH 12/25] fix: memoize the getDatestring logic --- package/src/utils/i18n/getDateString.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/src/utils/i18n/getDateString.ts b/package/src/utils/i18n/getDateString.ts index fc0bda2ed7..6b16e8f943 100644 --- a/package/src/utils/i18n/getDateString.ts +++ b/package/src/utils/i18n/getDateString.ts @@ -56,7 +56,8 @@ export function getDateString({ ...options, timestamp: new Date(date), }); - return translatedTimestamp; + const translationKeyFound = timestampTranslationKey !== translatedTimestamp; + if (translationKeyFound) return translatedTimestamp; } const parsedTime = tDateTimeParser(date); From 33508c2ce2f17d259c3e94a34ebc078d49937588 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Fri, 14 Jun 2024 22:18:11 +0530 Subject: [PATCH 13/25] fix: translations test --- package/babel.i18next-extract.json | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/package/babel.i18next-extract.json b/package/babel.i18next-extract.json index ea86ed7c53..3320bda927 100644 --- a/package/babel.i18next-extract.json +++ b/package/babel.i18next-extract.json @@ -1,22 +1,4 @@ { "presets": ["@babel/env", "module:@react-native/babel-preset"], - "plugins": [ - [ - "i18next-extract", - { - "contextSeparator": "__", - "defaultContexts": [""], - "defaultNS": "en", - "locales": ["en", "es", "fr", "he", "hi", "it", "ja", "ko", "nl", "ru", "tr", "pt-BR"], - "jsonSpace": 4, - "keySeparator": null, - "nsSeparator": null, - "keyAsDefaultValue": ["en"], - "keyAsDefaultValueForDerivedKeys": false, - "outputPath": "src/i18n/{{locale}}.json", - "discardOldKeys": true - } - ], - "@babel/transform-runtime" - ] + "plugins": [["i18next-extract"], "@babel/transform-runtime"] } From b628b6eee8c3c30ce59375ed1a0dec0950a5a97f Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 10:27:21 +0530 Subject: [PATCH 14/25] fix: add tests --- .../__tests__/MessageSystem.test.js | 9 ++++++-- .../src/utils/__tests__/Streami18n.test.js | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/package/src/components/MessageList/__tests__/MessageSystem.test.js b/package/src/components/MessageList/__tests__/MessageSystem.test.js index f742e767eb..d20d48f2d6 100644 --- a/package/src/components/MessageList/__tests__/MessageSystem.test.js +++ b/package/src/components/MessageList/__tests__/MessageSystem.test.js @@ -13,9 +13,15 @@ import { MessageSystem } from '../MessageSystem'; afterEach(cleanup); +let i18nInstance; + describe('MessageSystem', () => { + beforeAll(() => { + i18nInstance = new Streami18n(); + }); + afterEach(cleanup); + it('should render the message system', async () => { - const i18nInstance = new Streami18n(); const translators = await i18nInstance.getTranslators(); const message = generateMessage(); const { queryByTestId } = render( @@ -32,7 +38,6 @@ describe('MessageSystem', () => { }); it('should match the snapshot for message system', async () => { - const i18nInstance = new Streami18n(); const translators = await i18nInstance.getTranslators(); const user = generateStaticUser(0); const message = generateStaticMessage('Hello World', { user }); diff --git a/package/src/utils/__tests__/Streami18n.test.js b/package/src/utils/__tests__/Streami18n.test.js index 7e2b26f927..9300f1d654 100644 --- a/package/src/utils/__tests__/Streami18n.test.js +++ b/package/src/utils/__tests__/Streami18n.test.js @@ -183,3 +183,25 @@ describe('setLanguage - switch to french', () => { } }); }); + +describe('formatters property', () => { + it('contains the default timestampFormatter', () => { + expect(new Streami18n().formatters.timestampFormatter).toBeDefined(); + }); + it('allows to override the default timestampFormatter', async () => { + const i18n = new Streami18n({ + formatters: { timestampFormatter: (s) => () => 'custom' }, + translationsForLanguage: { abc: '{{ value | timestampFormatter }}' }, + }); + await i18n.init(); + expect(i18n.t('abc')).toBe('custom'); + }); + it('allows to add new custom formatter', async () => { + const i18n = new Streami18n({ + formatters: { customFormatter: (s) => () => 'custom' }, + translationsForLanguage: { abc: '{{ value | customFormatter }}' }, + }); + await i18n.init(); + expect(i18n.t('abc')).toBe('custom'); + }); +}); From 167489b9418ed6ce6c98b8e4cbfc1d1c9bacfa23 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 11:54:19 +0530 Subject: [PATCH 15/25] fix: use i18n-parser for build-translations and improve related scripts --- .prettierrc | 15 +- package/.babelrc | 39 -- package/babel.config.js | 41 +- package/bin/validate-translations.js | 4 +- package/i18next-parser.config.js | 15 + package/package.json | 15 +- package/src/i18n/en.json | 4 +- package/src/i18n/es.json | 4 +- package/src/i18n/fr.json | 4 +- package/src/i18n/he.json | 4 +- package/src/i18n/hi.json | 4 +- package/src/i18n/it.json | 4 +- package/src/i18n/ja.json | 4 +- package/src/i18n/ko.json | 10 +- package/src/i18n/nl.json | 4 +- package/src/i18n/pt-BR.json | 4 +- package/src/i18n/ru.json | 4 +- package/src/i18n/tr.json | 4 +- package/yarn.lock | 739 +++++++++++++++++++++++++-- 19 files changed, 742 insertions(+), 180 deletions(-) delete mode 100644 package/.babelrc create mode 100644 package/i18next-parser.config.js diff --git a/.prettierrc b/.prettierrc index cbb3f3b95d..753a6e9d36 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,18 +4,5 @@ "printWidth": 100, "singleQuote": true, "tabWidth": 2, - "trailingComma": "all", - "overrides": [ - { - "files": ["*.md", "*.mdx"], - "options": { - "arrowParens": "avoid", - "jsxSingleQuote": true, - "printWidth": 120, - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "all" - } - } - ] + "trailingComma": "all" } diff --git a/package/.babelrc b/package/.babelrc deleted file mode 100644 index 9d4a3ca2b7..0000000000 --- a/package/.babelrc +++ /dev/null @@ -1,39 +0,0 @@ -{ - "env": { - "production": { - "presets": [ - [ - "@babel/env", - { - "modules": false - } - ] - ] - } - }, - "overrides": [ - { - "compact": false - } - ], - "plugins": [ - [ - "i18next-extract", - { - "contextSeparator": "__", - "defaultContexts": [""], - "defaultNS": "en", - "locales": ["en", "es", "fr", "he", "hi", "it", "ja", "ko", "nl", "ru", "tr", "pt-BR"], - "jsonSpace": 4, - "keySeparator": null, - "nsSeparator": null, - "keyAsDefaultValue": ["en"], - "keyAsDefaultValueForDerivedKeys": false, - "outputPath": "src/i18n/{{locale}}.json", - "discardOldKeys": true - } - ], - "module-resolver" - ], - "presets": ["@babel/env", "module:@react-native/babel-preset"] -} diff --git a/package/babel.config.js b/package/babel.config.js index 7ce72427ad..ddd62ec2cf 100644 --- a/package/babel.config.js +++ b/package/babel.config.js @@ -9,26 +9,7 @@ module.exports = (api) => { compact: false, }, ], - plugins: [ - [ - 'i18next-extract', - { - contextSeparator: '__', - defaultContexts: [''], - defaultNS: 'en', - discardOldKeys: true, - jsonSpace: 4, - keyAsDefaultValue: ['en'], - keyAsDefaultValueForDerivedKeys: false, - keySeparator: null, - locales: ['en', 'es', 'fr', 'he', 'hi', 'it', 'ja', 'ko', 'nl', 'ru', 'tr', 'pt-BR'], - nsSeparator: null, - outputPath: 'src/i18n/{{locale}}.json', - }, - ], - 'module-resolver', - 'react-native-reanimated/plugin', - ], + plugins: ['module-resolver', 'react-native-reanimated/plugin'], presets: ['@babel/env', 'module:@react-native/babel-preset', '@babel/preset-typescript'], }; } @@ -51,25 +32,7 @@ module.exports = (api) => { compact: false, }, ], - plugins: [ - [ - 'i18next-extract', - { - contextSeparator: '__', - defaultContexts: [''], - defaultNS: 'en', - discardOldKeys: true, - jsonSpace: 4, - keyAsDefaultValue: ['en'], - keyAsDefaultValueForDerivedKeys: false, - keySeparator: null, - locales: ['en', 'es', 'fr', 'he', 'hi', 'it', 'ja', 'ko', 'nl', 'ru', 'tr', 'pt-BR'], - nsSeparator: null, - outputPath: 'src/i18n/{{locale}}.json', - }, - ], - 'module-resolver', - ], + plugins: ['module-resolver'], presets: ['@babel/env', 'module:@react-native/babel-preset', '@babel/preset-typescript'], }; }; diff --git a/package/bin/validate-translations.js b/package/bin/validate-translations.js index f07eef9cb7..193f8f60a7 100644 --- a/package/bin/validate-translations.js +++ b/package/bin/validate-translations.js @@ -1,7 +1,7 @@ /* eslint-disable no-undef */ -const path = require('path'); const fs = require('fs'); +const path = require('path'); const i18nDirectoryRelativePath = '../src/i18n/'; const directoryPath = path.join(__dirname, i18nDirectoryRelativePath); let countMissingTranslations = 0; @@ -12,7 +12,7 @@ fs.readdir(directoryPath, function (err, files) { } files.forEach(function (file) { - if (file === 'index.js' || file === 'index.ts') return; + if (file.split('.').reverse()[0] !== 'json') return; // Do whatever you want to do with the file const data = require(i18nDirectoryRelativePath + file); const keys = Object.keys(data); diff --git a/package/i18next-parser.config.js b/package/i18next-parser.config.js new file mode 100644 index 0000000000..1ecb57816d --- /dev/null +++ b/package/i18next-parser.config.js @@ -0,0 +1,15 @@ +// https://github.com/i18next/i18next-parser#options +/* global module */ +module.exports = { + createOldCatalogs: false, + input: ['./src/**/*.{tsx,ts}'], + keySeparator: false, + locales: ['en', 'es', 'fr', 'he', 'hi', 'it', 'ja', 'ko', 'nl', 'pt-br', 'ru', 'tr'], + namespaceSeparator: false, + output: 'src/i18n/$LOCALE.json', + sort(a, b) { + return a < b ? -1 : 1; // alfabetical order + }, + useKeysAsDefaultValue: true, + verbose: true, +}; diff --git a/package/package.json b/package/package.json index be811213a9..f2ed02acb4 100644 --- a/package/package.json +++ b/package/package.json @@ -23,17 +23,16 @@ ], "scripts": { "analyze": "yarn build -- --stats && webpack-bundle-analyzer build/bundle-stats.json", - "build": "rm -rf lib && yarn run --silent build-translations && bob build && yarn run --silent copy-translations && yarn run --silent lint-fix-translations", - "lint-fix-translations": "prettier --check 'src/i18n/*.json' --write 'src/i18n/*.json' .eslintrc.json ../.prettierrc .babelrc", - "build-translations": "rm -rf .tmpi18ncache || true && mkdir .tmpi18ncache && yarn run babel --config-file ./babel.i18next-extract.json 'src/**/*.{js,jsx,ts,tsx}' --out-dir '.tmpi18ncache/' && rm -rf .tmpi18ncache && prettier --write 'src/i18n/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc .babelrc", + "build": "rm -rf lib && yarn run --silent build-translations && bob build && yarn run --silent copy-translations", + "build-translations": "i18next", "copy-translations": "echo '\u001b[34mℹ\u001b[0m Copying translation files to \u001b[34mlib/typescript/i18n\u001b[0m' && cp -R -f ./src/i18n ./lib/typescript/i18n && echo '\u001b[32m✓\u001b[0m Done Copying Translations'", "eslint": "eslint 'src/**/*.{js,md,ts,jsx,tsx}' --max-warnings 0", - "lint": "prettier --ignore-path ../.prettierignore --list-different 'src/**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc .babelrc && eslint 'src/**/*.{js,ts,tsx,md}' --max-warnings 0 && yarn run validate-translations", - "lint-fix": "prettier --ignore-path ../.prettierignore --write 'src/**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc .babelrc && eslint --fix 'src/**/*.{js,ts,tsx,md}' --max-warnings 0", + "lint": "prettier --ignore-path ../.prettierignore --list-different 'src/**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc babel.config.js && eslint 'src/**/*.{js,ts,tsx,md}' --max-warnings 0 && yarn run validate-translations", + "lint-fix": "prettier --ignore-path ../.prettierignore --write 'src/**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc babel.config.js && eslint --fix 'src/**/*.{js,ts,tsx,md}' --max-warnings 0", "prepare": "yarn run build", "prepare-distribution": "cd examples/SampleApp && npm version patch && react-native-version && git add ./ && git commit -m 'Bump build version' --no-verify", - "prettier": "prettier --list-different '**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc .babelrc", - "prettier-fix": "prettier --write '**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc .babelrc", + "prettier": "prettier --list-different '**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc babel.config.js", + "prettier-fix": "prettier --write '**/*.{js,ts,tsx,md,json}' .eslintrc.json ../.prettierrc babel.config.js", "test:coverage": "yarn test:unit --coverage", "test:unit": "TZ=UTC jest", "validate-translations": "node bin/validate-translations.js", @@ -120,7 +119,6 @@ "babel-eslint": "10.1.0", "babel-jest": "29.6.3", "babel-loader": "8.2.2", - "babel-plugin-i18next-extract": "0.8.3", "babel-plugin-module-resolver": "4.1.0", "better-sqlite3": "9.0.0", "eslint": "7.32.0", @@ -134,6 +132,7 @@ "eslint-plugin-react": "7.34.1", "eslint-plugin-sort-destructure-keys": "1.5.0", "eslint-plugin-typescript-sort-keys": "3.2.0", + "i18next-parser": "^9.0.0", "jest": "29.6.3", "moment": "2.29.2", "prettier": "2.8.8", diff --git a/package/src/i18n/en.json b/package/src/i18n/en.json index c26caade32..9f19f81a99 100644 --- a/package/src/i18n/en.json +++ b/package/src/i18n/en.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Error loading channel list...", "Error loading messages for this channel...": "Error loading messages for this channel...", "Error while loading, please reload/refresh": "Error while loading, please reload/refresh", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "File is too large: {{ size }}, maximum upload size is {{ limit }}", + "File type not supported": "File type not supported", "Flag": "Flag", "Flag Message": "Flag Message", "Flag action failed either due to a network issue or the message is already flagged": "Flag action failed either due to a network issue or the message is already flagged.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "File is too large: {{ size }}, maximum upload size is {{ limit }}", - "File type not supported": "File type not supported", "Hold to start recording.": "Hold to start recording.", "How about sending your first message to a friend?": "How about sending your first message to a friend?", "Instant Commands": "Instant Commands", diff --git a/package/src/i18n/es.json b/package/src/i18n/es.json index feea498cc7..b5d7916bf8 100644 --- a/package/src/i18n/es.json +++ b/package/src/i18n/es.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Error al cargar la lista de canales...", "Error loading messages for this channel...": "Error al cargar los mensajes de este canal...", "Error while loading, please reload/refresh": "Error al cargar, por favor recarga/actualiza", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "El archivo es demasiado grande: {{ size }}, el tamaño máximo de carga es de {{ limit }}", + "File type not supported": "Tipo de archivo no admitido", "Flag": "Reportar", "Flag Message": "Reportar mensaje", "Flag action failed either due to a network issue or the message is already flagged": "El reporte falló debido a un problema de red o el mensaje ya fue reportado.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "El archivo es demasiado grande: {{ size }}, el tamaño máximo de carga es de {{ limit }}", - "File type not supported": "Tipo de archivo no admitido", "Hold to start recording.": "Mantén presionado para comenzar a grabar.", "How about sending your first message to a friend?": "¿Qué tal enviar tu primer mensaje a un amigo?", "Instant Commands": "Comandos instantáneos", diff --git a/package/src/i18n/fr.json b/package/src/i18n/fr.json index 5030980d02..bdabdb5eaa 100644 --- a/package/src/i18n/fr.json +++ b/package/src/i18n/fr.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Erreur lors du chargement de la liste de canaux...", "Error loading messages for this channel...": "Erreur lors du chargement des messages de ce canal...", "Error while loading, please reload/refresh": "Erreur lors du chargement, veuillez recharger/rafraîchir", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Le fichier est trop volumineux : {{ size }}, la taille de téléchargement maximale est de {{ limit }}", + "File type not supported": "Le type de fichier n'est pas pris en charge", "Flag": "Signaler", "Flag Message": "Signaler le message", "Flag action failed either due to a network issue or the message is already flagged": "L'action de signalisation a échoué en raison d'un problème de réseau ou le message est déjà signalé.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Le fichier est trop volumineux : {{ size }}, la taille de téléchargement maximale est de {{ limit }}", - "File type not supported": "Le type de fichier n'est pas pris en charge", "Hold to start recording.": "Hold to start recording.", "How about sending your first message to a friend?": "Et si vous envoyiez votre premier message à un ami ?", "Instant Commands": "Commandes Instantanées", diff --git a/package/src/i18n/he.json b/package/src/i18n/he.json index 75df209d31..9dd83b7df4 100644 --- a/package/src/i18n/he.json +++ b/package/src/i18n/he.json @@ -24,11 +24,11 @@ "Error loading channel list...": "שגיאה ארעה בטעינת השיחות...", "Error loading messages for this channel...": "שגיאה ארעה בטעינת הודעות עבור שיחה זאת...", "Error while loading, please reload/refresh": "שגיאה ארעה בזמן הטעינה, אנא טען מחדש/רענן", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "הקובץ גדול מדי: {{ size }}, גודל העלאה מקסימלי הוא {{ limit }}", + "File type not supported": "סוג הקובץ אינו נתמך", "Flag": "סמן", "Flag Message": "סמן הודעה", "Flag action failed either due to a network issue or the message is already flagged": "פעולת הסימון נכשלה בגלל בעיית רשת או שההודעה כבר סומנה.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "הקובץ גדול מדי: {{ size }}, גודל העלאה מקסימלי הוא {{ limit }}", - "File type not supported": "סוג הקובץ אינו נתמך", "Hold to start recording.": "לחץ והחזק כדי להתחיל להקליט.", "How about sending your first message to a friend?": "מה דעתך לשלוח את ההודעה הראשונה שלך לחבר?", "Instant Commands": "פעולות מיידיות", diff --git a/package/src/i18n/hi.json b/package/src/i18n/hi.json index 8beab108c4..ec0cabc01e 100644 --- a/package/src/i18n/hi.json +++ b/package/src/i18n/hi.json @@ -24,11 +24,11 @@ "Error loading channel list...": "चैनल सूची लोड करने में त्रुटि...", "Error loading messages for this channel...": "इस चैनल के लिए मेसेजेस लोड करने में त्रुटि हुई...", "Error while loading, please reload/refresh": "एरर, रिफ्रेश करे", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "फ़ाइल बहुत बड़ी है: {{ size }}, अधिकतम अपलोड साइज़ {{ limit }} है", + "File type not supported": "फ़ाइल प्रकार समर्थित नहीं है", "Flag": "झंडा", "Flag Message": "झंडा संदेश", "Flag action failed either due to a network issue or the message is already flagged": "फ़्लैग कार्रवाई या तो नेटवर्क समस्या के कारण विफल हो गई या संदेश पहले से फ़्लैग किया गया है।", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "फ़ाइल बहुत बड़ी है: {{ size }}, अधिकतम अपलोड साइज़ {{ limit }} है", - "File type not supported": "फ़ाइल प्रकार समर्थित नहीं है", "Hold to start recording.": "रिकॉर्डिंग शुरू करने के लिए दबाएं।", "How about sending your first message to a friend?": "किसी मित्र को अपना पहला संदेश भेजने के बारे में क्या ख़याल है?", "Instant Commands": "त्वरित कमांड", diff --git a/package/src/i18n/it.json b/package/src/i18n/it.json index 6f5399fa3c..f6c45803a1 100644 --- a/package/src/i18n/it.json +++ b/package/src/i18n/it.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Errore durante il caricamento della lista dei canali...", "Error loading messages for this channel...": "Errore durante il caricamento dei messaggi per questo canale...", "Error while loading, please reload/refresh": "Errore durante il caricamento, per favore ricarica la pagina", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Il file è troppo grande: {{ size }}, la dimensione massima di caricamento è {{ limit }}", + "File type not supported": "Tipo di file non supportato", "Flag": "Contrassegna", "Flag Message": "Contrassegna Messaggio", "Flag action failed either due to a network issue or the message is already flagged": "L'azione di segnalazione non è riuscita a causa di un problema di rete o il messaggio è già segnalato.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Il file è troppo grande: {{ size }}, la dimensione massima di caricamento è {{ limit }}", - "File type not supported": "Tipo di file non supportato", "Hold to start recording.": "Tieni premuto per avviare la registrazione.", "How about sending your first message to a friend?": "Che ne dici di inviare il tuo primo messaggio ad un amico?", "Instant Commands": "Comandi Istantanei", diff --git a/package/src/i18n/ja.json b/package/src/i18n/ja.json index 3c2ce9364c..6ab5bb75f3 100644 --- a/package/src/i18n/ja.json +++ b/package/src/i18n/ja.json @@ -24,11 +24,11 @@ "Error loading channel list...": "チャネルリストの読み込み中にエラーが発生しました。。。", "Error loading messages for this channel...": "このチャネルのメッセージの読み込み中にエラーが発生しました。。。", "Error while loading, please reload/refresh": "ロード中にエラーが発生しました。更新してください", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "ファイルが大きすぎます:{{ size }}、最大アップロードサイズは{{ limit }}です", + "File type not supported": "サポートされていないファイルです", "Flag": "フラグ", "Flag Message": "メッセージをフラグする", "Flag action failed either due to a network issue or the message is already flagged": "ネットワーク接続に問題があるか、すでにフラグが設定されているため、フラグが失敗しました。", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "ファイルが大きすぎます:{{ size }}、最大アップロードサイズは{{ limit }}です", - "File type not supported": "サポートされていないファイルです", "Hold to start recording.": "録音を開始するには押し続けてください。", "How about sending your first message to a friend?": "初めてのメッセージを友達に送ってみてはいかがでしょうか?", "Instant Commands": "インスタントコマンド", diff --git a/package/src/i18n/ko.json b/package/src/i18n/ko.json index cf3e5bb894..3c0f53d7f2 100644 --- a/package/src/i18n/ko.json +++ b/package/src/i18n/ko.json @@ -1,6 +1,6 @@ { "1 Reply": "답장 1개", - "1 Thread Reply": "1개의 스레드 답글", + "1 Thread Reply": "1개의 스레드\u3000답글", "Allow access to your Gallery": "갤러리에 대한 액세스를 허용", "Allow camera access in device settings": "기기 설정에서 카메라 액세스를 허용하세요.", "Also send to channel": "채널에도 전송", @@ -24,11 +24,11 @@ "Error loading channel list...": "채널리스트 을로드하는 동안 오류가 발생했습니다...", "Error loading messages for this channel...": "이 채널의 메시지를로드하는 동안 오류가 발생했습니다...", "Error while loading, please reload/refresh": "로드하는 동안 오류가 발생했습니다. 다시로드하십시오", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "파일이 너무 큽니다: {{ size }}, 최대 업로드 크기는 {{ limit }}입니다", + "File type not supported": "지원하지 않는 파일입니다.", "Flag": "플래그", "Flag Message": "메시지를 플래그하기", "Flag action failed either due to a network issue or the message is already flagged": "네트워크 연결에 문제가 있거나 이미 플래그 되어서 플래그에 실패했습니다.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "파일이 너무 큽니다: {{ size }}, 최대 업로드 크기는 {{ limit }}입니다", - "File type not supported": "지원하지 않는 파일입니다.", "Hold to start recording.": "녹음을 시작하려면 눌러주세요.", "How about sending your first message to a friend?": "친구에게 첫 번째 메시지를 보내는 것은 어떻습니까?", "Instant Commands": "인스턴트 명령", @@ -65,7 +65,7 @@ "Sending links is not allowed in this conversation": "이 대화에서는 링크 기능을 사용할 수 없습니다", "Slow mode ON": "슬로모드 켜짐", "The message has been reported to a moderator.": "메시지는 운영자에보고되었습니다.", - "Thread Reply": "스레드 답장", + "Thread Reply": "스레드\u3000답장", "Unblock User": "사용자 차단 해제", "Unknown User": "알 수없는 사용자", "Unmute User": "사용자 음소거 해제", @@ -77,7 +77,7 @@ "{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "{{ firstUser }} 외 {{ nonSelfUserLength }}명이 입력 중입니다", "{{ index }} of {{ photoLength }}": "{{ index }} / {{ photoLength }}", "{{ replyCount }} Replies": "{{ replyCount }} 답글", - "{{ replyCount }} Thread Replies": "{{ replyCount }} 스레드 답글", + "{{ replyCount }} Thread Replies": "{{ replyCount }}\u3000스레드\u3000답글", "{{ user }} is typing": "{{ user }} 타이핑 중", "🏙 Attachment...": "🏙 부착..." } diff --git a/package/src/i18n/nl.json b/package/src/i18n/nl.json index 30690dacb9..a72a3240ff 100644 --- a/package/src/i18n/nl.json +++ b/package/src/i18n/nl.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Probleem bij het laden van de kanalen...", "Error loading messages for this channel...": "Probleem bij het laden van de berichten in dit kanaal...", "Error while loading, please reload/refresh": "Probleem bij het laden, probeer opnieuw", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Bestand is te groot: {{ size }}, maximale uploadgrootte is {{ limit }}", + "File type not supported": "Bestandstype niet ondersteund", "Flag": "Markeer", "Flag Message": "Markeer bericht", "Flag action failed either due to a network issue or the message is already flagged": "Rapporteren mislukt door een netwerk fout of het berich is al gerapporteerd", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Bestand is te groot: {{ size }}, maximale uploadgrootte is {{ limit }}", - "File type not supported": "Bestandstype niet ondersteund", "Hold to start recording.": "Houd vast om opname te starten.", "How about sending your first message to a friend?": "Wat dacht je ervan om je eerste bericht naar een vriend te sturen?", "Instant Commands": "Directe Opdrachten", diff --git a/package/src/i18n/pt-BR.json b/package/src/i18n/pt-BR.json index 83ea8215cd..4c643afc46 100644 --- a/package/src/i18n/pt-BR.json +++ b/package/src/i18n/pt-BR.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Erro ao carregar lista de canais...", "Error loading messages for this channel...": "Erro ao carregar mensagens para este canal...", "Error while loading, please reload/refresh": "Erro ao carregar, por favor recarregue/atualize", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "O arquivo é muito grande: {{ size }}, o tamanho máximo de upload é {{ limit }}", + "File type not supported": "Tipo de arquivo não suportado", "Flag": "Reportar", "Flag Message": "Reportar Mensagem", "Flag action failed either due to a network issue or the message is already flagged": "A ação para reportar a mensagem falhou devido a um problema de rede ou a mensagem já foi reportada.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "O arquivo é muito grande: {{ size }}, o tamanho máximo de upload é {{ limit }}", - "File type not supported": "Tipo de arquivo não suportado", "Hold to start recording.": "Mantenha pressionado para começar a gravar.", "How about sending your first message to a friend?": "Que tal enviar sua primeira mensagem para um amigo?", "Instant Commands": "Comandos Instantâneos", diff --git a/package/src/i18n/ru.json b/package/src/i18n/ru.json index dea08ec299..7fef9463f2 100644 --- a/package/src/i18n/ru.json +++ b/package/src/i18n/ru.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Ошибка загрузки списка каналов...", "Error loading messages for this channel...": "Ошибка загрузки сообщений для этого канала...", "Error while loading, please reload/refresh": "Ошибка загрузки, пожалуйста перезагрузите или обновите", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Файл слишком большой: {{ size }}, максимальный размер загрузки составляет {{ limit }}", + "File type not supported": "Тип файла не поддерживается", "Flag": "Пометить", "Flag Message": "Пометить сообщение", "Flag action failed either due to a network issue or the message is already flagged": "Не удалось отправить жалобу. Возможные причины: проблема с подключением к интернету или ваша жалоба уже была принята.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Файл слишком большой: {{ size }}, максимальный размер загрузки составляет {{ limit }}", - "File type not supported": "Тип файла не поддерживается", "Hold to start recording.": "Удерживайте, чтобы начать запись.", "How about sending your first message to a friend?": "Как насчет отправки первого сообщения другу?", "Instant Commands": "Мгновенные Команды", diff --git a/package/src/i18n/tr.json b/package/src/i18n/tr.json index aca6f73703..aad2912960 100644 --- a/package/src/i18n/tr.json +++ b/package/src/i18n/tr.json @@ -24,11 +24,11 @@ "Error loading channel list...": "Kanal listesi yüklenirken hata oluştu...", "Error loading messages for this channel...": "Bu kanal için mesajlar yüklenirken hata oluştu...", "Error while loading, please reload/refresh": "Yüklenirken hata oluştu, lütfen tekrar deneyiniz", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Dosya çok büyük: {{ size }}, maksimum yükleme boyutu {{ limit }}", + "File type not supported": "Dosya türü desteklenmiyor", "Flag": "Raporla", "Flag Message": "Mesajı Raporla", "Flag action failed either due to a network issue or the message is already flagged": "Mesajın daha önce raporlanmış olması veya bir ağ bağlantısı sorunu nedeniyle raporlama işlemi başarısız oldu.", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "Dosya çok büyük: {{ size }}, maksimum yükleme boyutu {{ limit }}", - "File type not supported": "Dosya türü desteklenmiyor", "Hold to start recording.": "Kayıt yapmak için basılı tutun.", "How about sending your first message to a friend?": "İlk mesajınızı bir arkadaşınıza göndermeye ne dersiniz?", "Instant Commands": "Anlık Komutlar", diff --git a/package/yarn.lock b/package/yarn.lock index 320f74906e..d729819cbb 100644 --- a/package/yarn.lock +++ b/package/yarn.lock @@ -478,7 +478,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== -"@babel/helper-validator-identifier@^7.22.5", "@babel/helper-validator-identifier@^7.9.5": +"@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== @@ -1788,6 +1788,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.23.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.0.0", "@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -1838,15 +1845,6 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" - integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== - dependencies: - "@babel/helper-validator-identifier" "^7.9.5" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" @@ -1877,6 +1875,121 @@ dependencies: "@types/hammerjs" "^2.0.36" +"@esbuild/aix-ppc64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" + integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== + +"@esbuild/android-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" + integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== + +"@esbuild/android-arm@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" + integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== + +"@esbuild/android-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" + integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== + +"@esbuild/darwin-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" + integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== + +"@esbuild/darwin-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" + integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== + +"@esbuild/freebsd-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" + integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== + +"@esbuild/freebsd-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" + integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== + +"@esbuild/linux-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" + integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== + +"@esbuild/linux-arm@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" + integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== + +"@esbuild/linux-ia32@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" + integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== + +"@esbuild/linux-loong64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" + integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== + +"@esbuild/linux-mips64el@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" + integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== + +"@esbuild/linux-ppc64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" + integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== + +"@esbuild/linux-riscv64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" + integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== + +"@esbuild/linux-s390x@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" + integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== + +"@esbuild/linux-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" + integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== + +"@esbuild/netbsd-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" + integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== + +"@esbuild/openbsd-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" + integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== + +"@esbuild/sunos-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" + integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== + +"@esbuild/win32-arm64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" + integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== + +"@esbuild/win32-ia32@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" + integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== + +"@esbuild/win32-x64@0.20.2": + version "0.20.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" + integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1919,6 +2032,13 @@ dependencies: nanoid "^3.3.1" +"@gulpjs/to-absolute-glob@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz#1fc2460d3953e1d9b9f2dfdb4bcc99da4710c021" + integrity sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA== + dependencies: + is-negated-glob "^1.0.0" + "@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -2794,6 +2914,11 @@ resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73" integrity sha512-8LDSKVdJxwfJXZAcHRwFDxozsTCo3UmIpDjN1cOnYMTr0h4ivK9I+IdEMdtjnssFm0y66vbnpd21mAgGZ1oGAQ== +"@types/minimatch@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + "@types/node@*": version "20.2.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" @@ -2845,6 +2970,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/symlink-or-copy@^1.2.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/symlink-or-copy/-/symlink-or-copy-1.2.2.tgz#51b1c00b516a5774ada5d611e65eb123f988ef8d" + integrity sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA== + "@types/uuid@^8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -3414,7 +3544,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -anymatch@^3.0.3, anymatch@~3.1.2: +anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -3439,6 +3569,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -3666,6 +3801,11 @@ axios@^1.6.0: form-data "^4.0.0" proxy-from-env "^1.1.0" +b4a@^1.6.4: + version "1.6.6" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.6.tgz#a4cc349a3851987c3c4ac2d7785c18744f6da9ba" + integrity sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg== + babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" @@ -3719,17 +3859,6 @@ babel-loader@8.2.2: make-dir "^3.1.0" schema-utils "^2.6.5" -babel-plugin-i18next-extract@0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/babel-plugin-i18next-extract/-/babel-plugin-i18next-extract-0.8.3.tgz#4b1c279f5ac607c96b6b71074dd15842b5c21df0" - integrity sha512-ZBhGjP2nLF3pGJO/X6s8DlyUo8zkuPQ09sGZK4XGqtJit/ccj8zocO5JI/F+oFZgKVH1tN8pAQT4fm0JWk2SIQ== - dependencies: - "@babel/core" "^7.12.3" - "@babel/types" "7.9.6" - deepmerge "^4.2.2" - i18next "^19.8.3" - json-stable-stringify "^1.0.1" - babel-plugin-istanbul@^6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -3877,6 +4006,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bare-events@^2.2.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.4.2.tgz#3140cca7a0e11d49b3edc5041ab560659fd8e1f8" + integrity sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q== + base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -3934,6 +4068,15 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" +bl@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273" + integrity sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ== + dependencies: + buffer "^6.0.3" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -3992,6 +4135,38 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +broccoli-node-api@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/broccoli-node-api/-/broccoli-node-api-1.7.0.tgz#391aa6edecd2a42c63c111b4162956b2fa288cb6" + integrity sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw== + +broccoli-node-info@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/broccoli-node-info/-/broccoli-node-info-2.2.0.tgz#feb01c13020792f429e01d7f7845dc5b3a7932b3" + integrity sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg== + +broccoli-output-wrapper@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/broccoli-output-wrapper/-/broccoli-output-wrapper-3.2.5.tgz#514b17801c92922a2c2f87fd145df2a25a11bc5f" + integrity sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw== + dependencies: + fs-extra "^8.1.0" + heimdalljs-logger "^0.1.10" + symlink-or-copy "^1.2.0" + +broccoli-plugin@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/broccoli-plugin/-/broccoli-plugin-4.0.7.tgz#dd176a85efe915ed557d913744b181abe05047db" + integrity sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg== + dependencies: + broccoli-node-api "^1.7.0" + broccoli-output-wrapper "^3.2.5" + fs-merger "^3.2.1" + promise-map-series "^0.3.0" + quick-temp "^0.1.8" + rimraf "^3.0.2" + symlink-or-copy "^1.3.1" + brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -4117,6 +4292,14 @@ buffer@^5.4.3, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -4263,6 +4446,31 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -4406,11 +4614,21 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag== + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +clone@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -4463,6 +4681,11 @@ colorette@^1.0.7: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +colors@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -4490,6 +4713,11 @@ commander@^9.4.1: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== +commander@~12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -5106,7 +5334,12 @@ enquirer@^2.3.5: ansi-colors "^4.1.1" strip-ansi "^6.0.1" -entities@^4.2.0: +ensure-posix-path@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" + integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== + +entities@^4.2.0, entities@^4.4.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -5116,6 +5349,11 @@ envinfo@^7.10.0: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.1.tgz#2ffef77591057081b0129a8fd8cf6118da1b94e1" integrity sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg== +eol@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" + integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== + errno@^0.1.3, errno@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" @@ -5317,6 +5555,35 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +esbuild@^0.20.1: + version "0.20.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" + integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== + optionalDependencies: + "@esbuild/aix-ppc64" "0.20.2" + "@esbuild/android-arm" "0.20.2" + "@esbuild/android-arm64" "0.20.2" + "@esbuild/android-x64" "0.20.2" + "@esbuild/darwin-arm64" "0.20.2" + "@esbuild/darwin-x64" "0.20.2" + "@esbuild/freebsd-arm64" "0.20.2" + "@esbuild/freebsd-x64" "0.20.2" + "@esbuild/linux-arm" "0.20.2" + "@esbuild/linux-arm64" "0.20.2" + "@esbuild/linux-ia32" "0.20.2" + "@esbuild/linux-loong64" "0.20.2" + "@esbuild/linux-mips64el" "0.20.2" + "@esbuild/linux-ppc64" "0.20.2" + "@esbuild/linux-riscv64" "0.20.2" + "@esbuild/linux-s390x" "0.20.2" + "@esbuild/linux-x64" "0.20.2" + "@esbuild/netbsd-x64" "0.20.2" + "@esbuild/openbsd-x64" "0.20.2" + "@esbuild/sunos-x64" "0.20.2" + "@esbuild/win32-arm64" "0.20.2" + "@esbuild/win32-ia32" "0.20.2" + "@esbuild/win32-x64" "0.20.2" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -5788,6 +6055,11 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== +fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + fast-glob@^3.2.9: version "3.2.12" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" @@ -5816,6 +6088,13 @@ fast-xml-parser@^4.0.12, fast-xml-parser@^4.2.4: dependencies: strnum "^1.0.5" +fastq@^1.13.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + fastq@^1.6.0: version "1.15.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" @@ -6022,7 +6301,16 @@ fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^8.1.0: +fs-extra@^11.1.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^8.0.1, fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== @@ -6031,11 +6319,41 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-merger@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/fs-merger/-/fs-merger-3.2.1.tgz#a225b11ae530426138294b8fbb19e82e3d4e0b3b" + integrity sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug== + dependencies: + broccoli-node-api "^1.7.0" + broccoli-node-info "^2.1.0" + fs-extra "^8.0.1" + fs-tree-diff "^2.0.1" + walk-sync "^2.2.0" + +fs-mkdirp-stream@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz#1e82575c4023929ad35cf69269f84f1a8c973aa7" + integrity sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw== + dependencies: + graceful-fs "^4.2.8" + streamx "^2.12.0" + fs-readdir-recursive@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== +fs-tree-diff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fs-tree-diff/-/fs-tree-diff-2.0.1.tgz#343e4745ab435ec39ebac5f9059ad919cd034afa" + integrity sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A== + dependencies: + "@types/symlink-or-copy" "^1.2.0" + heimdalljs-logger "^0.1.7" + object-assign "^4.1.0" + path-posix "^1.0.0" + symlink-or-copy "^1.1.8" + fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -6204,6 +6522,27 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-stream@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-8.0.2.tgz#09e5818e41c16dd85274d72c7a7158d307426313" + integrity sha512-R8z6eTB55t3QeZMmU1C+Gv+t5UnNRkA55c5yo67fAVfxODxieTwsjNG7utxS/73NdP1NbDgCrhVEg2h00y4fFw== + dependencies: + "@gulpjs/to-absolute-glob" "^4.0.0" + anymatch "^3.1.3" + fastq "^1.13.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + is-negated-glob "^1.0.0" + normalize-path "^3.0.0" + streamx "^2.12.5" + glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -6265,7 +6604,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.8, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -6275,6 +6614,13 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +gulp-sort@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-sort/-/gulp-sort-2.0.0.tgz#c6762a2f1f0de0a3fc595a21599d3fac8dba1aca" + integrity sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g== + dependencies: + through2 "^2.0.1" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -6395,6 +6741,21 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +heimdalljs-logger@^0.1.10, heimdalljs-logger@^0.1.7: + version "0.1.10" + resolved "https://registry.yarnpkg.com/heimdalljs-logger/-/heimdalljs-logger-0.1.10.tgz#90cad58aabb1590a3c7e640ddc6a4cd3a43faaf7" + integrity sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g== + dependencies: + debug "^2.2.0" + heimdalljs "^0.2.6" + +heimdalljs@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heimdalljs/-/heimdalljs-0.2.6.tgz#b0eebabc412813aeb9542f9cc622cb58dbdcd9fe" + integrity sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA== + dependencies: + rsvp "~3.2.1" + hermes-estree@0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.15.0.tgz#e32f6210ab18c7b705bdcb375f7700f2db15d6ba" @@ -6447,6 +6808,16 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -6473,6 +6844,29 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +i18next-parser@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-9.0.0.tgz#7cd8d2cdc27a25e783670ce05ab2798d7e4da634" + integrity sha512-ZguWdu91Qthd001ilX8LdkYrlyYJM8pefnmgTXKTQwd8M2RJAlTCd2ww5uEyAUQe2jxzqSxfTh6XTOJbw5qP5A== + dependencies: + "@babel/runtime" "^7.23.2" + broccoli-plugin "^4.0.7" + cheerio "^1.0.0-rc.2" + colors "1.4.0" + commander "~12.1.0" + eol "^0.9.1" + esbuild "^0.20.1" + fs-extra "^11.1.0" + gulp-sort "^2.0.0" + i18next "^23.5.1" + js-yaml "4.1.0" + lilconfig "^3.0.0" + rsvp "^4.8.2" + sort-keys "^5.0.0" + typescript "^5.0.4" + vinyl "~3.0.0" + vinyl-fs "^4.0.0" + i18next@20.2.4: version "20.2.4" resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.2.4.tgz#972220f19dfef0075a70890d3e8b1f7cf64c5bd6" @@ -6480,14 +6874,21 @@ i18next@20.2.4: dependencies: "@babel/runtime" "^7.12.0" -i18next@^19.8.3: - version "19.9.2" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.9.2.tgz#ea5a124416e3c5ab85fddca2c8e3c3669a8da397" - integrity sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg== +i18next@^23.5.1: + version "23.11.5" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.11.5.tgz#d71eb717a7e65498d87d0594f2664237f9e361ef" + integrity sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA== dependencies: - "@babel/runtime" "^7.12.0" + "@babel/runtime" "^7.23.2" + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@^1.1.13, ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -6880,6 +7281,11 @@ is-map@^2.0.3: resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== +is-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug== + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -6924,6 +7330,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== +is-plain-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -7014,6 +7425,11 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA== + is-weakmap@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" @@ -7531,6 +7947,13 @@ joi@^17.2.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -7614,13 +8037,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stable-stringify@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" - integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== - dependencies: - jsonify "^0.0.1" - json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -7654,11 +8070,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - jsonwebtoken@~9.0.0: version "9.0.2" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" @@ -7734,6 +8145,11 @@ kleur@^4.1.4: resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== +lead@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-4.0.0.tgz#5317a49effb0e7ec3a0c8fb9c1b24fb716aab939" + integrity sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -7755,6 +8171,11 @@ lighthouse-logger@^1.0.0: debug "^2.6.9" marky "^1.2.2" +lilconfig@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -7861,7 +8282,7 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== -lodash@^4.17.10, lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.21: +lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7948,6 +8369,14 @@ marky@^1.2.2: resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== +matcher-collection@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/matcher-collection/-/matcher-collection-2.0.1.tgz#90be1a4cf58d6f2949864f65bb3b0f3e41303b29" + integrity sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ== + dependencies: + "@types/minimatch" "^3.0.3" + minimatch "^3.0.2" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -8326,6 +8755,11 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mktemp@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b" + integrity sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A== + moment@2.29.2: version "2.29.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4" @@ -8490,6 +8924,11 @@ node-stream-zip@^1.9.1: resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.15.0.tgz#158adb88ed8004c6c49a396b50a6a5de3bca33ea" integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== +normalize-path@3.0.0, normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" @@ -8497,10 +8936,12 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0, normalize-path@~3.0.0: +now-and-later@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-3.0.0.tgz#cdc045dc5b894b35793cf276cc3206077bb7302d" + integrity sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg== + dependencies: + once "^1.4.0" npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" @@ -8526,7 +8967,7 @@ ob1@0.80.8: resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.8.tgz#08be1b8398d004719074ad702c975a5c7e1b29f2" integrity sha512-QHJQk/lXMmAW8I7AIM3in1MSlwe1umR72Chhi8B7Xnq6mzjhBKkA6Fy/zAhQnGkA4S912EPCEvTij5yh+EQTAA== -object-assign@^4.1.1: +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -8824,6 +9265,21 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" + +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -8869,6 +9325,11 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-posix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" + integrity sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -9018,6 +9479,11 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== +promise-map-series@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promise-map-series/-/promise-map-series-0.3.0.tgz#41873ca3652bb7a042b387d538552da9b576f8a1" + integrity sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA== + promise@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" @@ -9124,6 +9590,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue-tick@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== + queue@6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" @@ -9131,6 +9602,15 @@ queue@6.0.2: dependencies: inherits "~2.0.3" +quick-temp@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/quick-temp/-/quick-temp-0.1.8.tgz#bab02a242ab8fb0dd758a3c9776b32f9a5d94408" + integrity sha512-YsmIFfD9j2zaFwJkzI6eMG7y0lQP7YeWzgtFgNl38pGWZBSXJooZbOWwkcRot7Vt0Fg9L23pX0tqWU3VvLDsiA== + dependencies: + mktemp "~0.4.0" + rimraf "^2.5.4" + underscore.string "~3.3.4" + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -9527,7 +10007,7 @@ remark-parse@^7.0.0: vfile-location "^2.0.0" xtend "^4.0.1" -remove-trailing-separator@^1.0.1: +remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== @@ -9547,6 +10027,11 @@ replace-ext@1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha512-vuNYXC7gG7IeVNBC1xUllqCcZKRbJoSPOBhnTEcAIiKCsbuef6zO3F0Rve3isPMMoNoQRWjQwbAgAjHUHniyEA== +replace-ext@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-2.0.0.tgz#9471c213d22e1bcc26717cd6e50881d88f812b06" + integrity sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -9589,6 +10074,13 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-options@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-2.0.0.tgz#a1a57a9949db549dd075de3f5550675f02f1e4c5" + integrity sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A== + dependencies: + value-or-function "^4.0.0" + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -9664,6 +10156,16 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rsvp@^4.8.2: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + +rsvp@~3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.2.1.tgz#07cb4a5df25add9e826ebc67dcc9fd89db27d84a" + integrity sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -9723,7 +10225,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -safer-buffer@^2.1.0: +"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -10017,6 +10519,13 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +sort-keys@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.0.0.tgz#5d775f8ae93ecc29bc7312bbf3acac4e36e3c446" + integrity sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw== + dependencies: + is-plain-obj "^4.0.0" + source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" @@ -10076,6 +10585,11 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" +sprintf-js@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -10153,6 +10667,13 @@ stream-chat@8.31.0: jsonwebtoken "~9.0.0" ws "^7.4.4" +stream-composer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stream-composer/-/stream-composer-1.0.2.tgz#7ee61ca1587bf5f31b2e29aa2093cbf11442d152" + integrity sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w== + dependencies: + streamx "^2.13.2" + stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" @@ -10177,6 +10698,17 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.18.0.tgz#5bc1a51eb412a667ebfdcd4e6cf6a6fc65721ac7" + integrity sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ== + dependencies: + fast-fifo "^1.3.2" + queue-tick "^1.0.1" + text-decoder "^1.1.0" + optionalDependencies: + bare-events "^2.2.0" + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -10363,6 +10895,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +symlink-or-copy@^1.1.8, symlink-or-copy@^1.2.0, symlink-or-copy@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/symlink-or-copy/-/symlink-or-copy-1.3.1.tgz#9506dd64d8e98fa21dcbf4018d1eab23e77f71fe" + integrity sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA== + table@^6.0.9: version "6.8.2" resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" @@ -10400,6 +10937,13 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" +teex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/teex/-/teex-1.0.1.tgz#b8fa7245ef8e8effa8078281946c85ab780a0b12" + integrity sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg== + dependencies: + streamx "^2.12.5" + temp-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" @@ -10455,6 +10999,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-decoder@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.1.0.tgz#3379e728fcf4d3893ec1aea35e8c2cac215ef190" + integrity sha512-TmLJNj6UgX8xcUZo4UDStGQtDiTzF7BzWlzn9g7UWrjkpHr5uJTK1ld16wZ3LXb2vb6jH8qU89dW5whuMdXYdw== + dependencies: + b4a "^1.6.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -10527,6 +11078,13 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +to-through@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-3.0.0.tgz#bf4956eaca5a0476474850a53672bed6906ace54" + integrity sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw== + dependencies: + streamx "^2.12.5" + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -10686,6 +11244,11 @@ typescript@5.0.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== +typescript@^5.0.4: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" @@ -10701,6 +11264,14 @@ unc-path-regex@^0.1.2: resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== +underscore.string@~3.3.4: + version "3.3.6" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.6.tgz#ad8cf23d7423cb3b53b898476117588f4e2f9159" + integrity sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ== + dependencies: + sprintf-js "^1.1.1" + util-deprecate "^1.0.2" + unherit@^1.0.4: version "1.1.3" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" @@ -10868,7 +11439,7 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -10918,6 +11489,11 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +value-or-function@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-4.0.0.tgz#70836b6a876a010dc3a2b884e7902e9db064378d" + integrity sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg== + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -10945,6 +11521,57 @@ vfile@^2.0.0: unist-util-stringify-position "^1.0.0" vfile-message "^1.0.0" +vinyl-contents@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/vinyl-contents/-/vinyl-contents-2.0.0.tgz#cc2ba4db3a36658d069249e9e36d9e2b41935d89" + integrity sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q== + dependencies: + bl "^5.0.0" + vinyl "^3.0.0" + +vinyl-fs@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-4.0.0.tgz#06cb36efc911c6e128452f230b96584a9133c3a1" + integrity sha512-7GbgBnYfaquMk3Qu9g22x000vbYkOex32930rBnc3qByw6HfMEAoELjCjoJv4HuEQxHAurT+nvMHm6MnJllFLw== + dependencies: + fs-mkdirp-stream "^2.0.1" + glob-stream "^8.0.0" + graceful-fs "^4.2.11" + iconv-lite "^0.6.3" + is-valid-glob "^1.0.0" + lead "^4.0.0" + normalize-path "3.0.0" + resolve-options "^2.0.0" + stream-composer "^1.0.2" + streamx "^2.14.0" + to-through "^3.0.0" + value-or-function "^4.0.0" + vinyl "^3.0.0" + vinyl-sourcemap "^2.0.0" + +vinyl-sourcemap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz#422f410a0ea97cb54cebd698d56a06d7a22e0277" + integrity sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q== + dependencies: + convert-source-map "^2.0.0" + graceful-fs "^4.2.10" + now-and-later "^3.0.0" + streamx "^2.12.5" + vinyl "^3.0.0" + vinyl-contents "^2.0.0" + +vinyl@^3.0.0, vinyl@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-3.0.0.tgz#11e14732bf56e2faa98ffde5157fe6c13259ff30" + integrity sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g== + dependencies: + clone "^2.1.2" + clone-stats "^1.0.0" + remove-trailing-separator "^1.1.0" + replace-ext "^2.0.0" + teex "^1.0.1" + vlq@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" @@ -10955,6 +11582,16 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +walk-sync@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-2.2.0.tgz#80786b0657fcc8c0e1c0b1a042a09eae2966387a" + integrity sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg== + dependencies: + "@types/minimatch" "^3.0.3" + ensure-posix-path "^1.1.0" + matcher-collection "^2.0.0" + minimatch "^3.0.4" + walker@^1.0.7, walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" From 31e164aed556f7a5faf08257a5d80f5c223946e2 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:04:22 +0530 Subject: [PATCH 16/25] fix: use i18n-parser for build-translations and improve related scripts --- package/babel.i18next-extract.json | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 package/babel.i18next-extract.json diff --git a/package/babel.i18next-extract.json b/package/babel.i18next-extract.json deleted file mode 100644 index ea86ed7c53..0000000000 --- a/package/babel.i18next-extract.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "presets": ["@babel/env", "module:@react-native/babel-preset"], - "plugins": [ - [ - "i18next-extract", - { - "contextSeparator": "__", - "defaultContexts": [""], - "defaultNS": "en", - "locales": ["en", "es", "fr", "he", "hi", "it", "ja", "ko", "nl", "ru", "tr", "pt-BR"], - "jsonSpace": 4, - "keySeparator": null, - "nsSeparator": null, - "keyAsDefaultValue": ["en"], - "keyAsDefaultValueForDerivedKeys": false, - "outputPath": "src/i18n/{{locale}}.json", - "discardOldKeys": true - } - ], - "@babel/transform-runtime" - ] -} From f1098408a4986626967a6d35085208de657160fa Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:07:03 +0530 Subject: [PATCH 17/25] fix: prettier config --- .prettierrc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index 753a6e9d36..cbb3f3b95d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -4,5 +4,18 @@ "printWidth": 100, "singleQuote": true, "tabWidth": 2, - "trailingComma": "all" + "trailingComma": "all", + "overrides": [ + { + "files": ["*.md", "*.mdx"], + "options": { + "arrowParens": "avoid", + "jsxSingleQuote": true, + "printWidth": 120, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all" + } + } + ] } From 5562e8919c4dad067f7ceeb625f3c0dba944638c Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:24:18 +0530 Subject: [PATCH 18/25] debug commit --- package/bin/validate-translations.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package/bin/validate-translations.js b/package/bin/validate-translations.js index 193f8f60a7..0f4dedfcbb 100644 --- a/package/bin/validate-translations.js +++ b/package/bin/validate-translations.js @@ -15,6 +15,9 @@ fs.readdir(directoryPath, function (err, files) { if (file.split('.').reverse()[0] !== 'json') return; // Do whatever you want to do with the file const data = require(i18nDirectoryRelativePath + file); + if (file === 'pt-BR.json') { + console.log(data); + } const keys = Object.keys(data); keys.forEach((key) => { if (!data[key] || data[key] === '') { From 4c2f4d4c696e8f0c29ffbaf5d0994e8d0f59b77d Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:28:59 +0530 Subject: [PATCH 19/25] debug commit --- package/src/i18n/pt-br.json | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 package/src/i18n/pt-br.json diff --git a/package/src/i18n/pt-br.json b/package/src/i18n/pt-br.json new file mode 100644 index 0000000000..4c643afc46 --- /dev/null +++ b/package/src/i18n/pt-br.json @@ -0,0 +1,83 @@ +{ + "1 Reply": "1 Resposta", + "1 Thread Reply": "1 Resposta de Thread", + "Allow access to your Gallery": "Permitir acesso à sua Galeria", + "Allow camera access in device settings": "Permitir acesso à câmera nas configurações do dispositivo", + "Also send to channel": "Também enviar para o canal", + "Are you sure you want to permanently delete this message?": "Tem certeza de que deseja excluir esta mensagem permanentemente?", + "Are you sure?": "Tem certeza?", + "Block User": "Bloquear Usuário", + "Cancel": "Cancelar", + "Cannot Flag Message": "Não é possível reportar a mensagem", + "Consider how your comment might make others feel and be sure to follow our Community Guidelines": "Considere como seu comentário pode fazer os outros se sentirem e certifique-se de seguir nossas Diretrizes da Comunidade", + "Copy Message": "Copiar Mensagem", + "Delete": "Excluir", + "Delete Message": "Excluir Mensagem", + "Device camera is used to take photos or videos.": "A câmera do dispositivo é usada para tirar fotos ou vídeos.", + "Do you want to send a copy of this message to a moderator for further investigation?": "Deseja enviar uma cópia desta mensagem para um moderador para investigação adicional?", + "Edit Message": "Editar Mensagem", + "Edited": "Editado", + "Editing Message": "Editando Mensagem", + "Emoji matching": "Correspondência de Emoji", + "Empty message...": "Mensagem vazia...", + "Error loading": "Erro ao carregar", + "Error loading channel list...": "Erro ao carregar lista de canais...", + "Error loading messages for this channel...": "Erro ao carregar mensagens para este canal...", + "Error while loading, please reload/refresh": "Erro ao carregar, por favor recarregue/atualize", + "File is too large: {{ size }}, maximum upload size is {{ limit }}": "O arquivo é muito grande: {{ size }}, o tamanho máximo de upload é {{ limit }}", + "File type not supported": "Tipo de arquivo não suportado", + "Flag": "Reportar", + "Flag Message": "Reportar Mensagem", + "Flag action failed either due to a network issue or the message is already flagged": "A ação para reportar a mensagem falhou devido a um problema de rede ou a mensagem já foi reportada.", + "Hold to start recording.": "Mantenha pressionado para começar a gravar.", + "How about sending your first message to a friend?": "Que tal enviar sua primeira mensagem para um amigo?", + "Instant Commands": "Comandos Instantâneos", + "Let's start chatting!": "Vamos começar a conversar!", + "Links are disabled": "Links estão desabilitados", + "Loading channels...": "Carregando canais...", + "Loading messages...": "Carregando mensagens...", + "Loading...": "Carregando...", + "Message Reactions": "Reações à Mensagem", + "Message deleted": "Mensagem excluída", + "Message flagged": "Mensagem sinalizada", + "Mute User": "Silenciar Usuário", + "No chats here yet…": "Ainda não há chats aqui...", + "Not supported": "Não suportado", + "Nothing yet...": "Nada ainda...", + "Ok": "Ok", + "Only visible to you": "Apenas visível para você", + "Open Settings": "Abrir Configurações", + "Photo": "Foto", + "Photos and Videos": "Fotos e Vídeos", + "Pin to Conversation": "Fixar na Conversa", + "Pinned by": "Fixado por", + "Please allow Audio permissions in settings.": "Por favor, permita as permissões de áudio nas configurações.", + "Please enable access to your photos and videos so you can share them.": "Por favor, habilite o acesso às suas fotos e vídeos para poder compartilhá-los.", + "Please select a channel first": "Por favor, selecione um canal primeiro", + "Reconnecting...": "Reconectando...", + "Reply": "Responder", + "Reply to Message": "Responder à Mensagem", + "Resend": "Reenviar", + "Search GIFs": "Pesquisar GIFs", + "Select More Photos": "Selecionar Mais Fotos", + "Send Anyway": "Enviar de qualquer maneira", + "Send a message": "Enviar uma mensagem", + "Sending links is not allowed in this conversation": "Não é permitido enviar links nesta conversa", + "Slow mode ON": "Modo Lento ATIVADO", + "The message has been reported to a moderator.": "A mensagem foi relatada a um moderador.", + "Thread Reply": "Respostas de Tópico", + "Unblock User": "Desbloquear Usuário", + "Unknown User": "Usuário Desconhecido", + "Unmute User": "Remover usuário do modo silencioso", + "Unpin from Conversation": "Desmarcar como fixado na conversa", + "Unread Messages": "Mensagens não lidas", + "Video": "Vídeo", + "You": "Você", + "You can't send messages in this channel": "Você não pode enviar mensagens neste canal", + "{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "{{ firstUser }} e mais {{ nonSelfUserLength }} pessoa(s) estão digitando", + "{{ index }} of {{ photoLength }}": "{{ index }} de {{ photoLength }}", + "{{ replyCount }} Replies": "{{ replyCount }} Respostas", + "{{ replyCount }} Thread Replies": "{{ replyCount }} Respostas de Thread", + "{{ user }} is typing": "{{ user }} está digitando", + "🏙 Attachment...": "🏙 Anexo..." +} From 43ffc795b69e1edc48258218ee8090f0f80970a8 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:31:00 +0530 Subject: [PATCH 20/25] Delete package/src/i18n/pt-BR.json --- package/src/i18n/pt-BR.json | 83 ------------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 package/src/i18n/pt-BR.json diff --git a/package/src/i18n/pt-BR.json b/package/src/i18n/pt-BR.json deleted file mode 100644 index 4c643afc46..0000000000 --- a/package/src/i18n/pt-BR.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "1 Reply": "1 Resposta", - "1 Thread Reply": "1 Resposta de Thread", - "Allow access to your Gallery": "Permitir acesso à sua Galeria", - "Allow camera access in device settings": "Permitir acesso à câmera nas configurações do dispositivo", - "Also send to channel": "Também enviar para o canal", - "Are you sure you want to permanently delete this message?": "Tem certeza de que deseja excluir esta mensagem permanentemente?", - "Are you sure?": "Tem certeza?", - "Block User": "Bloquear Usuário", - "Cancel": "Cancelar", - "Cannot Flag Message": "Não é possível reportar a mensagem", - "Consider how your comment might make others feel and be sure to follow our Community Guidelines": "Considere como seu comentário pode fazer os outros se sentirem e certifique-se de seguir nossas Diretrizes da Comunidade", - "Copy Message": "Copiar Mensagem", - "Delete": "Excluir", - "Delete Message": "Excluir Mensagem", - "Device camera is used to take photos or videos.": "A câmera do dispositivo é usada para tirar fotos ou vídeos.", - "Do you want to send a copy of this message to a moderator for further investigation?": "Deseja enviar uma cópia desta mensagem para um moderador para investigação adicional?", - "Edit Message": "Editar Mensagem", - "Edited": "Editado", - "Editing Message": "Editando Mensagem", - "Emoji matching": "Correspondência de Emoji", - "Empty message...": "Mensagem vazia...", - "Error loading": "Erro ao carregar", - "Error loading channel list...": "Erro ao carregar lista de canais...", - "Error loading messages for this channel...": "Erro ao carregar mensagens para este canal...", - "Error while loading, please reload/refresh": "Erro ao carregar, por favor recarregue/atualize", - "File is too large: {{ size }}, maximum upload size is {{ limit }}": "O arquivo é muito grande: {{ size }}, o tamanho máximo de upload é {{ limit }}", - "File type not supported": "Tipo de arquivo não suportado", - "Flag": "Reportar", - "Flag Message": "Reportar Mensagem", - "Flag action failed either due to a network issue or the message is already flagged": "A ação para reportar a mensagem falhou devido a um problema de rede ou a mensagem já foi reportada.", - "Hold to start recording.": "Mantenha pressionado para começar a gravar.", - "How about sending your first message to a friend?": "Que tal enviar sua primeira mensagem para um amigo?", - "Instant Commands": "Comandos Instantâneos", - "Let's start chatting!": "Vamos começar a conversar!", - "Links are disabled": "Links estão desabilitados", - "Loading channels...": "Carregando canais...", - "Loading messages...": "Carregando mensagens...", - "Loading...": "Carregando...", - "Message Reactions": "Reações à Mensagem", - "Message deleted": "Mensagem excluída", - "Message flagged": "Mensagem sinalizada", - "Mute User": "Silenciar Usuário", - "No chats here yet…": "Ainda não há chats aqui...", - "Not supported": "Não suportado", - "Nothing yet...": "Nada ainda...", - "Ok": "Ok", - "Only visible to you": "Apenas visível para você", - "Open Settings": "Abrir Configurações", - "Photo": "Foto", - "Photos and Videos": "Fotos e Vídeos", - "Pin to Conversation": "Fixar na Conversa", - "Pinned by": "Fixado por", - "Please allow Audio permissions in settings.": "Por favor, permita as permissões de áudio nas configurações.", - "Please enable access to your photos and videos so you can share them.": "Por favor, habilite o acesso às suas fotos e vídeos para poder compartilhá-los.", - "Please select a channel first": "Por favor, selecione um canal primeiro", - "Reconnecting...": "Reconectando...", - "Reply": "Responder", - "Reply to Message": "Responder à Mensagem", - "Resend": "Reenviar", - "Search GIFs": "Pesquisar GIFs", - "Select More Photos": "Selecionar Mais Fotos", - "Send Anyway": "Enviar de qualquer maneira", - "Send a message": "Enviar uma mensagem", - "Sending links is not allowed in this conversation": "Não é permitido enviar links nesta conversa", - "Slow mode ON": "Modo Lento ATIVADO", - "The message has been reported to a moderator.": "A mensagem foi relatada a um moderador.", - "Thread Reply": "Respostas de Tópico", - "Unblock User": "Desbloquear Usuário", - "Unknown User": "Usuário Desconhecido", - "Unmute User": "Remover usuário do modo silencioso", - "Unpin from Conversation": "Desmarcar como fixado na conversa", - "Unread Messages": "Mensagens não lidas", - "Video": "Vídeo", - "You": "Você", - "You can't send messages in this channel": "Você não pode enviar mensagens neste canal", - "{{ firstUser }} and {{ nonSelfUserLength }} more are typing": "{{ firstUser }} e mais {{ nonSelfUserLength }} pessoa(s) estão digitando", - "{{ index }} of {{ photoLength }}": "{{ index }} de {{ photoLength }}", - "{{ replyCount }} Replies": "{{ replyCount }} Respostas", - "{{ replyCount }} Thread Replies": "{{ replyCount }} Respostas de Thread", - "{{ user }} is typing": "{{ user }} está digitando", - "🏙 Attachment...": "🏙 Anexo..." -} From dded19cc8defba5e5c4bc73b61aec166fd6905f6 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:34:02 +0530 Subject: [PATCH 21/25] debug commit --- package/bin/validate-translations.js | 2 +- package/src/utils/Streami18n.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/bin/validate-translations.js b/package/bin/validate-translations.js index 0f4dedfcbb..2ac9d3225b 100644 --- a/package/bin/validate-translations.js +++ b/package/bin/validate-translations.js @@ -15,7 +15,7 @@ fs.readdir(directoryPath, function (err, files) { if (file.split('.').reverse()[0] !== 'json') return; // Do whatever you want to do with the file const data = require(i18nDirectoryRelativePath + file); - if (file === 'pt-BR.json') { + if (file === 'pt-br.json') { console.log(data); } const keys = Object.keys(data); diff --git a/package/src/utils/Streami18n.ts b/package/src/utils/Streami18n.ts index 5a78fefec4..ae8f56cc69 100644 --- a/package/src/utils/Streami18n.ts +++ b/package/src/utils/Streami18n.ts @@ -18,7 +18,7 @@ import itTranslations from '../i18n/it.json'; import jaTranslations from '../i18n/ja.json'; import koTranslations from '../i18n/ko.json'; import nlTranslations from '../i18n/nl.json'; -import ptBRTranslations from '../i18n/pt-BR.json'; +import ptBRTranslations from '../i18n/pt-br.json'; import ruTranslations from '../i18n/ru.json'; import trTranslations from '../i18n/tr.json'; From b82ce7a6fb35ff02a186140a653d4c2952b30b25 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Sun, 16 Jun 2024 12:38:36 +0530 Subject: [PATCH 22/25] debug commit --- package/bin/validate-translations.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/package/bin/validate-translations.js b/package/bin/validate-translations.js index 2ac9d3225b..193f8f60a7 100644 --- a/package/bin/validate-translations.js +++ b/package/bin/validate-translations.js @@ -15,9 +15,6 @@ fs.readdir(directoryPath, function (err, files) { if (file.split('.').reverse()[0] !== 'json') return; // Do whatever you want to do with the file const data = require(i18nDirectoryRelativePath + file); - if (file === 'pt-br.json') { - console.log(data); - } const keys = Object.keys(data); keys.forEach((key) => { if (!data[key] || data[key] === '') { From be213b21d27a0f90f33a8fed795f8a7933b2be33 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Mon, 17 Jun 2024 10:48:30 +0530 Subject: [PATCH 23/25] set keepRemoved true --- package/i18next-parser.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/package/i18next-parser.config.js b/package/i18next-parser.config.js index 1ecb57816d..cd603c4b98 100644 --- a/package/i18next-parser.config.js +++ b/package/i18next-parser.config.js @@ -3,6 +3,7 @@ module.exports = { createOldCatalogs: false, input: ['./src/**/*.{tsx,ts}'], + keepRemoved: true, // Dymanic keys are failed to be parsed so `keepRemoved` is set to `true` - https://github.com/i18next/i18next-parser?tab=readme-ov-file#caveats keySeparator: false, locales: ['en', 'es', 'fr', 'he', 'hi', 'it', 'ja', 'ko', 'nl', 'pt-br', 'ru', 'tr'], namespaceSeparator: false, From 61b3f267ad9d7462b5dc2ca90c4c9506ae1c9541 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Mon, 17 Jun 2024 11:32:12 +0530 Subject: [PATCH 24/25] fix: build config --- package/src/utils/__tests__/Streami18n.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/package/src/utils/__tests__/Streami18n.test.js b/package/src/utils/__tests__/Streami18n.test.js index 9300f1d654..2a051ced68 100644 --- a/package/src/utils/__tests__/Streami18n.test.js +++ b/package/src/utils/__tests__/Streami18n.test.js @@ -1,3 +1,4 @@ +/* eslint-disable */ import { default as Dayjs } from 'dayjs'; import 'dayjs/locale/nl'; import localeData from 'dayjs/plugin/localeData'; From 86a792b71ae88f5e2741dae29a3e8bd9765e4aa5 Mon Sep 17 00:00:00 2001 From: Khushal Agarwal Date: Mon, 17 Jun 2024 11:32:54 +0530 Subject: [PATCH 25/25] fix: build config --- package/src/utils/__tests__/Streami18n.test.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package/src/utils/__tests__/Streami18n.test.js b/package/src/utils/__tests__/Streami18n.test.js index 2a051ced68..f84f40599d 100644 --- a/package/src/utils/__tests__/Streami18n.test.js +++ b/package/src/utils/__tests__/Streami18n.test.js @@ -1,4 +1,3 @@ -/* eslint-disable */ import { default as Dayjs } from 'dayjs'; import 'dayjs/locale/nl'; import localeData from 'dayjs/plugin/localeData'; @@ -191,7 +190,7 @@ describe('formatters property', () => { }); it('allows to override the default timestampFormatter', async () => { const i18n = new Streami18n({ - formatters: { timestampFormatter: (s) => () => 'custom' }, + formatters: { timestampFormatter: () => () => 'custom' }, translationsForLanguage: { abc: '{{ value | timestampFormatter }}' }, }); await i18n.init(); @@ -199,7 +198,7 @@ describe('formatters property', () => { }); it('allows to add new custom formatter', async () => { const i18n = new Streami18n({ - formatters: { customFormatter: (s) => () => 'custom' }, + formatters: { customFormatter: () => () => 'custom' }, translationsForLanguage: { abc: '{{ value | customFormatter }}' }, }); await i18n.init();