mirror of
https://github.com/h3poteto/whalebird-desktop
synced 2025-02-02 02:16:46 +01:00
Setup i18n
This commit is contained in:
parent
5fd257dc7a
commit
0375e02d93
25
locales/en/translation.json
Normal file
25
locales/en/translation.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"timeline": {
|
||||
"home": "Home",
|
||||
"notifications": "Notifications",
|
||||
"local": "Local",
|
||||
"public": "Public",
|
||||
"search": "Search",
|
||||
"status": {
|
||||
"boosted": "{user} boosted",
|
||||
"poll": {
|
||||
"refresh": "Refresh",
|
||||
"vote": "Vote",
|
||||
"peolpe": "{num} people",
|
||||
"closed": "Closed"
|
||||
}
|
||||
}
|
||||
},
|
||||
"accounts": {
|
||||
"new": {
|
||||
"title": "Add account",
|
||||
"sign_in": "Sign in",
|
||||
"authorize": "Authorize"
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
"flowbite": "^2.0.0",
|
||||
"flowbite-react": "^0.6.4",
|
||||
"megalodon": "^9.1.1",
|
||||
"react-intl": "^6.5.1",
|
||||
"react-virtuoso": "^4.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -2,6 +2,7 @@ import { Label, Modal, TextInput, Button } from 'flowbite-react'
|
||||
import generator, { MegalodonInterface, detector } from 'megalodon'
|
||||
import { useState } from 'react'
|
||||
import { db } from '@/db'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
|
||||
type NewProps = {
|
||||
opened: boolean
|
||||
@ -63,7 +64,9 @@ export default function New(props: NewProps) {
|
||||
return (
|
||||
<>
|
||||
<Modal dismissible={false} show={props.opened} onClose={close}>
|
||||
<Modal.Header>Add account</Modal.Header>
|
||||
<Modal.Header>
|
||||
<FormattedMessage id="accounts.new.title" />
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<form className="flex max-w-md flex-col gap-2">
|
||||
{sns === null && (
|
||||
@ -72,7 +75,9 @@ export default function New(props: NewProps) {
|
||||
<Label htmlFor="domain" value="Domain" />
|
||||
</div>
|
||||
<TextInput id="domain" placeholder="mastodon.social" required type="text" />
|
||||
<Button onClick={checkDomain}>Sign In</Button>{' '}
|
||||
<Button onClick={checkDomain}>
|
||||
<FormattedMessage id="accounts.new.sign_in" />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{sns && (
|
||||
@ -81,7 +86,9 @@ export default function New(props: NewProps) {
|
||||
<Label htmlFor="authorization" value="Authorization Code" />
|
||||
</div>
|
||||
<TextInput id="authorization" required type="text" />
|
||||
<Button onClick={authorize}>Authorize</Button>{' '}
|
||||
<Button onClick={authorize}>
|
||||
<FormattedMessage id="accounts.new.authorize" />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</form>
|
||||
|
@ -2,6 +2,7 @@ import { Account, db } from '@/db'
|
||||
import { CustomFlowbiteTheme, Flowbite, Sidebar } from 'flowbite-react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
type LayoutProps = {
|
||||
children: React.ReactNode
|
||||
@ -21,6 +22,7 @@ const customTheme: CustomFlowbiteTheme = {
|
||||
|
||||
export default function Layout({ children }: LayoutProps) {
|
||||
const router = useRouter()
|
||||
const { formatMessage } = useIntl()
|
||||
|
||||
const [account, setAccount] = useState<Account | null>(null)
|
||||
useEffect(() => {
|
||||
@ -37,22 +39,22 @@ export default function Layout({ children }: LayoutProps) {
|
||||
const pages = [
|
||||
{
|
||||
id: 'home',
|
||||
title: 'Home',
|
||||
title: formatMessage({ id: 'timeline.home' }),
|
||||
path: `/accounts/${router.query.id}/home`
|
||||
},
|
||||
{
|
||||
id: 'notifications',
|
||||
title: 'Notifications',
|
||||
title: formatMessage({ id: 'timeline.notifications' }),
|
||||
path: `/accounts/${router.query.id}/notifications`
|
||||
},
|
||||
{
|
||||
id: 'local',
|
||||
title: 'Local',
|
||||
title: formatMessage({ id: 'timeline.local' }),
|
||||
path: `/accounts/${router.query.id}/local`
|
||||
},
|
||||
{
|
||||
id: 'public',
|
||||
title: 'Public',
|
||||
title: formatMessage({ id: 'timeline.public' }),
|
||||
path: `/accounts/${router.query.id}/public`
|
||||
}
|
||||
]
|
||||
|
@ -4,6 +4,7 @@ import { Entity, MegalodonInterface } from 'megalodon'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Virtuoso } from 'react-virtuoso'
|
||||
import Status from './status/Status'
|
||||
import { FormattedMessage, useIntl } from 'react-intl'
|
||||
|
||||
type Props = {
|
||||
timeline: string
|
||||
@ -12,6 +13,7 @@ type Props = {
|
||||
}
|
||||
export default function Timeline(props: Props) {
|
||||
const [statuses, setStatuses] = useState<Array<Entity.Status>>([])
|
||||
const { formatMessage } = useIntl()
|
||||
|
||||
useEffect(() => {
|
||||
const f = async () => {
|
||||
@ -65,10 +67,12 @@ export default function Timeline(props: Props) {
|
||||
return (
|
||||
<section className="h-full w-full">
|
||||
<div className="w-full bg-blue-950 text-blue-100 p-2 flex justify-between">
|
||||
<div className="text-lg font-bold">{props.timeline}</div>
|
||||
<div className="text-lg font-bold">
|
||||
<FormattedMessage id={`timeline.${props.timeline}`} />
|
||||
</div>
|
||||
<div className="w-64 text-xs">
|
||||
<form>
|
||||
<TextInput type="text" placeholder="search" disabled sizing="sm" />
|
||||
<TextInput type="text" placeholder={formatMessage({ id: 'timeline.search' })} disabled sizing="sm" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { Progress, Button, Radio, Label, Checkbox } from 'flowbite-react'
|
||||
import { Entity, MegalodonInterface } from 'megalodon'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
|
||||
type Props = {
|
||||
poll: Entity.Poll
|
||||
@ -41,9 +42,11 @@ function SimplePoll(props: Props) {
|
||||
))}
|
||||
<div className="flex gap-2 items-center mt-2">
|
||||
<Button outline={true} size="xs" onClick={vote}>
|
||||
Vote
|
||||
<FormattedMessage id="timeline.status.poll.vote" />
|
||||
</Button>
|
||||
<div>{props.poll.votes_count} people</div>
|
||||
<div>
|
||||
<FormattedMessage id="timeline.status.poll.people" values={{ num: props.poll.votes_count }} />
|
||||
</div>
|
||||
<div>
|
||||
<time dateTime={props.poll.expires_at}>{dayjs(props.poll.expires_at).format('YYYY-MM-DD HH:mm:ss')}</time>
|
||||
</div>
|
||||
@ -77,9 +80,11 @@ function MultiplePoll(props: Props) {
|
||||
))}
|
||||
<div className="flex gap-2 items-center mt-2">
|
||||
<Button outline={true} size="xs" onClick={vote}>
|
||||
Vote
|
||||
<FormattedMessage id="timeline.status.poll.vote" />
|
||||
</Button>
|
||||
<div>{props.poll.votes_count} people</div>
|
||||
<div>
|
||||
<FormattedMessage id="timeline.status.poll.people" values={{ num: props.poll.votes_count }} />
|
||||
</div>
|
||||
<div>
|
||||
<time dateTime={props.poll.expires_at}>{dayjs(props.poll.expires_at).format('YYYY-MM-DD HH:mm:ss')}</time>
|
||||
</div>
|
||||
@ -100,11 +105,15 @@ function PollResult(props: Props) {
|
||||
))}
|
||||
<div className="flex gap-2 items-center mt-2">
|
||||
<Button outline={true} size="xs" onClick={props.onRefresh}>
|
||||
Refresh
|
||||
<FormattedMessage id="timeline.status.poll.refresh" />
|
||||
</Button>
|
||||
<div>{props.poll.votes_count} people</div>
|
||||
<div>
|
||||
<FormattedMessage id="timeline.status.poll.people" values={{ num: props.poll.votes_count }} />
|
||||
</div>
|
||||
{props.poll.expired ? (
|
||||
<div>Closed</div>
|
||||
<div>
|
||||
<FormattedMessage id="timeline.status.poll.closed" />
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<time dateTime={props.poll.expires_at}>{dayjs(props.poll.expires_at).format('YYYY-MM-DD HH:mm:ss')}</time>
|
||||
|
@ -6,6 +6,7 @@ import Media from './Media'
|
||||
import emojify from '@/utils/emojify'
|
||||
import Card from './Card'
|
||||
import Poll from './Poll'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
|
||||
type Props = {
|
||||
status: Entity.Status
|
||||
@ -66,7 +67,9 @@ const rebloggedHeader = (status: Entity.Status) => {
|
||||
<div className="grid justify-items-end pr-2" style={{ width: '56px' }}>
|
||||
<Avatar img={status.account.avatar} size="xs" />
|
||||
</div>
|
||||
<div style={{ width: 'calc(100% - 56px)' }}>{status.account.username} boosted</div>
|
||||
<div style={{ width: 'calc(100% - 56px)' }}>
|
||||
<FormattedMessage id="timeline.status.boosted" values={{ user: status.account.username }} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
|
@ -2,13 +2,16 @@ import type { AppProps } from 'next/app'
|
||||
import '../app.css'
|
||||
import AccountLayout from '@/components/layouts/account'
|
||||
import TimelineLayout from '@/components/layouts/timelines'
|
||||
import { IntlProviderWrapper } from '@/utils/i18n'
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<AccountLayout>
|
||||
<TimelineLayout>
|
||||
<Component {...pageProps} />
|
||||
</TimelineLayout>
|
||||
</AccountLayout>
|
||||
<IntlProviderWrapper>
|
||||
<AccountLayout>
|
||||
<TimelineLayout>
|
||||
<Component {...pageProps} />
|
||||
</TimelineLayout>
|
||||
</AccountLayout>
|
||||
</IntlProviderWrapper>
|
||||
)
|
||||
}
|
||||
|
14
renderer/utils/flattenMessage.ts
Normal file
14
renderer/utils/flattenMessage.ts
Normal file
@ -0,0 +1,14 @@
|
||||
export function flattenMessages(nestedMessages: { [key: string]: any }, prefix = ''): { [key: string]: string } {
|
||||
return Object.keys(nestedMessages).reduce((messages, key) => {
|
||||
const value = nestedMessages[key]
|
||||
const prefixedKey = prefix ? `${prefix}.${key}` : key
|
||||
|
||||
if (typeof value === 'string') {
|
||||
messages[prefixedKey] = value
|
||||
} else {
|
||||
Object.assign(messages, flattenMessages(value, prefixedKey))
|
||||
}
|
||||
|
||||
return messages
|
||||
}, {})
|
||||
}
|
37
renderer/utils/i18n.tsx
Normal file
37
renderer/utils/i18n.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import en from '../../locales/en/translation.json'
|
||||
import { flattenMessages } from './flattenMessage'
|
||||
import { createContext, useState } from 'react'
|
||||
import { IntlProvider } from 'react-intl'
|
||||
|
||||
export type localeType = 'en' | 'ja' | 'it' | 'pt-BR' | 'fr'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
interface Lang {
|
||||
switchLang(lang: string): void
|
||||
}
|
||||
|
||||
export const Context = createContext<Lang>({} as Lang)
|
||||
|
||||
export const IntlProviderWrapper: React.FC<Props> = props => {
|
||||
const langs = [{ locale: 'en', messages: flattenMessages(en) }]
|
||||
const [lang, setLang] = useState(langs[0])
|
||||
|
||||
const switchLang = (locale: string) => {
|
||||
const changeLang = langs.find(lang => lang.locale === locale)
|
||||
if (changeLang == null) {
|
||||
return
|
||||
}
|
||||
setLang(changeLang)
|
||||
}
|
||||
|
||||
return (
|
||||
<Context.Provider value={{ switchLang }}>
|
||||
<IntlProvider {...lang} defaultLocale="en" fallbackOnEmptyString={true}>
|
||||
{props.children}
|
||||
</IntlProvider>
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
125
yarn.lock
125
yarn.lock
@ -1106,6 +1106,76 @@
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.6.tgz#22958c042e10b67463997bd6ea7115fe28cbcaf9"
|
||||
integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==
|
||||
|
||||
"@formatjs/ecma402-abstract@1.17.2":
|
||||
version "1.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.2.tgz#d197c6e26b9fd96ff7ba3b3a0cc2f25f1f2dcac3"
|
||||
integrity sha512-k2mTh0m+IV1HRdU0xXM617tSQTi53tVR2muvYOsBeYcUgEAyxV1FOC7Qj279th3fBVQ+Dj6muvNJZcHSPNdbKg==
|
||||
dependencies:
|
||||
"@formatjs/intl-localematcher" "0.4.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/fast-memoize@2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz#33bd616d2e486c3e8ef4e68c99648c196887802b"
|
||||
integrity sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/icu-messageformat-parser@2.7.0":
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.0.tgz#9b13f2710a3b4efddfeb544480f684f27a53483b"
|
||||
integrity sha512-7uqC4C2RqOaBQtcjqXsSpGRYVn+ckjhNga5T/otFh6MgxRrCJQqvjfbrGLpX1Lcbxdm5WH3Z2WZqt1+Tm/cn/Q==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
"@formatjs/icu-skeleton-parser" "1.6.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/icu-skeleton-parser@1.6.2":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.6.2.tgz#00303034dc08583973c8aa67b96534c49c0bad8d"
|
||||
integrity sha512-VtB9Slo4ZL6QgtDFJ8Injvscf0xiDd4bIV93SOJTBjUF4xe2nAWOoSjLEtqIG+hlIs1sNrVKAaFo3nuTI4r5ZA==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/intl-displaynames@6.6.1":
|
||||
version "6.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-6.6.1.tgz#2099dbd0d3dffba3176d7b470c73bdd578850d76"
|
||||
integrity sha512-TIPaDu0SlwJUXlIyeSL9052jrUC4QviLnvUEJ53Ldc3Q4nZJnT2wD8NHIroTOYX9lgp5m3BeTlhpRcsnuExDkA==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
"@formatjs/intl-localematcher" "0.4.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/intl-listformat@7.5.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-7.5.0.tgz#dbccf2e0f07792aa1c273702796bdad061dc27ae"
|
||||
integrity sha512-n9FsXGl1T2ZbX6wSyrzCDJHrbJR0YJ9ZNsAqUvHXfbY3nsOmGnSTf5+bkuIp1Xiywu7m1X1Pfm/Ngp/yK1H84A==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
"@formatjs/intl-localematcher" "0.4.2"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/intl-localematcher@0.4.2":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.4.2.tgz#7e6e596dbaf2f0c5a7c22da5a01d5c55f4c37e9a"
|
||||
integrity sha512-BGdtJFmaNJy5An/Zan4OId/yR9Ih1OojFjcduX/xOvq798OgWSyDtd6Qd5jqJXwJs1ipe4Fxu9+cshic5Ox2tA==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@formatjs/intl@2.9.5":
|
||||
version "2.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.9.5.tgz#30087e97db940038ede523439c2fb2bdf84989dd"
|
||||
integrity sha512-WEdEv8Jf2nKBErTK4MJ2xCesUJVHH9iunXzfHzZo4tnn2NSj48g04FNH9w17XDpEbj9KEM39fLkwBz7ay/ErPQ==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
"@formatjs/fast-memoize" "2.2.0"
|
||||
"@formatjs/icu-messageformat-parser" "2.7.0"
|
||||
"@formatjs/intl-displaynames" "6.6.1"
|
||||
"@formatjs/intl-listformat" "7.5.0"
|
||||
intl-messageformat "10.5.4"
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
|
||||
@ -1328,6 +1398,14 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/hoist-non-react-statics@^3.3.1":
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.4.tgz#cc477ce0283bb9d19ea0cbfa2941fe2c8493a1be"
|
||||
integrity sha512-ZchYkbieA+7tnxwX/SCBySx9WwvWR8TaP5tb2jRAzwvLb/rWchGw3v0w3pqUbUvj0GCwW2Xz/AVPSk6kUGctXQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
"@types/http-cache-semantics@*":
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#a3ff232bf7d5c55f38e4e45693eda2ebb545794d"
|
||||
@ -1377,6 +1455,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d"
|
||||
integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==
|
||||
|
||||
"@types/react@*", "@types/react@16 || 17 || 18":
|
||||
version "18.2.34"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.34.tgz#aed20f19473721ba328feb99d1ec3307ebc1a8dd"
|
||||
integrity sha512-U6eW/alrRk37FU/MS2RYMjx0Va2JGIVXELTODaTIYgvWGCV4Y4TfTUzG8DdmpDNIT0Xpj/R7GfyHOJJrDttcvg==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/react@^18.0.26":
|
||||
version "18.2.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.33.tgz#055356243dc4350a9ee6c6a2c07c5cae12e38877"
|
||||
@ -2814,6 +2901,13 @@ hasown@^2.0.0:
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
hosted-git-info@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
|
||||
@ -2889,6 +2983,16 @@ inherits@2:
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
intl-messageformat@10.5.4:
|
||||
version "10.5.4"
|
||||
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.4.tgz#7b212b083f1b354d7e282518e78057e025134af9"
|
||||
integrity sha512-z+hrFdiJ/heRYlzegrdFYqU1m/KOMOVMqNilIArj+PbsuU8TNE7v4TWdQgSoxlxbT4AcZH3Op3/Fu15QTp+W1w==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
"@formatjs/fast-memoize" "2.2.0"
|
||||
"@formatjs/icu-messageformat-parser" "2.7.0"
|
||||
tslib "^2.4.0"
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
@ -3664,6 +3768,27 @@ react-indiana-drag-scroll@^2.2.0:
|
||||
debounce "^1.2.0"
|
||||
easy-bem "^1.1.1"
|
||||
|
||||
react-intl@^6.5.1:
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.5.1.tgz#c44f67798e25b2778b2091563e004f54e8dc911b"
|
||||
integrity sha512-mKxfH7GV5P4dJcQmbq/xU8FVBl//xRudXgS5r1Gt62NEr+T8pnzQZZ2th1jP5BQ+Ne/3kS3uYpFcynj5KyXVhg==
|
||||
dependencies:
|
||||
"@formatjs/ecma402-abstract" "1.17.2"
|
||||
"@formatjs/icu-messageformat-parser" "2.7.0"
|
||||
"@formatjs/intl" "2.9.5"
|
||||
"@formatjs/intl-displaynames" "6.6.1"
|
||||
"@formatjs/intl-listformat" "7.5.0"
|
||||
"@types/hoist-non-react-statics" "^3.3.1"
|
||||
"@types/react" "16 || 17 || 18"
|
||||
hoist-non-react-statics "^3.3.2"
|
||||
intl-messageformat "10.5.4"
|
||||
tslib "^2.4.0"
|
||||
|
||||
react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-virtuoso@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.6.2.tgz#74b59ebe3260e1f73e92340ffec84a6853285a12"
|
||||
|
Loading…
x
Reference in New Issue
Block a user