diff options
author | Thibaut Girka <thib@sitedethib.com> | 2018-05-09 17:43:30 +0200 |
---|---|---|
committer | Thibaut Girka <thib@sitedethib.com> | 2018-05-10 00:03:28 +0200 |
commit | 1c9c0167b7ea7dd03ef233a085adc0a6ef1b2527 (patch) | |
tree | ccfcb53c4ddb61d7ef3158d29403ff7cd6516e55 /app/javascript | |
parent | 143878d9dadd03347c54c9261b9bc754a1d0f5bc (diff) | |
parent | ac788ad47e32a3cf84a46ac87f84f376185cdad4 (diff) |
Merge branch 'master' into glitch-soc/master
Conflicts: app/models/account.rb app/views/accounts/_header.html.haml
Diffstat (limited to 'app/javascript')
31 files changed, 764 insertions, 237 deletions
diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index 5f1274fab..c015d3a99 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -1,20 +1,29 @@ import escapeTextContentForBrowser from 'escape-html'; import emojify from '../../features/emoji/emoji'; +import { unescapeHTML } from '../../utils/html'; const domParser = new DOMParser(); +const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => { + obj[`:${emoji.shortcode}:`] = emoji; + return obj; +}, {}); + export function normalizeAccount(account) { account = { ...account }; + const emojiMap = makeEmojiMap(account); const displayName = account.display_name.length === 0 ? account.username : account.display_name; - account.display_name_html = emojify(escapeTextContentForBrowser(displayName)); - account.note_emojified = emojify(account.note); + + account.display_name_html = emojify(escapeTextContentForBrowser(displayName), emojiMap); + account.note_emojified = emojify(account.note, emojiMap); if (account.fields) { account.fields = account.fields.map(pair => ({ ...pair, name_emojified: emojify(escapeTextContentForBrowser(pair.name)), - value_emojified: emojify(pair.value), + value_emojified: emojify(pair.value, emojiMap), + value_plain: unescapeHTML(pair.value), })); } @@ -42,11 +51,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.hidden = normalOldStatus.get('hidden'); } else { const searchContent = [status.spoiler_text, status.content].join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n'); - - const emojiMap = normalStatus.emojis.reduce((obj, emoji) => { - obj[`:${emoji.shortcode}:`] = emoji; - return obj; - }, {}); + const emojiMap = makeEmojiMap(normalStatus); normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index 7aa070f56..393268811 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -8,6 +8,7 @@ import { importFetchedStatuses, } from './importer'; import { defineMessages } from 'react-intl'; +import { unescapeHTML } from '../utils/html'; export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'; export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP'; @@ -31,13 +32,6 @@ const fetchRelatedRelationships = (dispatch, notifications) => { } }; -const unescapeHTML = (html) => { - const wrapper = document.createElement('div'); - html = html.replace(/<br \/>|<br>|\n/g, ' '); - wrapper.innerHTML = html; - return wrapper.textContent; -}; - export function updateNotifications(notification, intlMessages, intlLocale) { return (dispatch, getState) => { const showInColumn = getState().getIn(['settings', 'notifications', 'shows', notification.type], true); diff --git a/app/javascript/mastodon/components/dropdown_menu.js b/app/javascript/mastodon/components/dropdown_menu.js index 982d34718..0a6e7c627 100644 --- a/app/javascript/mastodon/components/dropdown_menu.js +++ b/app/javascript/mastodon/components/dropdown_menu.js @@ -43,6 +43,7 @@ class DropdownMenu extends React.PureComponent { componentDidMount () { document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); + if (this.focusedItem) this.focusedItem.focus(); this.setState({ mounted: true }); } @@ -55,6 +56,46 @@ class DropdownMenu extends React.PureComponent { this.node = c; } + setFocusRef = c => { + this.focusedItem = c; + } + + handleKeyDown = e => { + const items = Array.from(this.node.getElementsByTagName('a')); + const index = items.indexOf(e.currentTarget); + let element; + + switch(e.key) { + case 'Enter': + this.handleClick(e); + break; + case 'ArrowDown': + element = items[index+1]; + if (element) { + element.focus(); + } + break; + case 'ArrowUp': + element = items[index-1]; + if (element) { + element.focus(); + } + break; + case 'Home': + element = items[0]; + if (element) { + element.focus(); + } + break; + case 'End': + element = items[items.length-1]; + if (element) { + element.focus(); + } + break; + } + } + handleClick = e => { const i = Number(e.currentTarget.getAttribute('data-index')); const { action, to } = this.props.items[i]; @@ -79,7 +120,7 @@ class DropdownMenu extends React.PureComponent { return ( <li className='dropdown-menu__item' key={`${text}-${i}`}> - <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' autoFocus={i === 0} onClick={this.handleClick} data-index={i}> + <a href={href} target='_blank' rel='noopener' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyDown={this.handleKeyDown} data-index={i}> {text} </a> </li> @@ -156,9 +197,6 @@ export default class Dropdown extends React.PureComponent { handleKeyDown = e => { switch(e.key) { - case 'Enter': - this.handleClick(e); - break; case 'Escape': this.handleClose(); break; diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 7cdd63910..fd6858d05 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -35,7 +35,6 @@ export default class ScrollableList extends PureComponent { state = { fullscreen: null, - mouseOver: false, }; intersectionObserverWrapper = new IntersectionObserverWrapper(); @@ -72,7 +71,7 @@ export default class ScrollableList extends PureComponent { const someItemInserted = React.Children.count(prevProps.children) > 0 && React.Children.count(prevProps.children) < React.Children.count(this.props.children) && this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); - if (someItemInserted && this.node.scrollTop > 0 || (this.state.mouseOver && !prevProps.isLoading)) { + if (someItemInserted && this.node.scrollTop > 0) { return this.node.scrollHeight - this.node.scrollTop; } else { return null; @@ -140,14 +139,6 @@ export default class ScrollableList extends PureComponent { this.props.onLoadMore(); } - handleMouseEnter = () => { - this.setState({ mouseOver: true }); - } - - handleMouseLeave = () => { - this.setState({ mouseOver: false }); - } - render () { const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, emptyMessage, onLoadMore } = this.props; const { fullscreen } = this.state; @@ -158,7 +149,7 @@ export default class ScrollableList extends PureComponent { if (isLoading || childrenCount > 0 || !emptyMessage) { scrollableArea = ( - <div className={classNames('scrollable', { fullscreen })} ref={this.setRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> + <div className={classNames('scrollable', { fullscreen })} ref={this.setRef}> <div role='feed' className='item-list'> {prepend} diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index 402d558c4..953d98c20 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -206,7 +206,7 @@ export default class Status extends ImmutablePureComponent { ); } else { media = ( - <Bundle fetchComponent={MediaGallery} loading={this.renderLoadingMediaGallery} > + <Bundle fetchComponent={MediaGallery} loading={this.renderLoadingMediaGallery}> {Component => <Component media={status.get('media_attachments')} sensitive={status.get('sensitive')} height={110} onOpenMedia={this.props.onOpenMedia} />} </Bundle> ); diff --git a/app/javascript/mastodon/containers/card_container.js b/app/javascript/mastodon/containers/card_container.js deleted file mode 100644 index 11b9f88d4..000000000 --- a/app/javascript/mastodon/containers/card_container.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Card from '../features/status/components/card'; -import { fromJS } from 'immutable'; - -export default class CardContainer extends React.PureComponent { - - static propTypes = { - locale: PropTypes.string, - card: PropTypes.array.isRequired, - }; - - render () { - const { card, ...props } = this.props; - return <Card card={fromJS(card)} {...props} />; - } - -} diff --git a/app/javascript/mastodon/containers/cards_container.js b/app/javascript/mastodon/containers/cards_container.js new file mode 100644 index 000000000..894bf4ef9 --- /dev/null +++ b/app/javascript/mastodon/containers/cards_container.js @@ -0,0 +1,59 @@ +import React, { Fragment } from 'react'; +import ReactDOM from 'react-dom'; +import PropTypes from 'prop-types'; +import { IntlProvider, addLocaleData } from 'react-intl'; +import { getLocale } from '../locales'; +import Card from '../features/status/components/card'; +import ModalRoot from '../components/modal_root'; +import MediaModal from '../features/ui/components/media_modal'; +import { fromJS } from 'immutable'; + +const { localeData, messages } = getLocale(); +addLocaleData(localeData); + +export default class CardsContainer extends React.PureComponent { + + static propTypes = { + locale: PropTypes.string, + cards: PropTypes.object.isRequired, + }; + + state = { + media: null, + }; + + handleOpenCard = (media) => { + document.body.classList.add('card-standalone__body'); + this.setState({ media }); + } + + handleCloseCard = () => { + document.body.classList.remove('card-standalone__body'); + this.setState({ media: null }); + } + + render () { + const { locale, cards } = this.props; + + return ( + <IntlProvider locale={locale} messages={messages}> + <Fragment> + {[].map.call(cards, container => { + const { card, ...props } = JSON.parse(container.getAttribute('data-props')); + + return ReactDOM.createPortal( + <Card card={fromJS(card)} onOpenMedia={this.handleOpenCard} {...props} />, + container, + ); + })} + <ModalRoot onClose={this.handleCloseCard}> + {this.state.media && ( + <MediaModal media={this.state.media} index={0} onClose={this.handleCloseCard} /> + )} + </ModalRoot> + </Fragment> + </IntlProvider> + ); + } + +} diff --git a/app/javascript/mastodon/containers/timeline_container.js b/app/javascript/mastodon/containers/timeline_container.js index 8719bb5c9..a1a4bd024 100644 --- a/app/javascript/mastodon/containers/timeline_container.js +++ b/app/javascript/mastodon/containers/timeline_container.js @@ -1,4 +1,5 @@ -import React from 'react'; +import React, { Fragment } from 'react'; +import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import PropTypes from 'prop-types'; import configureStore from '../store/configureStore'; @@ -8,6 +9,7 @@ import { getLocale } from '../locales'; import PublicTimeline from '../features/standalone/public_timeline'; import CommunityTimeline from '../features/standalone/community_timeline'; import HashtagTimeline from '../features/standalone/hashtag_timeline'; +import ModalContainer from '../features/ui/containers/modal_container'; import initialState from '../initial_state'; const { localeData, messages } = getLocale(); @@ -47,7 +49,13 @@ export default class TimelineContainer extends React.PureComponent { return ( <IntlProvider locale={locale} messages={messages}> <Provider store={store}> - {timeline} + <Fragment> + {timeline} + {ReactDOM.createPortal( + <ModalContainer />, + document.getElementById('modal-container'), + )} + </Fragment> </Provider> </IntlProvider> ); diff --git a/app/javascript/mastodon/features/account/components/header.js b/app/javascript/mastodon/features/account/components/header.js index bbf886dca..7358053da 100644 --- a/app/javascript/mastodon/features/account/components/header.js +++ b/app/javascript/mastodon/features/account/components/header.js @@ -131,6 +131,7 @@ export default class Header extends ImmutablePureComponent { const content = { __html: account.get('note_emojified') }; const displayNameHtml = { __html: account.get('display_name_html') }; const fields = account.get('fields'); + const badge = account.get('bot') ? (<div className='roles'><div className='account-role bot'><FormattedMessage id='account.badges.bot' defaultMessage='Bot' /></div></div>) : null; return ( <div className={classNames('account__header', { inactive: !!account.get('moved') })} style={{ backgroundImage: `url(${account.get('header')})` }}> @@ -139,19 +140,20 @@ export default class Header extends ImmutablePureComponent { <span className='account__header__display-name' dangerouslySetInnerHTML={displayNameHtml} /> <span className='account__header__username'>@{account.get('acct')} {lockedIcon}</span> + + {badge} + <div className='account__header__content' dangerouslySetInnerHTML={content} /> {fields.size > 0 && ( - <table className='account__header__fields'> - <tbody> - {fields.map((pair, i) => ( - <tr key={i}> - <th dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} /> - <td dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} /> - </tr> - ))} - </tbody> - </table> + <div className='account__header__fields'> + {fields.map((pair, i) => ( + <dl key={i}> + <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> + <dd dangerouslySetInnerHTML={{ __html: pair.get('value_emojified') }} title={pair.get('value_plain')} /> + </dl> + ))} + </div> )} {info} diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js index 6b22ba84a..a772c1c95 100644 --- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js +++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js @@ -42,22 +42,65 @@ class PrivacyDropdownMenu extends React.PureComponent { } } - handleClick = e => { - if (e.key === 'Escape') { - this.props.onClose(); - } else if (!e.key || e.key === 'Enter') { - const value = e.currentTarget.getAttribute('data-index'); - - e.preventDefault(); + handleKeyDown = e => { + const { items } = this.props; + const value = e.currentTarget.getAttribute('data-index'); + const index = items.findIndex(item => { + return (item.value === value); + }); + let element; + switch(e.key) { + case 'Escape': this.props.onClose(); - this.props.onChange(value); + break; + case 'Enter': + this.handleClick(e); + break; + case 'ArrowDown': + element = this.node.childNodes[index + 1]; + if (element) { + element.focus(); + this.props.onChange(element.getAttribute('data-index')); + } + break; + case 'ArrowUp': + element = this.node.childNodes[index - 1]; + if (element) { + element.focus(); + this.props.onChange(element.getAttribute('data-index')); + } + break; + case 'Home': + element = this.node.firstChild; + if (element) { + element.focus(); + this.props.onChange(element.getAttribute('data-index')); + } + break; + case 'End': + element = this.node.lastChild; + if (element) { + element.focus(); + this.props.onChange(element.getAttribute('data-index')); + } + break; } } + handleClick = e => { + const value = e.currentTarget.getAttribute('data-index'); + + e.preventDefault(); + + this.props.onClose(); + this.props.onChange(value); + } + componentDidMount () { document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); + if (this.focusedItem) this.focusedItem.focus(); this.setState({ mounted: true }); } @@ -70,6 +113,10 @@ class PrivacyDropdownMenu extends React.PureComponent { this.node = c; } + setFocusRef = c => { + this.focusedItem = c; + } + render () { const { mounted } = this.state; const { style, items, value } = this.props; @@ -80,9 +127,9 @@ class PrivacyDropdownMenu extends React.PureComponent { // It should not be transformed when mounting because the resulting // size will be used to determine the coordinate of the menu by // react-overlays - <div className='privacy-dropdown__dropdown' style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}> + <div className='privacy-dropdown__dropdown' style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} role='listbox' ref={this.setRef}> {items.map(item => ( - <div role='button' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleClick} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })}> + <div role='option' tabIndex='0' key={item.value} data-index={item.value} onKeyDown={this.handleKeyDown} onClick={this.handleClick} className={classNames('privacy-dropdown__option', { active: item.value === value })} aria-selected={item.value === value} ref={item.value === value ? this.setFocusRef : null}> <div className='privacy-dropdown__option__icon'> <i className={`fa fa-fw fa-${item.icon}`} /> </div> @@ -147,9 +194,6 @@ export default class PrivacyDropdown extends React.PureComponent { handleKeyDown = e => { switch(e.key) { - case 'Enter': - this.handleToggle(e); - break; case 'Escape': this.handleClose(); break; diff --git a/app/javascript/mastodon/features/compose/index.js b/app/javascript/mastodon/features/compose/index.js index 67f0e7981..19aae0332 100644 --- a/app/javascript/mastodon/features/compose/index.js +++ b/app/javascript/mastodon/features/compose/index.js @@ -43,11 +43,19 @@ export default class Compose extends React.PureComponent { }; componentDidMount () { - this.props.dispatch(mountCompose()); + const { isSearchPage } = this.props; + + if (!isSearchPage) { + this.props.dispatch(mountCompose()); + } } componentWillUnmount () { - this.props.dispatch(unmountCompose()); + const { isSearchPage } = this.props; + + if (!isSearchPage) { + this.props.dispatch(unmountCompose()); + } } onFocus = () => { diff --git a/app/javascript/mastodon/features/ui/components/modal_root.js b/app/javascript/mastodon/features/ui/components/modal_root.js index 4185cba32..a334318ce 100644 --- a/app/javascript/mastodon/features/ui/components/modal_root.js +++ b/app/javascript/mastodon/features/ui/components/modal_root.js @@ -40,6 +40,17 @@ export default class ModalRoot extends React.PureComponent { onClose: PropTypes.func.isRequired, }; + getSnapshotBeforeUpdate () { + const visible = !!this.props.type; + return { + overflowY: visible ? 'hidden' : null, + }; + } + + componentDidUpdate (prevProps, prevState, { overflowY }) { + document.body.style.overflowY = overflowY; + } + renderLoading = modalId => () => { return ['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? <ModalLoading /> : null; } diff --git a/app/javascript/mastodon/features/ui/components/report_modal.js b/app/javascript/mastodon/features/ui/components/report_modal.js index 8a55c553c..8616f0315 100644 --- a/app/javascript/mastodon/features/ui/components/report_modal.js +++ b/app/javascript/mastodon/features/ui/components/report_modal.js @@ -30,7 +30,7 @@ const makeMapStateToProps = () => { account: getAccount(state, accountId), comment: state.getIn(['reports', 'new', 'comment']), forward: state.getIn(['reports', 'new', 'forward']), - statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])), + statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}:with_replies`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])), }; }; @@ -64,12 +64,12 @@ export default class ReportModal extends ImmutablePureComponent { } componentDidMount () { - this.props.dispatch(expandAccountTimeline(this.props.account.get('id'))); + this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true })); } componentWillReceiveProps (nextProps) { if (this.props.account !== nextProps.account && nextProps.account) { - this.props.dispatch(expandAccountTimeline(nextProps.account.get('id'))); + this.props.dispatch(expandAccountTimeline(nextProps.account.get('id'), { withReplies: true })); } } diff --git a/app/javascript/mastodon/features/ui/containers/status_list_container.js b/app/javascript/mastodon/features/ui/containers/status_list_container.js index 4efacda65..e5b1edc4a 100644 --- a/app/javascript/mastodon/features/ui/containers/status_list_container.js +++ b/app/javascript/mastodon/features/ui/containers/status_list_container.js @@ -21,6 +21,8 @@ const makeGetStatusIds = () => createSelector([ } return statusIds.filter(id => { + if (id === null) return true; + const statusForId = statuses.get(id); let showStatus = true; diff --git a/app/javascript/mastodon/locales/ar.json b/app/javascript/mastodon/locales/ar.json index 947348f70..d531d8fd5 100644 --- a/app/javascript/mastodon/locales/ar.json +++ b/app/javascript/mastodon/locales/ar.json @@ -258,7 +258,7 @@ "status.pin": "تدبيس على الملف الشخصي", "status.pinned": "تبويق مثبَّت", "status.reblog": "رَقِّي", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "القيام بالترقية إلى الجمهور الأصلي", "status.reblogged_by": "{name} رقى", "status.reply": "ردّ", "status.replyAll": "رُد على الخيط", diff --git a/app/javascript/mastodon/locales/co.json b/app/javascript/mastodon/locales/co.json new file mode 100644 index 000000000..2d7427c55 --- /dev/null +++ b/app/javascript/mastodon/locales/co.json @@ -0,0 +1,296 @@ +{ + "account.block": "Bluccà @{name}", + "account.block_domain": "Piattà tuttu da {domain}", + "account.blocked": "Bluccatu", + "account.direct": "Missaghju direttu @{name}", + "account.disclaimer_full": "Information below may reflect the user's profile incompletely.", + "account.domain_blocked": "Duminiu piattatu", + "account.edit_profile": "Mudificà u prufile", + "account.follow": "Siguità", + "account.followers": "Abbunati", + "account.follows": "Abbunamenti", + "account.follows_you": "Vi seguita", + "account.hide_reblogs": "Piattà spartere da @{name}", + "account.media": "Media", + "account.mention": "Mintuvà @{name}", + "account.moved_to": "{name} hè partutu nant'à:", + "account.mute": "Piattà @{name}", + "account.mute_notifications": "Piattà nutificazione da @{name}", + "account.muted": "Piattatu", + "account.posts": "Statuti", + "account.posts_with_replies": "Statuti è risposte", + "account.report": "Palisà @{name}", + "account.requested": "In attesa d'apprubazione. Cliccate per annullà a dumanda", + "account.share": "Sparte u prufile di @{name}", + "account.show_reblogs": "Vede spartere da @{name}", + "account.unblock": "Sbluccà @{name}", + "account.unblock_domain": "Ùn piattà più {domain}", + "account.unfollow": "Ùn siguità più", + "account.unmute": "Ùn piattà più @{name}", + "account.unmute_notifications": "Ùn piattà più nutificazione da @{name}", + "account.view_full_profile": "View full profile", + "alert.unexpected.message": "Un prublemu inaspettatu hè accadutu.", + "alert.unexpected.title": "Uups!", + "boost_modal.combo": "Pudete appughjà nant'à {combo} per saltà quessa a prussima volta", + "bundle_column_error.body": "C'hè statu un prublemu caricandu st'elementu.", + "bundle_column_error.retry": "Pruvà torna", + "bundle_column_error.title": "Errore di cunnessione", + "bundle_modal_error.close": "Chjudà", + "bundle_modal_error.message": "C'hè statu un prublemu caricandu st'elementu.", + "bundle_modal_error.retry": "Pruvà torna", + "column.blocks": "Utilizatori bluccati", + "column.community": "Linea pubblica lucale", + "column.direct": "Missaghji diretti", + "column.domain_blocks": "Duminii piattati", + "column.favourites": "Favuriti", + "column.follow_requests": "Dumande d'abbunamentu", + "column.home": "Accolta", + "column.lists": "Liste", + "column.mutes": "Utilizatori piattati", + "column.notifications": "Nutificazione", + "column.pins": "Statuti puntarulati", + "column.public": "Linea pubblica glubale", + "column_back_button.label": "Ritornu", + "column_header.hide_settings": "Piattà i parametri", + "column_header.moveLeft_settings": "Spiazzà à manca", + "column_header.moveRight_settings": "Spiazzà à diritta", + "column_header.pin": "Puntarulà", + "column_header.show_settings": "Mustrà i parametri", + "column_header.unpin": "Spuntarulà", + "column_subheading.navigation": "Navigazione", + "column_subheading.settings": "Parametri", + "compose_form.direct_message_warning": "Solu l'utilizatori mintuvati puderenu vede stu statutu.", + "compose_form.hashtag_warning": "Stu statutu ùn hè \"Micca listatu\" è ùn sarà micca listatu indè e circate da hashtag. Per esse vistu in quesse, u statutu deve esse \"Pubblicu\".", + "compose_form.lock_disclaimer": "U vostru contu ùn hè micca {locked}. Tuttu u mondu pò seguitavi è vede i vostri statuti privati.", + "compose_form.lock_disclaimer.lock": "privatu", + "compose_form.placeholder": "À chè pensate?", + "compose_form.publish": "Toot", + "compose_form.publish_loud": "{publish}!", + "compose_form.sensitive.marked": "Media indicatu cum'è sensibile", + "compose_form.sensitive.unmarked": "Media micca indicatu cum'è sensibile", + "compose_form.spoiler.marked": "Testu piattatu daret'à un'avertimentu", + "compose_form.spoiler.unmarked": "Testu micca piattatu", + "compose_form.spoiler_placeholder": "Scrive u vostr'avertimentu quì", + "confirmation_modal.cancel": "Annullà", + "confirmations.block.confirm": "Bluccà", + "confirmations.block.message": "Site sicuru·a che vulete bluccà @{name}?", + "confirmations.delete.confirm": "Toglie", + "confirmations.delete.message": "Site sicuru·a che vulete supprime stu statutu?", + "confirmations.delete_list.confirm": "Toglie", + "confirmations.delete_list.message": "Site sicuru·a che vulete supprime sta lista?", + "confirmations.domain_block.confirm": "Piattà tuttu u duminiu?", + "confirmations.domain_block.message": "Site sicuru·a che vulete piattà tuttu à {domain}? Saria forse abbastanza di bluccà ò piattà alcuni conti da quallà.", + "confirmations.mute.confirm": "Piattà", + "confirmations.mute.message": "Site sicuru·a che vulete piattà @{name}?", + "confirmations.unfollow.confirm": "Disabbunassi", + "confirmations.unfollow.message": "Site sicuru·a ch'ùn vulete più siguità @{name}?", + "embed.instructions": "Integrà stu statutu à u vostru situ cù u codice quì sottu.", + "embed.preview": "Assumiglierà à qualcosa cusì:", + "emoji_button.activity": "Attività", + "emoji_button.custom": "Persunalizati", + "emoji_button.flags": "Bandere", + "emoji_button.food": "Manghjusca è Bienda", + "emoji_button.label": "Mette un'emoji", + "emoji_button.nature": "Natura", + "emoji_button.not_found": "Ùn c'hè nunda! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "Oggetti", + "emoji_button.people": "Parsunaghji", + "emoji_button.recent": "Assai utilizati", + "emoji_button.search": "Cercà...", + "emoji_button.search_results": "Risultati di a cerca", + "emoji_button.symbols": "Simbuli", + "emoji_button.travel": "Lochi è Viaghju", + "empty_column.community": "Ùn c'hè nunda indè a linea lucale. Scrivete puru qualcosa!", + "empty_column.direct": "Ùn avete ancu nisun missaghju direttu. S'è voi mandate o ricevete unu, u vidarete quì.", + "empty_column.hashtag": "Ùn c'hè ancu nunda quì.", + "empty_column.home": "A vostr'accolta hè viota! Pudete andà nant'à {public} o pruvà a ricerca per truvà parsone da siguità.", + "empty_column.home.public_timeline": "a linea pubblica", + "empty_column.list": "Ùn c'hè ancu nunda quì. Quandu membri di sta lista manderanu novi statuti, i vidarete quì.", + "empty_column.notifications": "Ùn avete ancu nisuna nutificazione. Interact with others to start the conversation.", + "empty_column.public": "Ùn c'hè nunda quì! Scrivete qualcosa in pubblicu o seguitate utilizatori d'altre istanze per empie a linea pubblica.", + "follow_request.authorize": "Auturizà", + "follow_request.reject": "Righjittà", + "getting_started.appsshort": "Applicazione", + "getting_started.faq": "FAQ", + "getting_started.heading": "Per principià", + "getting_started.open_source_notice": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un bug, nant'à GitHub: {github}", + "getting_started.userguide": "Guida d'utilizazione", + "home.column_settings.advanced": "Avanzati", + "home.column_settings.basic": "Bàsichi", + "home.column_settings.filter_regex": "Filtrà cù spressione regulare (regex)", + "home.column_settings.show_reblogs": "Vede e spartere", + "home.column_settings.show_replies": "Vede e risposte", + "home.settings": "Parametri di a colonna", + "keyboard_shortcuts.back": "rivultà", + "keyboard_shortcuts.boost": "sparte", + "keyboard_shortcuts.column": "fucalizà un statutu indè una colonna", + "keyboard_shortcuts.compose": "fucalizà nant'à l'area di ridazzione", + "keyboard_shortcuts.description": "Descrizzione", + "keyboard_shortcuts.down": "falà indè a lista", + "keyboard_shortcuts.enter": "apre u statutu", + "keyboard_shortcuts.favourite": "aghjunghje à i favuriti", + "keyboard_shortcuts.heading": "Accorte cù a tastera", + "keyboard_shortcuts.hotkey": "Accorta", + "keyboard_shortcuts.legend": "vede a legenda", + "keyboard_shortcuts.mention": "mintuvà l'autore", + "keyboard_shortcuts.reply": "risponde", + "keyboard_shortcuts.search": "fucalizà nant'à l'area di circata", + "keyboard_shortcuts.toggle_hidden": "vede/piattà u testu daretu à l'avertimentu CW", + "keyboard_shortcuts.toot": "scrive un novu statutu", + "keyboard_shortcuts.unfocus": "ùn fucalizà più l'area di testu", + "keyboard_shortcuts.up": "cullà indè a lista", + "lightbox.close": "Chjudà", + "lightbox.next": "Siguente", + "lightbox.previous": "Pricidente", + "lists.account.add": "Aghjunghje à a lista", + "lists.account.remove": "Toglie di a lista", + "lists.delete": "Supprime a lista", + "lists.edit": "Mudificà a lista", + "lists.new.create": "Aghjustà una lista", + "lists.new.title_placeholder": "Titulu di a lista", + "lists.search": "Circà indè i vostr'abbunamenti", + "lists.subheading": "E vo liste", + "loading_indicator.label": "Caricamentu...", + "media_gallery.toggle_visible": "Cambià a visibilità", + "missing_indicator.label": "Micca trovu", + "missing_indicator.sublabel": "Ùn era micca pussivule di truvà sta risorsa", + "mute_modal.hide_notifications": "Piattà nutificazione da st'utilizatore?", + "navigation_bar.blocks": "Utilizatori bluccati", + "navigation_bar.community_timeline": "Linea pubblica lucale", + "navigation_bar.direct": "Missaghji diretti", + "navigation_bar.domain_blocks": "Duminii piattati", + "navigation_bar.edit_profile": "Mudificà u prufile", + "navigation_bar.favourites": "Favuriti", + "navigation_bar.follow_requests": "Dumande d'abbunamentu", + "navigation_bar.info": "À prupositu di l'istanza", + "navigation_bar.keyboard_shortcuts": "Accorte cù a tastera", + "navigation_bar.lists": "Liste", + "navigation_bar.logout": "Scunnettassi", + "navigation_bar.mutes": "Utilizatori piattati", + "navigation_bar.pins": "Statuti puntarulati", + "navigation_bar.preferences": "Preferenze", + "navigation_bar.public_timeline": "Linea pubblica glubale", + "notification.favourite": "{name} hà aghjuntu u vostru statutu à i so favuriti", + "notification.follow": "{name} v'hà seguitatu", + "notification.mention": "{name} v'hà mintuvatu", + "notification.reblog": "{name} hà spartutu u vostru statutu", + "notifications.clear": "Purgà e nutificazione", + "notifications.clear_confirmation": "Site sicuru·a che vulete toglie tutte ste nutificazione?", + "notifications.column_settings.alert": "Nutificazione nant'à l'urdinatore", + "notifications.column_settings.favourite": "Favuriti:", + "notifications.column_settings.follow": "Abbunati novi:", + "notifications.column_settings.mention": "Minzione:", + "notifications.column_settings.push": "Nutificazione Push", + "notifications.column_settings.push_meta": "Quess'apparechju", + "notifications.column_settings.reblog": "Spartere:", + "notifications.column_settings.show": "Mustrà indè a colonna", + "notifications.column_settings.sound": "Sunà", + "onboarding.done": "Fatta", + "onboarding.next": "Siguente", + "onboarding.page_five.public_timelines": "A linea pubblica lucale mostra statuti pubblichi da tuttu u mondu nant'à {domain}. A linea pubblica glubale mostra ancu quelli di a ghjente seguitata da l'utilizatori di {domain}. Quesse sò una bona manera d'incuntrà nove parsone.", + "onboarding.page_four.home": "A linea d'accolta mostra i statuti di i vostr'abbunamenti.", + "onboarding.page_four.notifications": "A colonna di nutificazione mostra l'interazzione ch'altre parsone anu cù u vostru contu.", + "onboarding.page_one.federation": "Mastodon ghjè una rete di servori independenti, chjamati istanze, uniti indè una sola rete suciale.", + "onboarding.page_one.full_handle": "U vostru identificatore cumplettu", + "onboarding.page_one.handle_hint": "Quessu ghjè cio chì direte à i vostri amichi per circavi.", + "onboarding.page_one.welcome": "Benvenuti/a nant'à Mastodon!", + "onboarding.page_six.admin": "L'amministratore di a vostr'istanza hè {admin}.", + "onboarding.page_six.almost_done": "Quasgi finitu...", + "onboarding.page_six.appetoot": "Bon Appetoot!", + "onboarding.page_six.apps_available": "Ci sò {apps} dispunibule per iOS, Android è altre piattaforme.", + "onboarding.page_six.github": "Mastodon ghjè un lugiziale liberu. Pudete cuntribuisce à u codice o a traduzione, o palisà un prublemu, nant'à {github}.", + "onboarding.page_six.guidelines": "regule di a cumunità", + "onboarding.page_six.read_guidelines": "Ùn vi scurdate di leghje e {guidelines} di {domain}", + "onboarding.page_six.various_app": "applicazione pè u telefuninu", + "onboarding.page_three.profile": "Pudete mudificà u prufile per cambia u ritrattu, a descrizzione è u nome affissatu. Ci sò ancu alcun'altre preferenze.", + "onboarding.page_three.search": "Fate usu di l'area di ricerca per truvà altre persone è vede hashtag cum'è {illustration} o {introductions}. Per vede qualcunu ch'ùn hè micca nant'à st'istanza, cercate u so identificatore complettu (pare un'email).", + "onboarding.page_two.compose": "I statuti è missaghji si scrivenu indè l'area di ridazzione. Pudete caricà imagine, cambià i parametri di pubblicazione, è mette avertimenti di cuntenuti cù i buttoni quì sottu.", + "onboarding.skip": "Passà", + "privacy.change": "Mudificà a cunfidenzialità di u statutu", + "privacy.direct.long": "Mandà solu à quelli chì so mintuvati", + "privacy.direct.short": "Direttu", + "privacy.private.long": "Mustrà solu à l'abbunati", + "privacy.private.short": "Privatu", + "privacy.public.long": "Mustrà à tuttu u mondu nant'a linea pubblica", + "privacy.public.short": "Pubblicu", + "privacy.unlisted.long": "Ùn mette micca nant'a linea pubblica (ma tutt'u mondu pò vede u statutu nant'à u vostru prufile)", + "privacy.unlisted.short": "Micca listatu", + "regeneration_indicator.label": "Caricamentu…", + "regeneration_indicator.sublabel": "Priparazione di a vostra pagina d'accolta", + "relative_time.days": "{number}d", + "relative_time.hours": "{number}h", + "relative_time.just_now": "avà", + "relative_time.minutes": "{number}m", + "relative_time.seconds": "{number}s", + "reply_indicator.cancel": "Annullà", + "report.forward": "Trasferisce à {target}", + "report.forward_hint": "U contu hè nant'à un'altru servore. Vulete ancu mandà una copia anonima di u signalamentu quallà?", + "report.hint": "U signalamentu sarà mandatu à i muderatori di l'istanza. Pudete spiegà perchè avete palisatu stu contu quì sottu:", + "report.placeholder": "Altri cummenti", + "report.submit": "Mandà", + "report.target": "Signalamentu", + "search.placeholder": "Circà", + "search_popout.search_format": "Ricerca avanzata", + "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.hashtag": "hashtag", + "search_popout.tips.status": "statutu", + "search_popout.tips.text": "Simple text returns matching display names, usernames and hashtags", + "search_popout.tips.user": "utilizatore", + "search_results.accounts": "Ghjente", + "search_results.hashtags": "Hashtags", + "search_results.statuses": "Statuti", + "search_results.total": "{count, number} {count, plural, one {risultatu} other {risultati}}", + "standalone.public_title": "Una vista di...", + "status.block": "Bluccà @{name}", + "status.cancel_reblog_private": "Ùn sparte più", + "status.cannot_reblog": "Stu statutu ùn pò micca esse spartutu", + "status.delete": "Toglie", + "status.direct": "Mandà un missaghju @{name}", + "status.embed": "Integrà", + "status.favourite": "Aghjunghje à i favuriti", + "status.load_more": "Vede di più", + "status.media_hidden": "Media piattata", + "status.mention": "Mintuvà @{name}", + "status.more": "Più", + "status.mute": "Piattà @{name}", + "status.mute_conversation": "Piattà a cunversazione", + "status.open": "Apre stu statutu", + "status.pin": "Puntarulà à u prufile", + "status.pinned": "Statutu puntarulatu", + "status.reblog": "Sparte", + "status.reblog_private": "Sparte à l'audienza uriginale", + "status.reblogged_by": "{name} hà spartutu", + "status.reply": "Risponde", + "status.replyAll": "Risponde à tutti", + "status.report": "Palisà @{name}", + "status.sensitive_toggle": "Cliccate per vede", + "status.sensitive_warning": "Cuntinutu sensibile", + "status.share": "Sparte", + "status.show_less": "Ripiegà", + "status.show_less_all": "Ripiegà tuttu", + "status.show_more": "Slibrà", + "status.show_more_all": "Slibrà tuttu", + "status.unmute_conversation": "Ùn piattà più a cunversazione", + "status.unpin": "Spuntarulà da u prufile", + "tabs_bar.federated_timeline": "Glubale", + "tabs_bar.home": "Accolta", + "tabs_bar.local_timeline": "Lucale", + "tabs_bar.notifications": "Nutificazione", + "tabs_bar.search": "Cercà", + "ui.beforeunload": "A bruttacopia sarà persa s'ellu hè chjosu Mastodon.", + "upload_area.title": "Drag & drop per caricà un fugliale", + "upload_button.label": "Aghjunghje un media", + "upload_form.description": "Discrive per i malvistosi", + "upload_form.focus": "Riquatrà", + "upload_form.undo": "Annullà", + "upload_progress.label": "Caricamentu...", + "video.close": "Chjudà a video", + "video.exit_fullscreen": "Caccià u pienu screnu", + "video.expand": "Ingrandà a video", + "video.fullscreen": "Pienu screnu", + "video.hide": "Piattà a video", + "video.mute": "Surdina", + "video.pause": "Pausa", + "video.play": "Lettura", + "video.unmute": "Caccià a surdina" +} diff --git a/app/javascript/mastodon/locales/el.json b/app/javascript/mastodon/locales/el.json index a7e1c408f..5b36348eb 100644 --- a/app/javascript/mastodon/locales/el.json +++ b/app/javascript/mastodon/locales/el.json @@ -2,9 +2,9 @@ "account.block": "Απόκλεισε τον/την @{name}", "account.block_domain": "Απόκρυψε τα πάντα από τον/την", "account.blocked": "Αποκλεισμένος/η", - "account.direct": "Απευθείας μήνυμα προς @{name}", + "account.direct": "Άμεσο μήνυμα προς @{name}", "account.disclaimer_full": "Οι παρακάτω πληροφορίες μπορει να μην αντανακλούν το προφίλ του χρήστη επαρκως.", - "account.domain_blocked": "Domain hidden", + "account.domain_blocked": "Κρυμμένος τομέας", "account.edit_profile": "Επεξεργάσου το προφίλ", "account.follow": "Ακολούθησε", "account.followers": "Ακόλουθοι", @@ -23,15 +23,15 @@ "account.requested": "Εκκρεμεί έγκριση. Κάνε κλικ για να ακυρώσεις το αίτημα ακολούθησης", "account.share": "Μοιράσου το προφίλ του/της @{name}", "account.show_reblogs": "Δείξε τις προωθήσεις του/της @{name}", - "account.unblock": "Unblock @{name}", + "account.unblock": "Ξεμπλόκαρε τον/την @{name}", "account.unblock_domain": "Αποκάλυψε το {domain}", - "account.unfollow": "Unfollow", - "account.unmute": "Unmute @{name}", - "account.unmute_notifications": "Unmute notifications from @{name}", + "account.unfollow": "Διακοπή παρακολούθησης", + "account.unmute": "Διακοπή αποσιώπησης του/της @{name}", + "account.unmute_notifications": "Διακοπή αποσιώπησης ειδοποιήσεων του/της @{name}", "account.view_full_profile": "Δες το πλήρες προφίλ", "alert.unexpected.message": "Προέκυψε απροσδόκητο σφάλμα.", "alert.unexpected.title": "Εεπ!", - "boost_modal.combo": "You can press {combo} to skip this next time", + "boost_modal.combo": "Μπορείς να πατήσεις {combo} για να το προσπεράσεις αυτό την επόμενη φορά", "bundle_column_error.body": "Κάτι πήγε στραβά ενώ φορτωνόταν αυτό το στοιχείο.", "bundle_column_error.retry": "Δοκίμασε ξανά", "bundle_column_error.title": "Σφάλμα δικτύου", @@ -41,7 +41,7 @@ "column.blocks": "Αποκλεισμένοι χρήστες", "column.community": "Τοπική ροή", "column.direct": "Απευθείας μηνύματα", - "column.domain_blocks": "Hidden domains", + "column.domain_blocks": "Κρυμμένοι τομείς", "column.favourites": "Αγαπημένα", "column.follow_requests": "Αιτήματα παρακολούθησης", "column.home": "Αρχική", @@ -60,7 +60,7 @@ "column_subheading.navigation": "Πλοήγηση", "column_subheading.settings": "Ρυθμίσεις", "compose_form.direct_message_warning": "Αυτό το τουτ θα εμφανίζεται μόνο σε όλους τους αναφερόμενους χρήστες.", - "compose_form.hashtag_warning": "This toot won't be listed under any hashtag as it is unlisted. Only public toots can be searched by hashtag.", + "compose_form.hashtag_warning": "Αυτό το τουτ δεν θα εμφανίζεται κάτω από καμία ταμπέλα καθώς είναι αφανές. Μόνο τα δημόσια τουτ μπορούν να αναζητηθούν ανά ταμπέλα.", "compose_form.lock_disclaimer": "Ο λογαριασμός σου δεν είναι {locked}. Οποιοσδήποτε μπορεί να σε ακολουθήσει για να δει τις δημοσιεύσεις σας προς τους ακολούθους σας.", "compose_form.lock_disclaimer.lock": "κλειδωμένος", "compose_form.placeholder": "Τι σκέφτεσαι;", @@ -78,65 +78,65 @@ "confirmations.delete.message": "Σίγουρα θες να διαγράψεις αυτή την κατάσταση;", "confirmations.delete_list.confirm": "Διέγραψε", "confirmations.delete_list.message": "Σίγουρα θες να διαγράψεις οριστικά αυτή τη λίστα;", - "confirmations.domain_block.confirm": "Hide entire domain", - "confirmations.domain_block.message": "Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.", - "confirmations.mute.confirm": "Mute", - "confirmations.mute.message": "Are you sure you want to mute {name}?", - "confirmations.unfollow.confirm": "Unfollow", - "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", - "embed.instructions": "Embed this status on your website by copying the code below.", - "embed.preview": "Here is what it will look like:", - "emoji_button.activity": "Activity", - "emoji_button.custom": "Custom", - "emoji_button.flags": "Flags", - "emoji_button.food": "Food & Drink", - "emoji_button.label": "Insert emoji", - "emoji_button.nature": "Nature", - "emoji_button.not_found": "No emojos!! (╯°□°)╯︵ ┻━┻", - "emoji_button.objects": "Objects", - "emoji_button.people": "People", - "emoji_button.recent": "Frequently used", - "emoji_button.search": "Search...", - "emoji_button.search_results": "Search results", - "emoji_button.symbols": "Symbols", - "emoji_button.travel": "Travel & Places", - "empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!", - "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", - "empty_column.hashtag": "There is nothing in this hashtag yet.", - "empty_column.home": "Your home timeline is empty! Visit {public} or use search to get started and meet other users.", - "empty_column.home.public_timeline": "the public timeline", - "empty_column.list": "There is nothing in this list yet. When members of this list post new statuses, they will appear here.", - "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.", - "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other instances to fill it up", - "follow_request.authorize": "Authorize", - "follow_request.reject": "Reject", - "getting_started.appsshort": "Apps", + "confirmations.domain_block.confirm": "Απόκρυψη ολόκληρου του τομέα", + "confirmations.domain_block.message": "Σίγουρα θες να μπλοκάρεις ολόκληρο το {domain}; Συνήθως μερικά εστιασμένα μπλοκ ή αποσιωπήσεις επαρκούν και προτιμούνται.", + "confirmations.mute.confirm": "Αποσιώπηση", + "confirmations.mute.message": "Σίγουρα θες να αποσιωπήσεις τον/την {name};", + "confirmations.unfollow.confirm": "Διακοπή παρακολούθησης", + "confirmations.unfollow.message": "Σίγουρα θες να πάψεις να ακολουθείς τον/την {name};", + "embed.instructions": "Ενσωματώστε αυτή την κατάσταση στην ιστοσελίδα σας αντιγράφοντας τον παρακάτω κώδικα.", + "embed.preview": "Ορίστε πως θα φαίνεται:", + "emoji_button.activity": "Δραστηριότητα", + "emoji_button.custom": "Προσαρμοσμένα", + "emoji_button.flags": "Σημαίες", + "emoji_button.food": "Φαγητά & Ποτά", + "emoji_button.label": "Εισάγετε emoji", + "emoji_button.nature": "Φύση", + "emoji_button.not_found": "Ουδέν emojo!! (╯°□°)╯︵ ┻━┻", + "emoji_button.objects": "Αντικείμενα", + "emoji_button.people": "Άνθρωποι", + "emoji_button.recent": "Δημοφιλή", + "emoji_button.search": "Αναζήτηση…", + "emoji_button.search_results": "Αποτελέσματα αναζήτησης", + "emoji_button.symbols": "Σύμβολα", + "emoji_button.travel": "Ταξίδια & Τοποθεσίες", + "empty_column.community": "Η τοπική ροή είναι κενή. Γράψε κάτι δημόσιο παραμύθι ν' αρχινίσει!", + "empty_column.direct": "Δεν έχεις απευθείας μηνύματα ακόμα. Όταν στείλεις ή λάβεις κανένα, θα εμφανιστεί εδώ.", + "empty_column.hashtag": "Δεν υπάρχει ακόμα κάτι για αυτή την ταμπέλα.", + "empty_column.home": "Η τοπική σου ροή είναι κενή! Πήγαινε στο {public} ή κάνε αναζήτηση για να ξεκινήσεις και να γνωρίσεις άλλους χρήστες.", + "empty_column.home.public_timeline": "η δημόσια ροή", + "empty_column.list": "Δεν υπάρχει τίποτα σε αυτή τη λίστα ακόμα. Όταν τα μέλη της δημοσιεύσουν νέες καταστάσεις, θα εμφανιστούν εδώ", + "empty_column.notifications": "Δεν έχεις ειδοποιήσεις ακόμα. Αλληλεπίδρασε με άλλους χρήστες για να ξεκινήσεις την κουβέντα.", + "empty_column.public": "Δεν υπάρχει τίποτα εδώ! Γράψε κάτι δημόσιο, ή ακολούθησε χειροκίνητα χρήστες από άλλα instances για να το γεμίσεις", + "follow_request.authorize": "Ενέκρινε", + "follow_request.reject": "Απέρριψε", + "getting_started.appsshort": "Εφαρμογές", "getting_started.faq": "FAQ", - "getting_started.heading": "Getting started", - "getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}.", - "getting_started.userguide": "User Guide", - "home.column_settings.advanced": "Advanced", - "home.column_settings.basic": "Basic", - "home.column_settings.filter_regex": "Filter out by regular expressions", - "home.column_settings.show_reblogs": "Show boosts", - "home.column_settings.show_replies": "Show replies", - "home.settings": "Column settings", - "keyboard_shortcuts.back": "to navigate back", - "keyboard_shortcuts.boost": "to boost", - "keyboard_shortcuts.column": "to focus a status in one of the columns", - "keyboard_shortcuts.compose": "to focus the compose textarea", + "getting_started.heading": "Ξεκινώντας", + "getting_started.open_source_notice": "Το Mastodon είναι ελεύθερο λογισμικό. Μπορείς να συνεισφέρεις ή να αναφέρεις ζητήματα στο GitHub στο {github}.", + "getting_started.userguide": "Οδηγός Χρηστών", + "home.column_settings.advanced": "Προχωρημένα", + "home.column_settings.basic": "Βασικά", + "home.column_settings.filter_regex": "Φιλτράρετε μέσω regular expressions", + "home.column_settings.show_reblogs": "Εμφάνιση προωθήσεων", + "home.column_settings.show_replies": "Εμφάνιση απαντήσεων", + "home.settings": "Ρυθμίσεις στηλών", + "keyboard_shortcuts.back": "για επιστροφή πίσω", + "keyboard_shortcuts.boost": "για προώθηση", + "keyboard_shortcuts.column": "για εστίαση μιας κατάστασης σε μια από τις στήλες", + "keyboard_shortcuts.compose": "για εστίαση στην περιοχή κειμένου συγγραφής", "keyboard_shortcuts.description": "Description", - "keyboard_shortcuts.down": "to move down in the list", + "keyboard_shortcuts.down": "για κίνηση προς τα κάτω στη λίστα", "keyboard_shortcuts.enter": "to open status", - "keyboard_shortcuts.favourite": "to favourite", + "keyboard_shortcuts.favourite": "για σημείωση αγαπημένου", "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.hotkey": "Hotkey", - "keyboard_shortcuts.legend": "to display this legend", - "keyboard_shortcuts.mention": "to mention author", - "keyboard_shortcuts.reply": "to reply", - "keyboard_shortcuts.search": "to focus search", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toot": "to start a brand new toot", + "keyboard_shortcuts.hotkey": "Συντόμευση", + "keyboard_shortcuts.legend": "για να εμφανίσεις αυτόν τον οδηγό", + "keyboard_shortcuts.mention": "για να αναφέρεις το συγγραφέα", + "keyboard_shortcuts.reply": "για απάντηση", + "keyboard_shortcuts.search": "για εστίαση αναζήτησης", + "keyboard_shortcuts.toggle_hidden": "για εμφάνιση/απόκρυψη κειμένου πίσω από την προειδοποίηση", + "keyboard_shortcuts.toot": "για δημιουργία ολοκαίνουριου τουτ", "keyboard_shortcuts.unfocus": "to un-focus compose textarea/search", "keyboard_shortcuts.up": "to move up in the list", "lightbox.close": "Close", diff --git a/app/javascript/mastodon/locales/eo.json b/app/javascript/mastodon/locales/eo.json index 37587c14c..1ab6d2aa0 100644 --- a/app/javascript/mastodon/locales/eo.json +++ b/app/javascript/mastodon/locales/eo.json @@ -2,7 +2,7 @@ "account.block": "Bloki @{name}", "account.block_domain": "Kaŝi ĉion de {domain}", "account.blocked": "Blokita", - "account.direct": "Direct message @{name}", + "account.direct": "Rekte mesaĝi @{name}", "account.disclaimer_full": "Subaj informoj povas reflekti la profilon de la uzanto nekomplete.", "account.domain_blocked": "Domajno kaŝita", "account.edit_profile": "Redakti profilon", @@ -29,8 +29,8 @@ "account.unmute": "Malsilentigi @{name}", "account.unmute_notifications": "Malsilentigi sciigojn de @{name}", "account.view_full_profile": "Vidi plenan profilon", - "alert.unexpected.message": "An unexpected error occurred.", - "alert.unexpected.title": "Oops!", + "alert.unexpected.message": "Neatendita eraro okazis.", + "alert.unexpected.title": "Ups!", "boost_modal.combo": "Vi povas premi {combo} por preterpasi sekvafoje", "bundle_column_error.body": "Io misfunkciis en la ŝargado de ĉi tiu elemento.", "bundle_column_error.retry": "Bonvolu reprovi", @@ -40,8 +40,8 @@ "bundle_modal_error.retry": "Bonvolu reprovi", "column.blocks": "Blokitaj uzantoj", "column.community": "Loka tempolinio", - "column.direct": "Direct messages", - "column.domain_blocks": "Hidden domains", + "column.direct": "Rektaj mesaĝoj", + "column.domain_blocks": "Kaŝitaj domajnoj", "column.favourites": "Stelumoj", "column.follow_requests": "Petoj de sekvado", "column.home": "Hejmo", @@ -59,7 +59,7 @@ "column_header.unpin": "Depingli", "column_subheading.navigation": "Navigado", "column_subheading.settings": "Agordado", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", + "compose_form.direct_message_warning": "Tiu mesaĝo videblos nur por ĉiuj menciitaj uzantoj.", "compose_form.hashtag_warning": "Ĉi tiu mesaĝo ne estos listigita per ajna kradvorto. Nur publikaj mesaĝoj estas serĉeblaj per kradvortoj.", "compose_form.lock_disclaimer": "Via konta ne estas {locked}. Iu ajn povas sekvi vin por vidi viajn mesaĝojn, kiuj estas nur por sekvantoj.", "compose_form.lock_disclaimer.lock": "ŝlosita", @@ -101,7 +101,7 @@ "emoji_button.symbols": "Simboloj", "emoji_button.travel": "Vojaĝoj kaj lokoj", "empty_column.community": "La loka tempolinio estas malplena. Skribu ion por plenigi ĝin!", - "empty_column.direct": "You don't have any direct messages yet. When you send or receive one, it will show up here.", + "empty_column.direct": "Vi ankoraŭ ne havas rektan mesaĝon. Kiam vi sendos aŭ ricevos iun, ĝi aperos ĉi tie.", "empty_column.hashtag": "Ankoraŭ estas nenio per ĉi tiu kradvorto.", "empty_column.home": "Via hejma tempolinio estas malplena! Vizitu {public} aŭ uzu la serĉilon por renkonti aliajn uzantojn.", "empty_column.home.public_timeline": "la publikan tempolinion", @@ -135,7 +135,7 @@ "keyboard_shortcuts.mention": "por mencii la aŭtoron", "keyboard_shortcuts.reply": "por respondi", "keyboard_shortcuts.search": "por fokusigi la serĉilon", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", + "keyboard_shortcuts.toggle_hidden": "por montri/kaŝi tekston malantaŭ enhava averto", "keyboard_shortcuts.toot": "por komenci tute novan mesaĝon", "keyboard_shortcuts.unfocus": "por malfokusigi la tekstujon aŭ la serĉilon", "keyboard_shortcuts.up": "por iri supren en la listo", @@ -157,8 +157,8 @@ "mute_modal.hide_notifications": "Ĉu vi volas kaŝi la sciigojn el ĉi tiu uzanto?", "navigation_bar.blocks": "Blokitaj uzantoj", "navigation_bar.community_timeline": "Loka tempolinio", - "navigation_bar.direct": "Direct messages", - "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.direct": "Rektaj mesaĝoj", + "navigation_bar.domain_blocks": "Kaŝitaj domajnoj", "navigation_bar.edit_profile": "Redakti profilon", "navigation_bar.favourites": "Stelumoj", "navigation_bar.follow_requests": "Petoj de sekvado", @@ -242,10 +242,10 @@ "search_results.total": "{count, number} {count, plural, one {rezulto} other {rezultoj}}", "standalone.public_title": "Enrigardo…", "status.block": "Bloki @{name}", - "status.cancel_reblog_private": "Unboost", + "status.cancel_reblog_private": "Eksdiskonigi", "status.cannot_reblog": "Ĉi tiu mesaĝo ne diskonigeblas", "status.delete": "Forigi", - "status.direct": "Direct message @{name}", + "status.direct": "Rekte mesaĝi @{name}", "status.embed": "Enkorpigi", "status.favourite": "Stelumi", "status.load_more": "Ŝargi pli", @@ -258,7 +258,7 @@ "status.pin": "Alpingli profile", "status.pinned": "Alpinglita mesaĝo", "status.reblog": "Diskonigi", - "status.reblog_private": "Boost to original audience", + "status.reblog_private": "Diskonigi al la originala atentaro", "status.reblogged_by": "{name} diskonigis", "status.reply": "Respondi", "status.replyAll": "Respondi al la fadeno", @@ -276,7 +276,7 @@ "tabs_bar.home": "Hejmo", "tabs_bar.local_timeline": "Loka tempolinio", "tabs_bar.notifications": "Sciigoj", - "tabs_bar.search": "Search", + "tabs_bar.search": "Serĉi", "ui.beforeunload": "Via malneto perdiĝos se vi eliras de Mastodon.", "upload_area.title": "Altreni kaj lasi por alŝuti", "upload_button.label": "Aldoni aŭdovidaĵon", diff --git a/app/javascript/mastodon/locales/fr.json b/app/javascript/mastodon/locales/fr.json index a4af97dda..16bf4033c 100644 --- a/app/javascript/mastodon/locales/fr.json +++ b/app/javascript/mastodon/locales/fr.json @@ -13,7 +13,7 @@ "account.hide_reblogs": "Masquer les partages de @{name}", "account.media": "Média", "account.mention": "Mentionner", - "account.moved_to": "{name} a déménagé vers :", + "account.moved_to": "{name} a déménagé vers :", "account.mute": "Masquer @{name}", "account.mute_notifications": "Ignorer les notifications de @{name}", "account.muted": "Silencé", @@ -30,7 +30,7 @@ "account.unmute_notifications": "Réactiver les notifications de @{name}", "account.view_full_profile": "Afficher le profil complet", "alert.unexpected.message": "Une erreur non-attendue s'est produite.", - "alert.unexpected.title": "Oups !", + "alert.unexpected.title": "Oups !", "boost_modal.combo": "Vous pouvez appuyer sur {combo} pour pouvoir passer ceci, la prochaine fois", "bundle_column_error.body": "Une erreur s’est produite lors du chargement de ce composant.", "bundle_column_error.retry": "Réessayer", @@ -77,7 +77,7 @@ "confirmations.delete.confirm": "Supprimer", "confirmations.delete.message": "Confirmez-vous la suppression de ce pouet ?", "confirmations.delete_list.confirm": "Supprimer", - "confirmations.delete_list.message": "Êtes-vous sûr de vouloir supprimer définitivement cette liste ?", + "confirmations.delete_list.message": "Êtes-vous sûr de vouloir supprimer définitivement cette liste ?", "confirmations.domain_block.confirm": "Masquer le domaine entier", "confirmations.domain_block.message": "Êtes-vous vraiment, vraiment sûr⋅e de vouloir bloquer {domain} en entier ? Dans la plupart des cas, quelques blocages ou masquages ciblés sont suffisants et préférables.", "confirmations.mute.confirm": "Masquer", @@ -85,14 +85,14 @@ "confirmations.unfollow.confirm": "Ne plus suivre", "confirmations.unfollow.message": "Voulez-vous arrêter de suivre {name} ?", "embed.instructions": "Intégrez ce statut à votre site en copiant le code ci-dessous.", - "embed.preview": "Il apparaîtra comme cela :", + "embed.preview": "Il apparaîtra comme cela :", "emoji_button.activity": "Activités", "emoji_button.custom": "Personnalisés", "emoji_button.flags": "Drapeaux", "emoji_button.food": "Nourriture & Boisson", "emoji_button.label": "Insérer un émoji", "emoji_button.nature": "Nature", - "emoji_button.not_found": "Pas d'emojis !! (╯°□°)╯︵ ┻━┻", + "emoji_button.not_found": "Pas d'emojis !! (╯°□°)╯︵ ┻━┻", "emoji_button.objects": "Objets", "emoji_button.people": "Personnages", "emoji_button.recent": "Fréquemment utilisés", @@ -154,7 +154,7 @@ "media_gallery.toggle_visible": "Modifier la visibilité", "missing_indicator.label": "Non trouvé", "missing_indicator.sublabel": "Ressource introuvable", - "mute_modal.hide_notifications": "Masquer les notifications de cette personne ?", + "mute_modal.hide_notifications": "Masquer les notifications de cette personne ?", "navigation_bar.blocks": "Comptes bloqués", "navigation_bar.community_timeline": "Fil public local", "navigation_bar.direct": "Messages directs", @@ -177,9 +177,9 @@ "notifications.clear": "Nettoyer les notifications", "notifications.clear_confirmation": "Voulez-vous vraiment supprimer toutes vos notifications ?", "notifications.column_settings.alert": "Notifications locales", - "notifications.column_settings.favourite": "Favoris :", - "notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e·s :", - "notifications.column_settings.mention": "Mentions :", + "notifications.column_settings.favourite": "Favoris :", + "notifications.column_settings.follow": "Nouveaux⋅elles abonné⋅e·s :", + "notifications.column_settings.mention": "Mentions :", "notifications.column_settings.push": "Notifications push", "notifications.column_settings.push_meta": "Cet appareil", "notifications.column_settings.reblog": "Partages :", @@ -216,7 +216,7 @@ "privacy.unlisted.long": "Ne pas afficher dans les fils publics", "privacy.unlisted.short": "Non-listé", "regeneration_indicator.label": "Chargement…", - "regeneration_indicator.sublabel": "Le flux de votre page principale est en cours de préparation !", + "regeneration_indicator.sublabel": "Le flux de votre page principale est en cours de préparation !", "relative_time.days": "{number} j", "relative_time.hours": "{number} h", "relative_time.just_now": "à l’instant", @@ -224,8 +224,8 @@ "relative_time.seconds": "{number} s", "reply_indicator.cancel": "Annuler", "report.forward": "Transférer à {target}", - "report.forward_hint": "Le compte provient d'un autre serveur. Envoyez également une copie anonyme du rapport ?", - "report.hint": "Le rapport sera envoyé aux modérateurs de votre instance. Vous pouvez expliquer pourquoi vous signalez ce compte ci-dessous :", + "report.forward_hint": "Le compte provient d'un autre serveur. Envoyez également une copie anonyme du rapport ?", + "report.hint": "Le rapport sera envoyé aux modérateurs de votre instance. Vous pouvez expliquer pourquoi vous signalez ce compte ci-dessous :", "report.placeholder": "Commentaires additionnels", "report.submit": "Envoyer", "report.target": "Signalement", diff --git a/app/javascript/mastodon/locales/oc.json b/app/javascript/mastodon/locales/oc.json index d4836e9fe..c4cb996cf 100644 --- a/app/javascript/mastodon/locales/oc.json +++ b/app/javascript/mastodon/locales/oc.json @@ -110,7 +110,7 @@ "empty_column.public": "I a pas res aquí ! Escrivètz quicòm de public, o seguètz de personas d’autras instàncias per garnir lo flux public", "follow_request.authorize": "Autorizar", "follow_request.reject": "Regetar", - "getting_started.appsshort": "Apps", + "getting_started.appsshort": "Aplicacions", "getting_started.faq": "FAQ", "getting_started.heading": "Per començar", "getting_started.open_source_notice": "Mastodon es un logicial liure. Podètz contribuir e mandar vòstres comentaris e rapòrt de bug via {github} sus GitHub.", @@ -158,7 +158,7 @@ "navigation_bar.blocks": "Personas blocadas", "navigation_bar.community_timeline": "Flux public local", "navigation_bar.direct": "Messatges dirèctes", - "navigation_bar.domain_blocks": "Hidden domains", + "navigation_bar.domain_blocks": "Domenis amagats", "navigation_bar.edit_profile": "Modificar lo perfil", "navigation_bar.favourites": "Favorits", "navigation_bar.follow_requests": "Demandas d’abonament", diff --git a/app/javascript/mastodon/locales/sk.json b/app/javascript/mastodon/locales/sk.json index e5e826c96..d69648ccf 100644 --- a/app/javascript/mastodon/locales/sk.json +++ b/app/javascript/mastodon/locales/sk.json @@ -231,7 +231,7 @@ "report.target": "Nahlásenie {target}", "search.placeholder": "Hľadaj", "search_popout.search_format": "Pokročilé vyhľadávanie", - "search_popout.tips.full_text": "Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.", + "search_popout.tips.full_text": "Jednoduchý textový výpis statusov ktoré si napísal/a, ktoré si obľúbil/a, povýšil/a, alebo aj tých, v ktorých si bol/a spomenutý/á, a potom všetky zadaniu odpovedajúce prezívky, mená a haštagy.", "search_popout.tips.hashtag": "haštag", "search_popout.tips.status": "status", "search_popout.tips.text": "Jednoduchý text vráti zhodujúce sa mená, prezývky a hashtagy", diff --git a/app/javascript/mastodon/locales/whitelist_co.json b/app/javascript/mastodon/locales/whitelist_co.json new file mode 100644 index 000000000..0d4f101c7 --- /dev/null +++ b/app/javascript/mastodon/locales/whitelist_co.json @@ -0,0 +1,2 @@ +[ +] diff --git a/app/javascript/mastodon/reducers/timelines.js b/app/javascript/mastodon/reducers/timelines.js index dd675d78f..b09d78b0f 100644 --- a/app/javascript/mastodon/reducers/timelines.js +++ b/app/javascript/mastodon/reducers/timelines.js @@ -134,7 +134,7 @@ export default function timelines(state = initialState, action) { initialTimeline, map => map.update( 'items', - items => items.first() ? items : items.unshift(null) + items => items.first() ? items.unshift(null) : items ) ); default: diff --git a/app/javascript/mastodon/utils/html.js b/app/javascript/mastodon/utils/html.js new file mode 100644 index 000000000..0b646ce58 --- /dev/null +++ b/app/javascript/mastodon/utils/html.js @@ -0,0 +1,6 @@ +export const unescapeHTML = (html) => { + const wrapper = document.createElement('div'); + html = html.replace(/<br \/>|<br>|\n/g, ' '); + wrapper.innerHTML = html; + return wrapper.textContent; +}; diff --git a/app/javascript/mastodon/utils/resize_image.js b/app/javascript/mastodon/utils/resize_image.js index 6442eda38..54459de3e 100644 --- a/app/javascript/mastodon/utils/resize_image.js +++ b/app/javascript/mastodon/utils/resize_image.js @@ -1,3 +1,5 @@ +import EXIF from 'exif-js'; + const MAX_IMAGE_DIMENSION = 1280; const getImageUrl = inputFile => new Promise((resolve, reject) => { @@ -28,6 +30,84 @@ const loadImage = inputFile => new Promise((resolve, reject) => { }).catch(reject); }); +const getOrientation = (img, type = 'image/png') => new Promise(resolve => { + if (type !== 'image/jpeg') { + resolve(1); + return; + } + + EXIF.getData(img, () => { + const orientation = EXIF.getTag(img, 'Orientation'); + resolve(orientation); + }); +}); + +const processImage = (img, { width, height, orientation, type = 'image/png' }) => new Promise(resolve => { + const canvas = document.createElement('canvas'); + [canvas.width, canvas.height] = orientation < 5 ? [width, height] : [height, width]; + + const context = canvas.getContext('2d'); + + switch (orientation) { + case 2: + context.translate(width, 0); + break; + case 3: + context.translate(width, height); + break; + case 4: + context.translate(0, height); + break; + case 5: + context.rotate(0.5 * Math.PI); + context.translate(1, -1); + break; + case 6: + context.rotate(0.5 * Math.PI); + context.translate(0, -height); + break; + case 7: + context.rotate(0.5, Math.PI); + context.translate(width, -height); + break; + case 8: + context.rotate(-0.5, Math.PI); + context.translate(-width, 0); + break; + } + + context.drawImage(img, 0, 0, width, height); + + canvas.toBlob(resolve, type); +}); + +const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => { + const { width, height } = img; + + let newWidth, newHeight; + + if (width > height) { + newHeight = height * MAX_IMAGE_DIMENSION / width; + newWidth = MAX_IMAGE_DIMENSION; + } else if (height > width) { + newWidth = width * MAX_IMAGE_DIMENSION / height; + newHeight = MAX_IMAGE_DIMENSION; + } else { + newWidth = MAX_IMAGE_DIMENSION; + newHeight = MAX_IMAGE_DIMENSION; + } + + getOrientation(img, type) + .then(orientation => processImage(img, { + width: newWidth, + height: newHeight, + orientation, + type, + })) + .then(resolve) + .catch(reject); +}); + export default inputFile => new Promise((resolve, reject) => { if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') { resolve(inputFile); @@ -35,32 +115,13 @@ export default inputFile => new Promise((resolve, reject) => { } loadImage(inputFile).then(img => { - const canvas = document.createElement('canvas'); - const { width, height } = img; - - let newWidth, newHeight; - - if (width < MAX_IMAGE_DIMENSION && height < MAX_IMAGE_DIMENSION) { + if (img.width < MAX_IMAGE_DIMENSION && img.height < MAX_IMAGE_DIMENSION) { resolve(inputFile); return; } - if (width > height) { - newHeight = height * MAX_IMAGE_DIMENSION / width; - newWidth = MAX_IMAGE_DIMENSION; - } else if (height > width) { - newWidth = width * MAX_IMAGE_DIMENSION / height; - newHeight = MAX_IMAGE_DIMENSION; - } else { - newWidth = MAX_IMAGE_DIMENSION; - newHeight = MAX_IMAGE_DIMENSION; - } - - canvas.width = newWidth; - canvas.height = newHeight; - - canvas.getContext('2d').drawImage(img, 0, 0, newWidth, newHeight); - - canvas.toBlob(resolve, inputFile.type); + resizeImage(img, inputFile.type) + .then(resolve) + .catch(() => resolve(inputFile)); }).catch(reject); }); diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index 3377c2329..38aaf895f 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -7,7 +7,6 @@ function main() { const { getLocale } = require('../mastodon/locales'); const { localeData } = getLocale(); const VideoContainer = require('../mastodon/containers/video_container').default; - const CardContainer = require('../mastodon/containers/card_container').default; const React = require('react'); const ReactDOM = require('react-dom'); @@ -57,10 +56,16 @@ function main() { ReactDOM.render(<VideoContainer locale={locale} {...props} />, content); }); - [].forEach.call(document.querySelectorAll('[data-component="Card"]'), (content) => { - const props = JSON.parse(content.getAttribute('data-props')); - ReactDOM.render(<CardContainer locale={locale} {...props} />, content); - }); + const cards = document.querySelectorAll('[data-component="Card"]'); + + if (cards.length > 0) { + import(/* webpackChunkName: "containers/cards_container" */ '../mastodon/containers/cards_container').then(({ default: CardsContainer }) => { + const content = document.createElement('div'); + + ReactDOM.render(<CardsContainer locale={locale} cards={cards} />, content); + document.body.appendChild(content); + }).catch(error => console.error(error)); + } const mediaGalleries = document.querySelectorAll('[data-component="MediaGallery"]'); diff --git a/app/javascript/styles/mastodon/accounts.scss b/app/javascript/styles/mastodon/accounts.scss index c2d0de4b9..b063ca52d 100644 --- a/app/javascript/styles/mastodon/accounts.scss +++ b/app/javascript/styles/mastodon/accounts.scss @@ -565,36 +565,41 @@ } .account__header__fields { - border-collapse: collapse; padding: 0; margin: 15px -15px -15px; border: 0 none; border-top: 1px solid lighten($ui-base-color, 4%); border-bottom: 1px solid lighten($ui-base-color, 4%); + font-size: 14px; + line-height: 20px; - th, - td { - padding: 15px; - padding-left: 15px; - border: 0 none; + dl { + display: flex; border-bottom: 1px solid lighten($ui-base-color, 4%); - vertical-align: middle; } - th { - padding-left: 15px; - font-weight: 500; + dt, + dd { + box-sizing: border-box; + padding: 14px; text-align: center; - width: 94px; + max-height: 48px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + dt { + font-weight: 500; + width: 120px; + flex: 0 0 auto; color: $secondary-text-color; background: rgba(darken($ui-base-color, 8%), 0.5); } - td { + dd { + flex: 1 1 auto; color: $darker-text-color; - text-align: center; - width: 100%; - padding-left: 0; } a { @@ -608,12 +613,7 @@ } } - tr { - &:last-child { - th, - td { - border-bottom: 0; - } - } + dl:last-child { + border-bottom: 0; } } diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index a6cc8b62b..1948a2a23 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -336,7 +336,8 @@ } } -.simple_form.new_report_note { +.simple_form.new_report_note, +.simple_form.new_account_moderation_note { max-width: 100%; } diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index a982585c3..70ef96aa7 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -4033,7 +4033,7 @@ a.status-card { .report-modal__statuses { flex: 1 1 auto; min-height: 20vh; - max-height: 40vh; + max-height: 80vh; overflow-y: auto; overflow-x: hidden; @@ -5159,38 +5159,45 @@ noscript { } } +.account__header .roles { + margin-top: 20px; + margin-bottom: 20px; + padding: 0 15px; +} + .account__header .account__header__fields { font-size: 14px; line-height: 20px; overflow: hidden; - border-collapse: collapse; margin: 20px -10px -20px; border-bottom: 0; - tr { + dl { border-top: 1px solid lighten($ui-base-color, 8%); - text-align: center; + display: flex; } - th, - td { + dt, + dd { + box-sizing: border-box; padding: 14px 20px; - vertical-align: middle; - max-height: 40px; + text-align: center; + max-height: 48px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } - th { + dt { color: $darker-text-color; background: darken($ui-base-color, 4%); - max-width: 120px; + width: 120px; + flex: 0 0 auto; font-weight: 500; } - td { - flex: auto; + dd { + flex: 1 1 auto; color: $primary-text-color; background: $ui-base-color; } diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss index 9d5ab66a4..c40b38a5a 100644 --- a/app/javascript/styles/mastodon/containers.scss +++ b/app/javascript/styles/mastodon/containers.scss @@ -60,6 +60,7 @@ } } +.card-standalone__body, .media-gallery-standalone__body { overflow: hidden; } diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index f97890187..de16784a8 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -87,6 +87,10 @@ code { align-items: flex-start; } + &.file .label_input { + flex-wrap: nowrap; + } + &.select .label_input { align-items: initial; } |