mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
First pass at configuring localization
This commit is contained in:
parent
509774e5ae
commit
1c8b9d0728
@ -1,6 +1,7 @@
|
||||
import { Button } from 'antd';
|
||||
import { FC } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useTranslation } from 'next-export-i18n';
|
||||
import styles from './ActionButton/ActionButton.module.scss';
|
||||
|
||||
// Lazy loaded components
|
||||
@ -14,14 +15,18 @@ export type NotifyButtonProps = {
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export const NotifyButton: FC<NotifyButtonProps> = ({ onClick, text }) => (
|
||||
<Button
|
||||
type="primary"
|
||||
className={styles.button}
|
||||
icon={<BellFilled />}
|
||||
onClick={onClick}
|
||||
id="notify-button"
|
||||
>
|
||||
{text || 'Notify'}
|
||||
</Button>
|
||||
);
|
||||
export const NotifyButton: FC<NotifyButtonProps> = ({ onClick, text }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="primary"
|
||||
className={styles.button}
|
||||
icon={<BellFilled />}
|
||||
onClick={onClick}
|
||||
id="notify-button"
|
||||
>
|
||||
{text || t('Notify')}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useTranslation } from 'next-export-i18n';
|
||||
import styles from './Footer.module.scss';
|
||||
import { ServerStatus } from '../../../interfaces/server-status.model';
|
||||
import { serverStatusState } from '../../stores/ClientConfigStore';
|
||||
@ -7,20 +8,21 @@ import { serverStatusState } from '../../stores/ClientConfigStore';
|
||||
export const Footer: FC = () => {
|
||||
const clientStatus = useRecoilValue<ServerStatus>(serverStatusState);
|
||||
const { versionNumber } = clientStatus;
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<footer className={styles.footer} id="footer">
|
||||
<span>
|
||||
Powered by <a href="https://owncast.online">Owncast v{versionNumber}</a>
|
||||
{t('Powered by Owncast')} <a href="https://owncast.online">v{versionNumber}</a>
|
||||
</span>
|
||||
<span className={styles.links}>
|
||||
<a href="https://owncast.online/docs" target="_blank" rel="noreferrer">
|
||||
Documentation
|
||||
{t('Documentation')}
|
||||
</a>
|
||||
<a href="https://owncast.online/help" target="_blank" rel="noreferrer">
|
||||
Contribute
|
||||
{t('Contribute')}
|
||||
</a>
|
||||
<a href="https://github.com/owncast/owncast" target="_blank" rel="noreferrer">
|
||||
Source
|
||||
{t('Source')}
|
||||
</a>
|
||||
</span>
|
||||
</footer>
|
||||
|
@ -3,6 +3,7 @@ import { FC, useEffect, useState } from 'react';
|
||||
import cn from 'classnames';
|
||||
import dynamic from 'next/dynamic';
|
||||
import Link from 'next/link';
|
||||
import { useTranslation } from 'next-export-i18n';
|
||||
import styles from './Header.module.scss';
|
||||
|
||||
// Lazy loaded components
|
||||
@ -23,6 +24,7 @@ export type HeaderComponentProps = {
|
||||
|
||||
export const Header: FC<HeaderComponentProps> = ({ name, chatAvailable, chatDisabled, online }) => {
|
||||
const [canHideChat, setCanHideChat] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
setCanHideChat(window.innerWidth >= 768);
|
||||
@ -32,18 +34,18 @@ export const Header: FC<HeaderComponentProps> = ({ name, chatAvailable, chatDisa
|
||||
<header className={cn([`${styles.header}`], 'global-header')}>
|
||||
{online ? (
|
||||
<Link href="#player" className={styles.skipLink}>
|
||||
Skip to player
|
||||
{t('Skip to player')}
|
||||
</Link>
|
||||
) : (
|
||||
<Link href="#offline-message" className={styles.skipLink}>
|
||||
Skip to offline message
|
||||
{t('Skip to offline message')}
|
||||
</Link>
|
||||
)}
|
||||
<Link href="#skip-to-content" className={styles.skipLink}>
|
||||
Skip to page content
|
||||
{t('Skip to page content')}
|
||||
</Link>
|
||||
<Link href="#footer" className={styles.skipLink}>
|
||||
Skip to footer
|
||||
{t('Skip to footer')}
|
||||
</Link>
|
||||
<div className={styles.logo}>
|
||||
<div id="header-logo" className={styles.logoImage}>
|
||||
@ -62,7 +64,7 @@ export const Header: FC<HeaderComponentProps> = ({ name, chatAvailable, chatDisa
|
||||
title="Chat will be available when the stream is live."
|
||||
placement="left"
|
||||
>
|
||||
<span className={styles.chatOfflineText}>Chat is offline</span>
|
||||
<span className={styles.chatOfflineText}>{t('Chat is offline')}</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
</header>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect, FC } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useTranslation } from 'next-export-i18n';
|
||||
import styles from './NotifyReminderPopup.module.scss';
|
||||
import { Popover } from '../Popover/Popover';
|
||||
|
||||
@ -24,6 +25,7 @@ export const NotifyReminderPopup: FC<NotifyReminderPopupProps> = ({
|
||||
}) => {
|
||||
const [openPopup, setOpenPopup] = useState(open);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
setOpenPopup(open);
|
||||
@ -33,7 +35,7 @@ export const NotifyReminderPopup: FC<NotifyReminderPopupProps> = ({
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
const title = <div className={styles.title}>Stay updated!</div>;
|
||||
const title = <div className={styles.title}>{t('Stay updated!')}</div>;
|
||||
|
||||
const popupClicked = e => {
|
||||
e.stopPropagation();
|
||||
@ -56,7 +58,7 @@ export const NotifyReminderPopup: FC<NotifyReminderPopupProps> = ({
|
||||
>
|
||||
<CloseOutlined />
|
||||
</button>
|
||||
<div className={styles.contentbutton}>Click and never miss future streams!</div>
|
||||
<div className={styles.contentbutton}>{t('Click and never miss future streams!')}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { FC } from 'react';
|
||||
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
|
||||
import dynamic from 'next/dynamic';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'next-export-i18n';
|
||||
import styles from './OfflineBanner.module.scss';
|
||||
|
||||
// Lazy loaded components
|
||||
@ -36,13 +37,15 @@ export const OfflineBanner: FC<OfflineBannerProps> = ({
|
||||
onFollowClick,
|
||||
className,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
let text;
|
||||
if (customText) {
|
||||
text = customText;
|
||||
} else if (!customText && notificationsEnabled && fediverseAccount) {
|
||||
text = (
|
||||
<span>
|
||||
This stream is offline. You can{' '}
|
||||
{t('This stream is offline. You can')}{' '}
|
||||
<span role="link" tabIndex={0} className={styles.actionLink} onClick={onNotifyClick}>
|
||||
be notified
|
||||
</span>{' '}
|
||||
@ -56,21 +59,25 @@ export const OfflineBanner: FC<OfflineBannerProps> = ({
|
||||
} else if (!customText && notificationsEnabled) {
|
||||
text = (
|
||||
<span>
|
||||
This stream is offline.{' '}
|
||||
{t('This stream is offline')}.{' '}
|
||||
<span role="link" tabIndex={0} className={styles.actionLink} onClick={onNotifyClick}>
|
||||
Be notified
|
||||
</span>{' '}
|
||||
the next time {streamName} goes live.
|
||||
{t('the next time goes live', { streamer: streamName })}.
|
||||
</span>
|
||||
);
|
||||
} else if (!customText && fediverseAccount) {
|
||||
text = (
|
||||
<span>
|
||||
This stream is offline.{' '}
|
||||
{t('This stream is offline.')}{' '}
|
||||
<span role="link" tabIndex={0} className={styles.actionLink} onClick={onFollowClick}>
|
||||
Follow
|
||||
{t('Follow')}
|
||||
</span>{' '}
|
||||
{fediverseAccount} on the Fediverse to see the next time {streamName} goes live.
|
||||
{t('on the Fediverse to see the next time goes live', {
|
||||
fediverseAccount,
|
||||
streamer: streamName,
|
||||
})}
|
||||
.
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
@ -95,7 +102,7 @@ export const OfflineBanner: FC<OfflineBannerProps> = ({
|
||||
{lastLive && (
|
||||
<div className={styles.lastLiveDate}>
|
||||
<ClockCircleOutlined className={styles.clockIcon} />
|
||||
{`Last live ${formatDistanceToNow(new Date(lastLive))} ago.`}
|
||||
{`${(t('Last live ago'), { timeAgo: formatDistanceToNow(new Date(lastLive)) })}`}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
3
web/crowdin.yml
Normal file
3
web/crowdin.yml
Normal file
@ -0,0 +1,3 @@
|
||||
files:
|
||||
- source: /translations/locales/en-us.po
|
||||
translation: /translations/locales/%locale%.po
|
19
web/i18n/index.js
Normal file
19
web/i18n/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
const en = require('./translations.en.json');
|
||||
const de = require('./translations.de.json');
|
||||
const fr = require('./translations.fr.json');
|
||||
const sp = require('./translations.sp.json');
|
||||
|
||||
const i18n = {
|
||||
translations: {
|
||||
en,
|
||||
de,
|
||||
fr,
|
||||
sp,
|
||||
},
|
||||
defaultLang: 'en',
|
||||
useBrowserDefault: true,
|
||||
// optional property, will default to "query" if not set
|
||||
languageDataStore: 'query' || 'localStorage',
|
||||
};
|
||||
|
||||
module.exports = i18n;
|
19
web/i18n/translations.de.json
Normal file
19
web/i18n/translations.de.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Notify": "Needs \"de\" translation: Notify",
|
||||
"Powered by Owncast": "Needs \"de\" translation: Powered by Owncast",
|
||||
"Documentation": "Needs \"de\" translation: Documentation",
|
||||
"Contribute": "Needs \"de\" translation: Contribute",
|
||||
"Source": "Needs \"de\" translation: Source",
|
||||
"Skip to player": "Needs \"de\" translation: Skip to player",
|
||||
"Skip to offline message": "Needs \"de\" translation: Skip to offline message",
|
||||
"Skip to page content": "Needs \"de\" translation: Skip to page content",
|
||||
"Skip to footer": "Needs \"de\" translation: Skip to footer",
|
||||
"Chat is offline": "Needs \"de\" translation: Chat is offline",
|
||||
"Stay updated!": "Needs \"de\" translation: Stay updated!",
|
||||
"Click and never miss future streams!": "Needs \"de\" translation: Click and never miss future streams!",
|
||||
"This stream is offline": "Needs \"de\" translation: This stream is offline.",
|
||||
"the next time goes live": "Needs \"de\" translation: the next time goes live",
|
||||
"Follow": "Needs \"de\" translation: Follow",
|
||||
"on the Fediverse to see the next time goes live": "Needs \"de\" translation: on the Fediverse to see the next time goes live",
|
||||
"Last live ago": "Needs \"de\" translation: Last live ago"
|
||||
}
|
19
web/i18n/translations.en.json
Normal file
19
web/i18n/translations.en.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Notify": "Needs \"en\" translation: Notify",
|
||||
"Powered by Owncast": "Needs \"en\" translation: Powered by Owncast",
|
||||
"Documentation": "Needs \"en\" translation: Documentation",
|
||||
"Contribute": "Needs \"en\" translation: Contribute",
|
||||
"Source": "Needs \"en\" translation: Source",
|
||||
"Skip to player": "Needs \"en\" translation: Skip to player",
|
||||
"Skip to offline message": "Needs \"en\" translation: Skip to offline message",
|
||||
"Skip to page content": "Needs \"en\" translation: Skip to page content",
|
||||
"Skip to footer": "Needs \"en\" translation: Skip to footer",
|
||||
"Chat is offline": "Needs \"en\" translation: Chat is offline",
|
||||
"Stay updated!": "Needs \"en\" translation: Stay updated!",
|
||||
"Click and never miss future streams!": "Needs \"en\" translation: Click and never miss future streams!",
|
||||
"This stream is offline": "Needs \"en\" translation: This stream is offline.",
|
||||
"the next time goes live": "Needs \"en\" translation: the next time goes live",
|
||||
"Follow": "Needs \"en\" translation: Follow",
|
||||
"on the Fediverse to see the next time goes live": "Needs \"en\" translation: on the Fediverse to see the next time goes live",
|
||||
"Last live ago": "Needs \"en\" translation: Last live ago"
|
||||
}
|
19
web/i18n/translations.es.json
Normal file
19
web/i18n/translations.es.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Notify": "Needs \"es\" translation: Notify",
|
||||
"Powered by Owncast": "Needs \"es\" translation: Powered by Owncast",
|
||||
"Documentation": "Needs \"es\" translation: Documentation",
|
||||
"Contribute": "Needs \"es\" translation: Contribute",
|
||||
"Source": "Needs \"es\" translation: Source",
|
||||
"Skip to player": "Needs \"es\" translation: Skip to player",
|
||||
"Skip to offline message": "Needs \"es\" translation: Skip to offline message",
|
||||
"Skip to page content": "Needs \"es\" translation: Skip to page content",
|
||||
"Skip to footer": "Needs \"es\" translation: Skip to footer",
|
||||
"Chat is offline": "Needs \"es\" translation: Chat is offline",
|
||||
"Stay updated!": "Needs \"es\" translation: Stay updated!",
|
||||
"Click and never miss future streams!": "Needs \"es\" translation: Click and never miss future streams!",
|
||||
"This stream is offline": "Needs \"es\" translation: This stream is offline.",
|
||||
"the next time goes live": "Needs \"es\" translation: the next time goes live",
|
||||
"Follow": "Needs \"es\" translation: Follow",
|
||||
"on the Fediverse to see the next time goes live": "Needs \"es\" translation: on the Fediverse to see the next time goes live",
|
||||
"Last live ago": "Needs \"es\" translation: Last live ago"
|
||||
}
|
19
web/i18n/translations.fr.json
Normal file
19
web/i18n/translations.fr.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Notify": "Needs \"fr\" translation: Notify",
|
||||
"Powered by Owncast": "Needs \"fr\" translation: Powered by Owncast",
|
||||
"Documentation": "Needs \"fr\" translation: Documentation",
|
||||
"Contribute": "Needs \"fr\" translation: Contribute",
|
||||
"Source": "Needs \"fr\" translation: Source",
|
||||
"Skip to player": "Needs \"fr\" translation: Skip to player",
|
||||
"Skip to offline message": "Needs \"fr\" translation: Skip to offline message",
|
||||
"Skip to page content": "Needs \"fr\" translation: Skip to page content",
|
||||
"Skip to footer": "Needs \"fr\" translation: Skip to footer",
|
||||
"Chat is offline": "Needs \"fr\" translation: Chat is offline",
|
||||
"Stay updated!": "Needs \"fr\" translation: Stay updated!",
|
||||
"Click and never miss future streams!": "Needs \"fr\" translation: Click and never miss future streams!",
|
||||
"This stream is offline": "Needs \"fr\" translation: This stream is offline.",
|
||||
"the next time goes live": "Needs \"fr\" translation: the next time goes live",
|
||||
"Follow": "Needs \"fr\" translation: Follow",
|
||||
"on the Fediverse to see the next time goes live": "Needs \"fr\" translation: on the Fediverse to see the next time goes live",
|
||||
"Last live ago": "Needs \"fr\" translation: Last live ago"
|
||||
}
|
19
web/i18n/translations.sp.json
Normal file
19
web/i18n/translations.sp.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Notify": "Needs \"sp\" translation: Notify",
|
||||
"Powered by Owncast": "Needs \"sp\" translation: Powered by Owncast",
|
||||
"Documentation": "Needs \"sp\" translation: Documentation",
|
||||
"Contribute": "Needs \"sp\" translation: Contribute",
|
||||
"Source": "Needs \"sp\" translation: Source",
|
||||
"Skip to player": "Needs \"sp\" translation: Skip to player",
|
||||
"Skip to offline message": "Needs \"sp\" translation: Skip to offline message",
|
||||
"Skip to page content": "Needs \"sp\" translation: Skip to page content",
|
||||
"Skip to footer": "Needs \"sp\" translation: Skip to footer",
|
||||
"Chat is offline": "Needs \"sp\" translation: Chat is offline",
|
||||
"Stay updated!": "Needs \"sp\" translation: Stay updated!",
|
||||
"Click and never miss future streams!": "Needs \"sp\" translation: Click and never miss future streams!",
|
||||
"This stream is offline": "Needs \"sp\" translation: This stream is offline.",
|
||||
"the next time goes live": "Needs \"sp\" translation: the next time goes live",
|
||||
"Follow": "Needs \"sp\" translation: Follow",
|
||||
"on the Fediverse to see the next time goes live": "Needs \"sp\" translation: on the Fediverse to see the next time goes live",
|
||||
"Last live ago": "Needs \"sp\" translation: Last live ago"
|
||||
}
|
113
web/i18next-parser.config.mjs
Normal file
113
web/i18next-parser.config.mjs
Normal file
@ -0,0 +1,113 @@
|
||||
// i18next-parser.config.js
|
||||
|
||||
export default {
|
||||
contextSeparator: '_',
|
||||
// Key separator used in your translation keys
|
||||
|
||||
createOldCatalogs: false,
|
||||
// Save the \_old files
|
||||
|
||||
defaultNamespace: 'translation',
|
||||
// Default namespace used in your i18next config
|
||||
|
||||
defaultValue: function (locale, namespace, key, value) {
|
||||
return `Needs \"${locale}\" translation: ${key}`;
|
||||
}, // Default value to give to keys with no value
|
||||
// You may also specify a function accepting the locale, namespace, key, and value as arguments
|
||||
|
||||
indentation: 2,
|
||||
// Indentation of the catalog files
|
||||
|
||||
keepRemoved: false,
|
||||
// Keep keys from the catalog that are no longer in code
|
||||
// You may either specify a boolean to keep or discard all removed keys.
|
||||
// You may also specify an array of patterns: the keys from the catalog that are no long in the code but match one of the patterns will be kept.
|
||||
// The patterns are applied to the full key including the namespace, the parent keys and the separators.
|
||||
|
||||
keySeparator: '.',
|
||||
// Key separator used in your translation keys
|
||||
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
|
||||
|
||||
// see below for more details
|
||||
lexers: {
|
||||
hbs: ['HandlebarsLexer'],
|
||||
handlebars: ['HandlebarsLexer'],
|
||||
|
||||
htm: ['HTMLLexer'],
|
||||
html: ['HTMLLexer'],
|
||||
|
||||
mjs: ['JavascriptLexer'],
|
||||
js: ['JavascriptLexer'], // if you're writing jsx inside .js files, change this to JsxLexer
|
||||
ts: ['JavascriptLexer'],
|
||||
jsx: ['JsxLexer'],
|
||||
tsx: ['JsxLexer'],
|
||||
|
||||
default: ['JavascriptLexer'],
|
||||
},
|
||||
|
||||
lineEnding: 'auto',
|
||||
// Control the line ending. See options at https://github.com/ryanve/eol
|
||||
|
||||
locales: ['en', 'fr', 'es', 'sp', 'de'],
|
||||
// An array of the locales in your applications
|
||||
|
||||
namespaceSeparator: ':',
|
||||
// Namespace separator used in your translation keys
|
||||
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.
|
||||
|
||||
output: 'i18n/translations.$LOCALE.json',
|
||||
// Supports $LOCALE and $NAMESPACE injection
|
||||
// Supports JSON (.json) and YAML (.yml) file formats
|
||||
// Where to write the locale files relative to process.cwd()
|
||||
|
||||
pluralSeparator: '_',
|
||||
// Plural separator used in your translation keys
|
||||
// If you want to use plain english keys, separators such as `_` might conflict. You might want to set `pluralSeparator` to a different string that does not occur in your keys.
|
||||
// If you don't want to generate keys for plurals (for example, in case you are using ICU format), set `pluralSeparator: false`.
|
||||
|
||||
input: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
|
||||
// An array of globs that describe where to look for source files
|
||||
// relative to the location of the configuration file
|
||||
|
||||
sort: false,
|
||||
// Whether or not to sort the catalog. Can also be a [compareFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#parameters)
|
||||
|
||||
verbose: true,
|
||||
// Display info about the parsing including some stats
|
||||
|
||||
failOnWarnings: false,
|
||||
// Exit with an exit code of 1 on warnings
|
||||
|
||||
failOnUpdate: false,
|
||||
// Exit with an exit code of 1 when translations are updated (for CI purpose)
|
||||
|
||||
customValueTemplate: null,
|
||||
// If you wish to customize the value output the value as an object, you can set your own format.
|
||||
// ${defaultValue} is the default value you set in your translation function.
|
||||
// Any other custom property will be automatically extracted.
|
||||
//
|
||||
// Example:
|
||||
// {
|
||||
// message: "${defaultValue}",
|
||||
// description: "${maxLength}", // t('my-key', {maxLength: 150})
|
||||
// }
|
||||
|
||||
resetDefaultValueLocale: null,
|
||||
// The locale to compare with default values to determine whether a default value has been changed.
|
||||
// If this is set and a default value differs from a translation in the specified locale, all entries
|
||||
// for that key across locales are reset to the default value, and existing translations are moved to
|
||||
// the `_old` file.
|
||||
|
||||
i18nextOptions: null,
|
||||
// If you wish to customize options in internally used i18next instance, you can define an object with any
|
||||
// configuration property supported by i18next (https://www.i18next.com/overview/configuration-options).
|
||||
// { compatibilityJSON: 'v3' } can be used to generate v3 compatible plurals.
|
||||
|
||||
yamlOptions: null,
|
||||
// If you wish to customize options for yaml output, you can define an object here.
|
||||
// Configuration options are here (https://github.com/nodeca/js-yaml#dump-object---options-).
|
||||
// Example:
|
||||
// {
|
||||
// lineWidth: -1,
|
||||
// }
|
||||
};
|
1424
web/package-lock.json
generated
1424
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,8 @@
|
||||
"build-storybook": "storybook build",
|
||||
"build-styles": "cd ./style-definitions && style-dictionary build && ./build.sh && cd -",
|
||||
"test": "jest",
|
||||
"format": "prettier --write **/*.{js,ts,jsx,tsx,css,md}"
|
||||
"format": "prettier --write **/*.{js,ts,jsx,tsx,css,md}",
|
||||
"translate": "i18next -c i18next-parser.config.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "4.8.1",
|
||||
@ -32,10 +33,12 @@
|
||||
"classnames": "2.3.2",
|
||||
"date-fns": "^2.29.3",
|
||||
"graphemer": "^1.4.0",
|
||||
"i18next-parser": "^8.9.0",
|
||||
"interweave": "^13.0.0",
|
||||
"interweave-autolink": "^5.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"next": "14.0.1",
|
||||
"next-export-i18n": "^2.1.0",
|
||||
"next-pwa": "^5.6.0",
|
||||
"next-with-less": "3.0.1",
|
||||
"picmo": "5.8.5",
|
||||
@ -107,6 +110,7 @@
|
||||
"eslint-plugin-storybook": "0.6.15",
|
||||
"handlebars": "^4.7.7",
|
||||
"html-webpack-plugin": "5.5.3",
|
||||
"i18next-scanner": "^4.4.0",
|
||||
"install": "^0.13.0",
|
||||
"knip": "^2.11.0",
|
||||
"less": "4.2.0",
|
||||
@ -130,4 +134,4 @@
|
||||
"ts-jest": "^29.1.0",
|
||||
"typescript": "5.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class InlineStylesHead extends Head {
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<Html>
|
||||
<InlineStylesHead />
|
||||
<body>
|
||||
<Main />
|
||||
|
Loading…
x
Reference in New Issue
Block a user