Adding german localization
This commit is contained in:
parent
c1be1ac7c6
commit
85d1b74ac3
26 changed files with 488 additions and 51 deletions
|
@ -2,7 +2,15 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import IconButton from './icon_button';
|
import IconButton from './icon_button';
|
||||||
import DropdownMenu from './dropdown_menu';
|
import DropdownMenu from './dropdown_menu';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
|
mention: { id: 'status.mention', defaultMessage: 'Mention' },
|
||||||
|
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
||||||
|
reblog: { id: 'status.reblog', defaultMessage: 'Reblog' },
|
||||||
|
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }
|
||||||
|
});
|
||||||
|
|
||||||
const StatusActionBar = React.createClass({
|
const StatusActionBar = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
|
@ -41,16 +49,16 @@ const StatusActionBar = React.createClass({
|
||||||
let menu = [];
|
let menu = [];
|
||||||
|
|
||||||
if (status.getIn(['account', 'id']) === me) {
|
if (status.getIn(['account', 'id']) === me) {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'status.delete', defaultMessage: 'Delete' }), action: this.handleDeleteClick });
|
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||||
} else {
|
} else {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'status.mention', defaultMessage: 'Mention' }), action: this.handleMentionClick });
|
menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ marginTop: '10px', overflow: 'hidden' }}>
|
<div style={{ marginTop: '10px', overflow: 'hidden' }}>
|
||||||
<div style={{ float: 'left', marginRight: '18px'}}><IconButton title={intl.formatMessage({ id: 'status.reply', defaultMessage: 'Reply' })} icon='reply' onClick={this.handleReplyClick} /></div>
|
<div style={{ float: 'left', marginRight: '18px'}}><IconButton title={intl.formatMessage(messages.reply)} icon='reply' onClick={this.handleReplyClick} /></div>
|
||||||
<div style={{ float: 'left', marginRight: '18px'}}><IconButton active={status.get('reblogged')} title={intl.formatMessage({ id: 'status.reblog', defaultMessage: 'Reblog' })} icon='retweet' onClick={this.handleReblogClick} /></div>
|
<div style={{ float: 'left', marginRight: '18px'}}><IconButton active={status.get('reblogged')} title={intl.formatMessage(messages.reblog)} icon='retweet' onClick={this.handleReblogClick} /></div>
|
||||||
<div style={{ float: 'left', marginRight: '18px'}}><IconButton active={status.get('favourited')} title={intl.formatMessage({ id: 'status.favourite', defaultMessage: 'Favourite' })} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div>
|
<div style={{ float: 'left', marginRight: '18px'}}><IconButton active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div>
|
||||||
|
|
||||||
<div style={{ width: '18px', height: '18px', float: 'left' }}>
|
<div style={{ width: '18px', height: '18px', float: 'left' }}>
|
||||||
<DropdownMenu items={menu} icon='ellipsis-h' size={18} />
|
<DropdownMenu items={menu} icon='ellipsis-h' size={18} />
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import IconButton from './icon_button';
|
import IconButton from './icon_button';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
toggle_sound: { id: 'video_player.toggle_sound', defaultMessage: 'Toggle sound' }
|
||||||
|
});
|
||||||
|
|
||||||
const videoStyle = {
|
const videoStyle = {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
@ -64,7 +68,7 @@ const VideoPlayer = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ cursor: 'default', marginTop: '8px', overflow: 'hidden', width: `${width}px`, height: `${height}px`, boxSizing: 'border-box', background: '#000', position: 'relative' }}>
|
<div style={{ cursor: 'default', marginTop: '8px', overflow: 'hidden', width: `${width}px`, height: `${height}px`, boxSizing: 'border-box', background: '#000', position: 'relative' }}>
|
||||||
<div style={muteStyle}><IconButton title={intl.formatMessage({ id: 'video_player.toggle_sound', defaultMessage: 'Toggle sound' })} icon={this.state.muted ? 'volume-up' : 'volume-off'} onClick={this.handleClick} /></div>
|
<div style={muteStyle}><IconButton title={intl.formatMessage(messages.toggle_sound)} icon={this.state.muted ? 'volume-up' : 'volume-off'} onClick={this.handleClick} /></div>
|
||||||
<video src={media.get('url')} autoPlay='true' loop={true} muted={this.state.muted} style={videoStyle} onClick={this.handleVideoClick} />
|
<video src={media.get('url')} autoPlay='true' loop={true} muted={this.state.muted} style={videoStyle} onClick={this.handleVideoClick} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -34,6 +34,8 @@ import Favourites from '../features/favourites';
|
||||||
import HashtagTimeline from '../features/hashtag_timeline';
|
import HashtagTimeline from '../features/hashtag_timeline';
|
||||||
import { IntlProvider, addLocaleData } from 'react-intl';
|
import { IntlProvider, addLocaleData } from 'react-intl';
|
||||||
import en from 'react-intl/locale-data/en';
|
import en from 'react-intl/locale-data/en';
|
||||||
|
import de from 'react-intl/locale-data/de';
|
||||||
|
import getMessagesForLocale from '../locales';
|
||||||
|
|
||||||
const store = configureStore();
|
const store = configureStore();
|
||||||
|
|
||||||
|
@ -41,7 +43,7 @@ const browserHistory = useRouterHistory(createBrowserHistory)({
|
||||||
basename: '/web'
|
basename: '/web'
|
||||||
});
|
});
|
||||||
|
|
||||||
addLocaleData([...en]);
|
addLocaleData([...en, ...de]);
|
||||||
|
|
||||||
const Mastodon = React.createClass({
|
const Mastodon = React.createClass({
|
||||||
|
|
||||||
|
@ -89,7 +91,7 @@ const Mastodon = React.createClass({
|
||||||
const { locale } = this.props;
|
const { locale } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IntlProvider locale={locale}>
|
<IntlProvider locale={locale} messages={getMessagesForLocale(locale)}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<Router history={browserHistory} render={applyRouterMiddleware(useScroll())}>
|
<Router history={browserHistory} render={applyRouterMiddleware(useScroll())}>
|
||||||
<Route path='/' component={UI}>
|
<Route path='/' component={UI}>
|
||||||
|
|
|
@ -2,7 +2,17 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import DropdownMenu from '../../../components/dropdown_menu';
|
import DropdownMenu from '../../../components/dropdown_menu';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { injectIntl, FormattedMessage, FormattedNumber } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
mention: { id: 'account.mention', defaultMessage: 'Mention' },
|
||||||
|
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
|
||||||
|
unblock: { id: 'account.unblock', defaultMessage: 'Unblock' },
|
||||||
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
|
block: { id: 'account.block', defaultMessage: 'Block' },
|
||||||
|
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||||
|
block: { id: 'account.block', defaultMessage: 'Block' }
|
||||||
|
});
|
||||||
|
|
||||||
const outerStyle = {
|
const outerStyle = {
|
||||||
borderTop: '1px solid #363c4b',
|
borderTop: '1px solid #363c4b',
|
||||||
|
@ -41,18 +51,18 @@ const ActionBar = React.createClass({
|
||||||
|
|
||||||
let menu = [];
|
let menu = [];
|
||||||
|
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.mention', defaultMessage: 'Mention' }), action: this.props.onMention });
|
menu.push({ text: intl.formatMessage(messages.mention), action: this.props.onMention });
|
||||||
|
|
||||||
if (account.get('id') === me) {
|
if (account.get('id') === me) {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.edit_profile', defaultMessage: 'Edit profile' }), href: '/settings/profile' });
|
menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' });
|
||||||
} else if (account.getIn(['relationship', 'blocking'])) {
|
} else if (account.getIn(['relationship', 'blocking'])) {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.unblock', defaultMessage: 'Unblock' }), action: this.props.onBlock });
|
menu.push({ text: intl.formatMessage(messages.unblock), action: this.props.onBlock });
|
||||||
} else if (account.getIn(['relationship', 'following'])) {
|
} else if (account.getIn(['relationship', 'following'])) {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.unfollow', defaultMessage: 'Unfollow' }), action: this.props.onFollow });
|
menu.push({ text: intl.formatMessage(messages.unfollow), action: this.props.onFollow });
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.block', defaultMessage: 'Block' }), action: this.props.onBlock });
|
menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock });
|
||||||
} else {
|
} else {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.follow', defaultMessage: 'Follow' }), action: this.props.onFollow });
|
menu.push({ text: intl.formatMessage(messages.follow), action: this.props.onFollow });
|
||||||
menu.push({ text: intl.formatMessage({ id: 'account.block', defaultMessage: 'Block' }), action: this.props.onBlock });
|
menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,6 +2,7 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import emojify from '../../../emoji';
|
import emojify from '../../../emoji';
|
||||||
import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser';
|
import escapeTextContentForBrowser from 'react/lib/escapeTextContentForBrowser';
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
const Header = React.createClass({
|
const Header = React.createClass({
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ const Header = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
|
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
|
||||||
info = <span style={{ position: 'absolute', top: '10px', right: '10px', opacity: '0.7', display: 'inline-block', verticalAlign: 'top', background: 'rgba(0, 0, 0, 0.4)', color: '#fff', textTransform: 'uppercase', fontSize: '11px', fontWeight: '500', padding: '4px', borderRadius: '4px' }}>Follows you</span>
|
info = <span style={{ position: 'absolute', top: '10px', right: '10px', opacity: '0.7', display: 'inline-block', verticalAlign: 'top', background: 'rgba(0, 0, 0, 0.4)', color: '#fff', textTransform: 'uppercase', fontSize: '11px', fontWeight: '500', padding: '4px', borderRadius: '4px' }}><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = { __html: emojify(account.get('note')) };
|
const content = { __html: emojify(account.get('note')) };
|
||||||
|
|
|
@ -8,7 +8,12 @@ import Autosuggest from 'react-autosuggest';
|
||||||
import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container';
|
import AutosuggestAccountContainer from '../../compose/containers/autosuggest_account_container';
|
||||||
import { debounce } from 'react-decoration';
|
import { debounce } from 'react-decoration';
|
||||||
import UploadButtonContainer from '../containers/upload_button_container';
|
import UploadButtonContainer from '../containers/upload_button_container';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
|
||||||
|
publish: { id: 'compose_form.publish', defaultMessage: 'Publish' }
|
||||||
|
});
|
||||||
|
|
||||||
const getTokenForSuggestions = (str, caretPosition) => {
|
const getTokenForSuggestions = (str, caretPosition) => {
|
||||||
let word;
|
let word;
|
||||||
|
@ -53,7 +58,7 @@ const textareaStyle = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderInputComponent = inputProps => (
|
const renderInputComponent = inputProps => (
|
||||||
<textarea {...inputProps} placeholder='What is on your mind?' className='compose-form__textarea' style={textareaStyle} />
|
<textarea {...inputProps} className='compose-form__textarea' style={textareaStyle} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const ComposeForm = React.createClass({
|
const ComposeForm = React.createClass({
|
||||||
|
@ -144,7 +149,7 @@ const ComposeForm = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
placeholder: intl.formatMessage({ id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' }),
|
placeholder: intl.formatMessage(messages.placeholder),
|
||||||
value: this.props.text,
|
value: this.props.text,
|
||||||
onKeyUp: this.handleKeyUp,
|
onKeyUp: this.handleKeyUp,
|
||||||
onChange: this.handleChange,
|
onChange: this.handleChange,
|
||||||
|
@ -169,7 +174,7 @@ const ComposeForm = React.createClass({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{ marginTop: '10px', overflow: 'hidden' }}>
|
<div style={{ marginTop: '10px', overflow: 'hidden' }}>
|
||||||
<div style={{ float: 'right' }}><Button text={intl.formatMessage({ id: 'compose_form.publish', defaultMessage: 'Publish' })} onClick={this.handleSubmit} disabled={disabled} /></div>
|
<div style={{ float: 'right' }}><Button text={intl.formatMessage(messages.publish)} onClick={this.handleSubmit} disabled={disabled} /></div>
|
||||||
<div style={{ float: 'right', marginRight: '16px', lineHeight: '36px' }}><CharacterCounter max={500} text={this.props.text} /></div>
|
<div style={{ float: 'right', marginRight: '16px', lineHeight: '36px' }}><CharacterCounter max={500} text={this.props.text} /></div>
|
||||||
<UploadButtonContainer style={{ paddingTop: '4px' }} />
|
<UploadButtonContainer style={{ paddingTop: '4px' }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,11 @@ import Avatar from '../../../components/avatar';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import DisplayName from '../../../components/display_name';
|
import DisplayName from '../../../components/display_name';
|
||||||
import emojify from '../../../emoji';
|
import emojify from '../../../emoji';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' }
|
||||||
|
});
|
||||||
|
|
||||||
const ReplyIndicator = React.createClass({
|
const ReplyIndicator = React.createClass({
|
||||||
|
|
||||||
|
@ -37,7 +41,7 @@ const ReplyIndicator = React.createClass({
|
||||||
return (
|
return (
|
||||||
<div style={{ background: '#9baec8', padding: '10px' }}>
|
<div style={{ background: '#9baec8', padding: '10px' }}>
|
||||||
<div style={{ overflow: 'hidden', marginBottom: '5px' }}>
|
<div style={{ overflow: 'hidden', marginBottom: '5px' }}>
|
||||||
<div style={{ float: 'right', lineHeight: '24px' }}><IconButton title={intl.formatMessage({ id: 'reply_indicator.cancel', defaultMessage: 'Cancel' })} icon='times' onClick={this.handleClick} /></div>
|
<div style={{ float: 'right', lineHeight: '24px' }}><IconButton title={intl.formatMessage(messages.cancel)} icon='times' onClick={this.handleClick} /></div>
|
||||||
|
|
||||||
<a href={this.props.status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='reply-indicator__display-name' style={{ display: 'block', maxWidth: '100%', paddingRight: '25px', color: '#282c37', textDecoration: 'none', overflow: 'hidden', lineHeight: '24px' }}>
|
<a href={this.props.status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='reply-indicator__display-name' style={{ display: 'block', maxWidth: '100%', paddingRight: '25px', color: '#282c37', textDecoration: 'none', overflow: 'hidden', lineHeight: '24px' }}>
|
||||||
<div style={{ float: 'left', marginRight: '5px' }}><Avatar size={24} src={this.props.status.getIn(['account', 'avatar'])} /></div>
|
<div style={{ float: 'left', marginRight: '5px' }}><Avatar size={24} src={this.props.status.getIn(['account', 'avatar'])} /></div>
|
||||||
|
|
|
@ -3,7 +3,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Autosuggest from 'react-autosuggest';
|
import Autosuggest from 'react-autosuggest';
|
||||||
import AutosuggestAccountContainer from '../containers/autosuggest_account_container';
|
import AutosuggestAccountContainer from '../containers/autosuggest_account_container';
|
||||||
import { debounce } from 'react-decoration';
|
import { debounce } from 'react-decoration';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' }
|
||||||
|
});
|
||||||
|
|
||||||
const getSuggestionValue = suggestion => suggestion.value;
|
const getSuggestionValue = suggestion => suggestion.value;
|
||||||
|
|
||||||
|
@ -16,7 +20,7 @@ const renderSuggestion = suggestion => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSectionTitle = section => (
|
const renderSectionTitle = section => (
|
||||||
<strong>{section.title}</strong>
|
<strong><FormattedMessage id={`search.${section.title}`} defaultMessage={section.title} /></strong>
|
||||||
);
|
);
|
||||||
|
|
||||||
const getSectionSuggestions = section => section.items;
|
const getSectionSuggestions = section => section.items;
|
||||||
|
@ -95,7 +99,7 @@ const Search = React.createClass({
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
placeholder: this.props.intl.formatMessage({ id: 'search.placeholder', defaultMessage: 'Search' }),
|
placeholder: this.props.intl.formatMessage(messages.placeholder),
|
||||||
value: this.props.value,
|
value: this.props.value,
|
||||||
onChange: this.onChange,
|
onChange: this.onChange,
|
||||||
style: inputStyle
|
style: inputStyle
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
upload: { id: 'upload_button.label', defaultMessage: 'Add media' }
|
||||||
|
});
|
||||||
|
|
||||||
const UploadButton = React.createClass({
|
const UploadButton = React.createClass({
|
||||||
|
|
||||||
|
@ -31,7 +35,7 @@ const UploadButton = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={this.props.style}>
|
<div style={this.props.style}>
|
||||||
<IconButton icon='photo' title={intl.formatMessage({ id: 'upload_button.label', defaultMessage: 'Add media' })} disabled={this.props.disabled} onClick={this.handleClick} size={24} />
|
<IconButton icon='photo' title={intl.formatMessage(messages.upload)} disabled={this.props.disabled} onClick={this.handleClick} size={24} />
|
||||||
<input ref={this.setRef} type='file' multiple={false} onChange={this.handleChange} disabled={this.props.disabled} style={{ display: 'none' }} />
|
<input ref={this.setRef} type='file' multiple={false} onChange={this.handleChange} disabled={this.props.disabled} style={{ display: 'none' }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
undo: { id: 'upload_form.undo', defaultMessage: 'Undo' }
|
||||||
|
});
|
||||||
|
|
||||||
const UploadForm = React.createClass({
|
const UploadForm = React.createClass({
|
||||||
|
|
||||||
|
@ -19,7 +23,7 @@ const UploadForm = React.createClass({
|
||||||
const uploads = this.props.media.map(attachment => (
|
const uploads = this.props.media.map(attachment => (
|
||||||
<div key={attachment.get('id')} style={{ borderRadius: '4px', marginBottom: '10px' }} className='transparent-background'>
|
<div key={attachment.get('id')} style={{ borderRadius: '4px', marginBottom: '10px' }} className='transparent-background'>
|
||||||
<div style={{ width: '100%', height: '100px', borderRadius: '4px', background: `url(${attachment.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }}>
|
<div style={{ width: '100%', height: '100px', borderRadius: '4px', background: `url(${attachment.get('preview_url')}) no-repeat center`, backgroundSize: 'cover' }}>
|
||||||
<IconButton icon='times' title={intl.formatMessage({ id: 'upload_form.undo', defaultMessage: 'Undo' })} size={36} onClick={this.props.onRemoveFile.bind(this, attachment.get('id'))} />
|
<IconButton icon='times' title={intl.formatMessage(messages.undo)} size={36} onClick={this.props.onRemoveFile.bind(this, attachment.get('id'))} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|
|
@ -4,7 +4,11 @@ import Avatar from '../../../components/avatar';
|
||||||
import DisplayName from '../../../components/display_name';
|
import DisplayName from '../../../components/display_name';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
follow: { id: 'account.follow', defaultMessage: 'Follow' }
|
||||||
|
});
|
||||||
|
|
||||||
const outerStyle = {
|
const outerStyle = {
|
||||||
padding: '10px',
|
padding: '10px',
|
||||||
|
@ -69,7 +73,7 @@ const Account = React.createClass({
|
||||||
|
|
||||||
buttons = (
|
buttons = (
|
||||||
<div style={buttonsStyle}>
|
<div style={buttonsStyle}>
|
||||||
<IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage({ id: 'account.follow', defaultMessage: 'Follow' })} onClick={this.handleFollow} active={following} />
|
<IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(messages.follow)} onClick={this.handleFollow} active={following} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,11 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import StatusListContainer from '../ui/containers/status_list_container';
|
import StatusListContainer from '../ui/containers/status_list_container';
|
||||||
import Column from '../ui/components/column';
|
import Column from '../ui/components/column';
|
||||||
import { refreshTimeline } from '../../actions/timelines';
|
import { refreshTimeline } from '../../actions/timelines';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'column.home', defaultMessage: 'Home' }
|
||||||
|
});
|
||||||
|
|
||||||
const HomeTimeline = React.createClass({
|
const HomeTimeline = React.createClass({
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ const HomeTimeline = React.createClass({
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column icon='home' heading={intl.formatMessage({ id: 'column.home', defaultMessage: 'Home' })}>
|
<Column icon='home' heading={intl.formatMessage(messages.title)}>
|
||||||
<StatusListContainer {...this.props} type='home' />
|
<StatusListContainer {...this.props} type='home' />
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,7 +3,11 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import StatusListContainer from '../ui/containers/status_list_container';
|
import StatusListContainer from '../ui/containers/status_list_container';
|
||||||
import Column from '../ui/components/column';
|
import Column from '../ui/components/column';
|
||||||
import { refreshTimeline } from '../../actions/timelines';
|
import { refreshTimeline } from '../../actions/timelines';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'column.mentions', defaultMessage: 'Mentions' }
|
||||||
|
});
|
||||||
|
|
||||||
const MentionsTimeline = React.createClass({
|
const MentionsTimeline = React.createClass({
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ const MentionsTimeline = React.createClass({
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column icon='at' heading={intl.formatMessage({ id: 'column.mentions', defaultMessage: 'Mentions' })}>
|
<Column icon='at' heading={intl.formatMessage(messages.title)}>
|
||||||
<StatusListContainer {...this.props} type='mentions' />
|
<StatusListContainer {...this.props} type='mentions' />
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,11 @@ import {
|
||||||
updateTimeline,
|
updateTimeline,
|
||||||
deleteFromTimelines
|
deleteFromTimelines
|
||||||
} from '../../actions/timelines';
|
} from '../../actions/timelines';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'column.public', defaultMessage: 'Public' }
|
||||||
|
});
|
||||||
|
|
||||||
const PublicTimeline = React.createClass({
|
const PublicTimeline = React.createClass({
|
||||||
|
|
||||||
|
@ -48,7 +52,7 @@ const PublicTimeline = React.createClass({
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column icon='globe' heading={intl.formatMessage({ id: 'column.public', defaultMessage: 'Public' })}>
|
<Column icon='globe' heading={intl.formatMessage(messages.title)}>
|
||||||
<StatusListContainer type='public' />
|
<StatusListContainer type='public' />
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,15 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import IconButton from '../../../components/icon_button';
|
import IconButton from '../../../components/icon_button';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import DropdownMenu from '../../../components/dropdown_menu';
|
import DropdownMenu from '../../../components/dropdown_menu';
|
||||||
import { injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
|
mention: { id: 'status.mention', defaultMessage: 'Mention' },
|
||||||
|
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
||||||
|
reblog: { id: 'status.reblog', defaultMessage: 'Reblog' },
|
||||||
|
favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }
|
||||||
|
});
|
||||||
|
|
||||||
const ActionBar = React.createClass({
|
const ActionBar = React.createClass({
|
||||||
|
|
||||||
|
@ -44,16 +52,16 @@ const ActionBar = React.createClass({
|
||||||
let menu = [];
|
let menu = [];
|
||||||
|
|
||||||
if (me === status.getIn(['account', 'id'])) {
|
if (me === status.getIn(['account', 'id'])) {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'status.delete', defaultMessage: 'Delete' }), action: this.handleDeleteClick });
|
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||||
} else {
|
} else {
|
||||||
menu.push({ text: intl.formatMessage({ id: 'status.mention', defaultMessage: 'Mention' }), action: this.handleMentionClick });
|
menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick });
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ background: '#2f3441', display: 'flex', flexDirection: 'row', borderTop: '1px solid #363c4b', borderBottom: '1px solid #363c4b', padding: '10px 0' }}>
|
<div style={{ background: '#2f3441', display: 'flex', flexDirection: 'row', borderTop: '1px solid #363c4b', borderBottom: '1px solid #363c4b', padding: '10px 0' }}>
|
||||||
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton title={intl.formatMessage({ id: 'status.reply', defaultMessage: 'Reply' })} icon='reply' onClick={this.handleReplyClick} /></div>
|
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton title={intl.formatMessage(messages.reply)} icon='reply' onClick={this.handleReplyClick} /></div>
|
||||||
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton active={status.get('reblogged')} title={intl.formatMessage({ id: 'status.reblog', defaultMessage: 'Reblog' })} icon='retweet' onClick={this.handleReblogClick} /></div>
|
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton active={status.get('reblogged')} title={intl.formatMessage(messages.reblog)} icon='retweet' onClick={this.handleReblogClick} /></div>
|
||||||
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton active={status.get('favourited')} title={intl.formatMessage({ id: 'status.favourite', defaultMessage: 'Favourite' })} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div>
|
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><IconButton active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} activeStyle={{ color: '#ca8f04' }} /></div>
|
||||||
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><DropdownMenu size={18} icon='ellipsis-h' items={menu} /></div>
|
<div style={{ flex: '1 1 auto', textAlign: 'center' }}><DropdownMenu size={18} icon='ellipsis-h' items={menu} /></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
48
app/assets/javascripts/components/locales/de.jsx
Normal file
48
app/assets/javascripts/components/locales/de.jsx
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
const en = {
|
||||||
|
"column_back_button.label": "Zurück",
|
||||||
|
"lightbox.close": "Schließen",
|
||||||
|
"loading_indicator.label": "Lade...",
|
||||||
|
"status.mention": "Erwähnen",
|
||||||
|
"status.delete": "Löschen",
|
||||||
|
"status.reply": "Antworten",
|
||||||
|
"status.reblog": "Teilen",
|
||||||
|
"status.favourite": "Favorisieren",
|
||||||
|
"status.reblogged_by": "{name} teilte",
|
||||||
|
"video_player.toggle_sound": "Ton umschalten",
|
||||||
|
"account.mention": "Erwähnen",
|
||||||
|
"account.edit_profile": "Profil bearbeiten",
|
||||||
|
"account.unblock": "Entblocken",
|
||||||
|
"account.unfollow": "Entfolgen",
|
||||||
|
"account.block": "Blocken",
|
||||||
|
"account.follow": "Folgen",
|
||||||
|
"account.posts": "Beiträge",
|
||||||
|
"account.follows": "Folgt",
|
||||||
|
"account.followers": "Folger",
|
||||||
|
"account.follows_you": "Folgt dir",
|
||||||
|
"getting_started.heading": "Erste Schritte",
|
||||||
|
"getting_started.about_addressing": "Du kannst Leuten folgen, falls du ihren Nutzernamen und ihre Domain kennst, in dem du eine e-mail-artige Addresse in das Suchfeld oben an der Seite eingibst.",
|
||||||
|
"getting_started.about_shortcuts": "Falls der Zielnutzer an derselben Domain ist wie du, funktioniert der Nutzername auch alleine. Das gilt auch für Erwähnungen in Beiträgen.",
|
||||||
|
"getting_started.about_developer": "Der Entwickler des Projekts kann unter Gargron@mastodon.social gefunden werden",
|
||||||
|
"column.home": "Home",
|
||||||
|
"column.mentions": "Erwähnungen",
|
||||||
|
"column.public": "Gesamtes Bekanntes Netz",
|
||||||
|
"tabs_bar.compose": "Schreiben",
|
||||||
|
"tabs_bar.home": "Home",
|
||||||
|
"tabs_bar.mentions": "Erwähnungen",
|
||||||
|
"tabs_bar.public": "Gesamtes Netz",
|
||||||
|
"compose_form.placeholder": "Worüber möchstest du schreiben?",
|
||||||
|
"compose_form.publish": "Veröffentlichen",
|
||||||
|
"navigation_bar.settings": "Einstellungen",
|
||||||
|
"navigation_bar.public_timeline": "Öffentlich",
|
||||||
|
"navigation_bar.logout": "Abmelden",
|
||||||
|
"reply_indicator.cancel": "Abbrechen",
|
||||||
|
"search.placeholder": "Suche",
|
||||||
|
"search.account": "Konto",
|
||||||
|
"search.hashtag": "Hashtag",
|
||||||
|
"suggestions_box.who_to_follow": "Wem folgen",
|
||||||
|
"suggestions_box.refresh": "Aktualisieren",
|
||||||
|
"upload_button.label": "Media-Datei anfügen",
|
||||||
|
"upload_form.undo": "Entfernen"
|
||||||
|
};
|
||||||
|
|
||||||
|
export default en;
|
49
app/assets/javascripts/components/locales/en.jsx
Normal file
49
app/assets/javascripts/components/locales/en.jsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
const en = {
|
||||||
|
"column_back_button.label": "Back",
|
||||||
|
"lightbox.close": "Close",
|
||||||
|
"loading_indicator.label": "Loading...",
|
||||||
|
"status.mention": "Mention",
|
||||||
|
"status.delete": "Delete",
|
||||||
|
"status.reply": "Reply",
|
||||||
|
"status.reblog": "Reblog",
|
||||||
|
"status.favourite": "Favourite",
|
||||||
|
"status.reblogged_by": "{name} reblogged",
|
||||||
|
"video_player.toggle_sound": "Toggle sound",
|
||||||
|
"account.mention": "Mention",
|
||||||
|
"account.edit_profile": "Edit profile",
|
||||||
|
"account.unblock": "Unblock",
|
||||||
|
"account.unfollow": "Unfollow",
|
||||||
|
"account.block": "Block",
|
||||||
|
"account.follow": "Follow",
|
||||||
|
"account.block": "Block",
|
||||||
|
"account.posts": "Posts",
|
||||||
|
"account.follows": "Follows",
|
||||||
|
"account.followers": "Followers",
|
||||||
|
"account.follows_you": "Follows you",
|
||||||
|
"getting_started.heading": "Getting started",
|
||||||
|
"getting_started.about_addressing": "You can follow people if you know their username and the domain they are on by entering an e-mail-esque address into the form at the top of the sidebar.",
|
||||||
|
"getting_started.about_shortcuts": "If the target user is on the same domain as you, just the username will work. The same rule applies to mentioning people in statuses.",
|
||||||
|
"getting_started.about_developer": "The developer of this project can be followed as Gargron@mastodon.social",
|
||||||
|
"column.home": "Home",
|
||||||
|
"column.mentions": "Mentions",
|
||||||
|
"column.public": "Public",
|
||||||
|
"tabs_bar.compose": "Compose",
|
||||||
|
"tabs_bar.home": "Home",
|
||||||
|
"tabs_bar.mentions": "Mentions",
|
||||||
|
"tabs_bar.public": "Public",
|
||||||
|
"compose_form.placeholder": "What is on your mind?",
|
||||||
|
"compose_form.publish": "Publish",
|
||||||
|
"navigation_bar.settings": "Settings",
|
||||||
|
"navigation_bar.public_timeline": "Public timeline",
|
||||||
|
"navigation_bar.logout": "Logout",
|
||||||
|
"reply_indicator.cancel": "Cancel",
|
||||||
|
"search.placeholder": "Search",
|
||||||
|
"search.account": "Account",
|
||||||
|
"search.hashtag": "Hashtag",
|
||||||
|
"suggestions_box.who_to_follow": "Who to follow",
|
||||||
|
"suggestions_box.refresh": "Refresh",
|
||||||
|
"upload_button.label": "Add media",
|
||||||
|
"upload_form.undo": "Undo"
|
||||||
|
};
|
||||||
|
|
||||||
|
export default en;
|
11
app/assets/javascripts/components/locales/index.jsx
Normal file
11
app/assets/javascripts/components/locales/index.jsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import en from './en';
|
||||||
|
import de from './de';
|
||||||
|
|
||||||
|
const locales = {
|
||||||
|
en,
|
||||||
|
de
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function getMessagesForLocale (locale) {
|
||||||
|
return locales[locale];
|
||||||
|
};
|
|
@ -14,7 +14,7 @@ const initialState = Immutable.Map({
|
||||||
const normalizeSuggestions = (state, value, accounts) => {
|
const normalizeSuggestions = (state, value, accounts) => {
|
||||||
let newSuggestions = [
|
let newSuggestions = [
|
||||||
{
|
{
|
||||||
title: 'Account',
|
title: 'account',
|
||||||
items: accounts.map(item => ({
|
items: accounts.map(item => ({
|
||||||
type: 'account',
|
type: 'account',
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
@ -25,7 +25,7 @@ const normalizeSuggestions = (state, value, accounts) => {
|
||||||
|
|
||||||
if (value.indexOf('@') === -1) {
|
if (value.indexOf('@') === -1) {
|
||||||
newSuggestions.push({
|
newSuggestions.push({
|
||||||
title: 'Hashtag',
|
title: 'hashtag',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
type: 'hashtag',
|
type: 'hashtag',
|
||||||
|
|
|
@ -20,7 +20,7 @@ module Mastodon
|
||||||
|
|
||||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||||
config.i18n.available_locales = [:en]
|
config.i18n.available_locales = [:en, :de]
|
||||||
config.i18n.default_locale = :en
|
config.i18n.default_locale = :en
|
||||||
|
|
||||||
# config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
|
# config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
|
||||||
|
|
59
config/locales/de.yml
Normal file
59
config/locales/de.yml
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
de:
|
||||||
|
about:
|
||||||
|
about_instance: "<em>%{instance}</em> ist eine Instanz von Mastodon."
|
||||||
|
about_mastodon: Mastodon ist ein <em>freier, quelloffener</em> soziales Netzwerkserver. Eine <em>dezentralisierte</em> Alternative zu kommerziellen Plattformen, verhindert es die Risiken, die entstehen, wenn eine einzelne Firma deine Kommunikation monopolisiert. Jeder kann Mastodon verwenden und ganz einfach am <em>sozialen Netzwerk</em> teilnehmen.
|
||||||
|
get_started: Erste Schritte
|
||||||
|
source_code: Quellcode
|
||||||
|
terms: AGB
|
||||||
|
accounts:
|
||||||
|
follow: Folgen
|
||||||
|
followers: Folger
|
||||||
|
following: Folgt
|
||||||
|
nothing_here: Hier gibt es nichts!
|
||||||
|
people_followed_by: Nutzer, denen %{name} folgt
|
||||||
|
people_who_follow: Nutzer, die %{name} folgen
|
||||||
|
posts: Beiträge
|
||||||
|
unfollow: Entfolgen
|
||||||
|
application_mailer:
|
||||||
|
signature: Mastodon-Benachrichtigungen von %{instance}
|
||||||
|
auth:
|
||||||
|
change_password: Passwort ändern
|
||||||
|
didnt_get_confirmation: Keine Bestätigung bekommen?
|
||||||
|
forgot_password: Passwort vergessen?
|
||||||
|
login: Anmelden
|
||||||
|
register: Registrieren
|
||||||
|
resend_confirmation: Bestätigung nochmal versenden
|
||||||
|
reset_password: Passwort zurücksetzen
|
||||||
|
set_new_password: Neues Passwort setzen
|
||||||
|
generic:
|
||||||
|
changes_saved_msg: Änderungen gespeichert!
|
||||||
|
powered_by: angetrieben von %{link}
|
||||||
|
save_changes: Änderungen speichern
|
||||||
|
validation_errors:
|
||||||
|
one: Etwas ist noch nicht ganz richtig! Bitte korrigiere den Fehler
|
||||||
|
other: Etwas ist noch nicht ganz richtig! Bitte korrigiere %{count} Fehler
|
||||||
|
notification_mailer:
|
||||||
|
favourite:
|
||||||
|
body: "Dein Beitrag wurde von %{name} favorisiert:"
|
||||||
|
subject: "%{name} hat deinen Beitrag favorisiert"
|
||||||
|
follow:
|
||||||
|
body: "%{name} folgt dir jetzt!"
|
||||||
|
subject: "%{name} folgt dir nun"
|
||||||
|
mention:
|
||||||
|
body: "%{name} hat dich erwähnt:"
|
||||||
|
subject: "%{name} hat dich erwähnt"
|
||||||
|
reblog:
|
||||||
|
body: "Dein Beitrag wurde von %{name} geteilt:"
|
||||||
|
subject: "%{name} teilte deinen Beitrag"
|
||||||
|
pagination:
|
||||||
|
next: Vorwärts
|
||||||
|
prev: Zurück
|
||||||
|
settings:
|
||||||
|
edit_profile: Profil bearbeiten
|
||||||
|
preferences: Einstellungen
|
||||||
|
stream_entries:
|
||||||
|
favourited: favorisierte einen Beitrag von
|
||||||
|
is_now_following: folgt nun
|
||||||
|
will_paginate:
|
||||||
|
page_gap: "…"
|
61
config/locales/devise.de.yml
Normal file
61
config/locales/devise.de.yml
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
de:
|
||||||
|
devise:
|
||||||
|
confirmations:
|
||||||
|
confirmed: "Vielen Dank für Deine Registrierung. Bitte melde dich jetzt an."
|
||||||
|
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail, mit der Du Deine Registrierung bestätigen kannst."
|
||||||
|
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Du Deine Registrierung bestätigen kannst."
|
||||||
|
failure:
|
||||||
|
already_authenticated: "Du bist bereits angemeldet."
|
||||||
|
inactive: "Dein Account ist nicht aktiv."
|
||||||
|
invalid: "Ungültige Anmeldedaten."
|
||||||
|
last_attempt: "Du hast noch einen Versuch bevor dein Account gesperrt wird"
|
||||||
|
locked: "Dein Account ist gesperrt."
|
||||||
|
not_found_in_database: "E-Mail-Adresse oder Passwort ungültig."
|
||||||
|
timeout: "Deine Sitzung ist abgelaufen, bitte melde Dich erneut an."
|
||||||
|
unauthenticated: "Du musst Dich anmelden oder registrieren, bevor Du fortfahren kannst."
|
||||||
|
unconfirmed: "Du musst Deinen Account bestätigen, bevor Du fortfahren kannst."
|
||||||
|
mailer:
|
||||||
|
confirmation_instructions:
|
||||||
|
subject: "Mastodon: Anleitung zur Bestätigung Deines Accounts"
|
||||||
|
password_change:
|
||||||
|
subject: 'Mastodon: Passwort wurde geändert'
|
||||||
|
reset_password_instructions:
|
||||||
|
subject: "Mastodon: Anleitung um Dein Passwort zurückzusetzen"
|
||||||
|
unlock_instructions:
|
||||||
|
subject: "Mastodon: Anleitung um Deinen Account freizuschalten"
|
||||||
|
omniauth_callbacks:
|
||||||
|
failure: "Du konntest nicht Deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
|
||||||
|
success: "Du hast Dich erfolgreich mit Deinem %{kind}-Account angemeldet."
|
||||||
|
passwords:
|
||||||
|
no_token: "Du kannst diese Seite nur von dem Link aus einer E-Mail zum Passwort-Zurücksetzen aufrufen. Wenn du einen solchen Link aufgerufen hast stelle bitte sicher, dass du die vollständige Adresse aufrufst."
|
||||||
|
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Dein Passwort zurücksetzen kannst."
|
||||||
|
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Dein Passwort zurücksetzen können."
|
||||||
|
updated: "Dein Passwort wurde geändert. Du bist jetzt angemeldet."
|
||||||
|
updated_not_active: "Dein Passwort wurde geändert."
|
||||||
|
registrations:
|
||||||
|
destroyed: "Dein Account wurde gelöscht."
|
||||||
|
signed_up: "Du hast dich erfolgreich registriert."
|
||||||
|
signed_up_but_inactive: "Du hast dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account inaktiv ist."
|
||||||
|
signed_up_but_locked: "Du hast dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account gesperrt ist."
|
||||||
|
signed_up_but_unconfirmed: "Du hast Dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account noch nicht bestätigt ist. Du erhältst in Kürze eine E-Mail mit der Anleitung, wie Du Deinen Account freischalten kannst."
|
||||||
|
update_needs_confirmation: "Deine Daten wurden aktualisiert, aber Du musst Deine neue E-Mail-Adresse bestätigen. Du erhälst in wenigen Minuten eine E-Mail, mit der Du die Änderung Deiner E-Mail-Adresse abschließen kannst."
|
||||||
|
updated: "Deine Daten wurden aktualisiert."
|
||||||
|
sessions:
|
||||||
|
already_signed_out: "Erfolgreich abgemeldet."
|
||||||
|
signed_in: "Erfolgreich angemeldet."
|
||||||
|
signed_out: "Erfolgreich abgemeldet."
|
||||||
|
unlocks:
|
||||||
|
send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Deinen Account entsperren können."
|
||||||
|
send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Deinen Account entsperren kannst."
|
||||||
|
unlocked: "Dein Account wurde entsperrt. Du bist jetzt angemeldet."
|
||||||
|
errors:
|
||||||
|
messages:
|
||||||
|
already_confirmed: "wurde bereits bestätigt"
|
||||||
|
confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an"
|
||||||
|
expired: "ist abgelaufen, bitte neu anfordern"
|
||||||
|
not_found: "nicht gefunden"
|
||||||
|
not_locked: "ist nicht gesperrt"
|
||||||
|
not_saved:
|
||||||
|
one: "Konnte %{resource} nicht speichern: ein Fehler."
|
||||||
|
other: "Konnte %{resource} nicht speichern: %{count} Fehler."
|
112
config/locales/doorkeeper.de.yml
Normal file
112
config/locales/doorkeeper.de.yml
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
---
|
||||||
|
de:
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
doorkeeper/application:
|
||||||
|
name: Name
|
||||||
|
redirect_uri: Redirect URI
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
doorkeeper/application:
|
||||||
|
attributes:
|
||||||
|
redirect_uri:
|
||||||
|
fragment_present: darf kein Fragment enthalten.
|
||||||
|
invalid_uri: muss ein valider URI (Identifier) sein.
|
||||||
|
relative_uri: muss ein absoluter URI (Identifier) sein.
|
||||||
|
secured_uri: muss ein HTTPS/SSL URI (Identifier) sein.
|
||||||
|
doorkeeper:
|
||||||
|
applications:
|
||||||
|
buttons:
|
||||||
|
authorize: Autorisieren
|
||||||
|
cancel: Abbrechen
|
||||||
|
destroy: Löschen
|
||||||
|
edit: Bearbeiten
|
||||||
|
submit: Übertragen
|
||||||
|
confirmations:
|
||||||
|
destroy: Bist du sicher?
|
||||||
|
edit:
|
||||||
|
title: Applikation bearbeiten
|
||||||
|
form:
|
||||||
|
error: Whoops! Bitte überprüfe das Formular auf Fehler!
|
||||||
|
help:
|
||||||
|
native_redirect_uri: "%{native_redirect_uri} für lokale Tests benutzen"
|
||||||
|
redirect_uri: Bitte benutze eine Zeile pro URI
|
||||||
|
scopes: Bitte die "Scopes" mit Leerzeichen trennen. Bitte frei lassen für die Verwendung der Default-Werte.
|
||||||
|
index:
|
||||||
|
callback_url: Callback URL
|
||||||
|
name: Name
|
||||||
|
new: Neue Applikation
|
||||||
|
title: Deine Applikationen
|
||||||
|
new:
|
||||||
|
title: Neue Applikation
|
||||||
|
show:
|
||||||
|
actions: Aktionen
|
||||||
|
application_id: Applikations-ID
|
||||||
|
callback_urls: Callback URLs
|
||||||
|
scopes: Scopes
|
||||||
|
secret: Secret
|
||||||
|
title: 'Applikation: %{name}'
|
||||||
|
authorizations:
|
||||||
|
buttons:
|
||||||
|
authorize: Autorisieren
|
||||||
|
deny: Verweigern
|
||||||
|
error:
|
||||||
|
title: Ein Fehler ist aufgetreten
|
||||||
|
new:
|
||||||
|
able_to: 'Diese Anwendung wird folgende Rechte haben:'
|
||||||
|
prompt: Soll %{client_name} für die Benutzung dieses Accounts autorisiert werden?
|
||||||
|
title: Autorisierung erforderlich
|
||||||
|
show:
|
||||||
|
title: Autorisierungscode
|
||||||
|
authorized_applications:
|
||||||
|
buttons:
|
||||||
|
revoke: Ungültig machen
|
||||||
|
confirmations:
|
||||||
|
revoke: Bist du sicher?
|
||||||
|
index:
|
||||||
|
application: Applikation
|
||||||
|
created_at: erstellt am
|
||||||
|
date_format: "%Y-%m-%d %H:%M:%S"
|
||||||
|
title: Deine autorisierten Applikationen
|
||||||
|
errors:
|
||||||
|
messages:
|
||||||
|
access_denied: Der Resource Owner oder der Autorisierungs-Server hat die Anfrage verweigert.
|
||||||
|
credential_flow_not_configured: 'Die Prozedur "Resource Owner Password Credentials" ist fehlgeschlagen: Doorkeeper.configure.resource_owner_from_credentials ist nicht konfiguriert.'
|
||||||
|
invalid_client: 'Client-Autorisierung MKIM ist fehlgeschlagen: Unbekannter Client, keine Autorisierung mitgeliefert oder Autorisierungsmethode nicht unterstützt.'
|
||||||
|
invalid_grant: Die bereitgestellte Autorisierung ist inkorrekt, abgelaufen, widerrufen, ist mit einem anderen Client verknüpft oder der Redirection URI stimmt nicht mit der Autorisierungs-Anfrage überein.
|
||||||
|
invalid_redirect_uri: Der Redirect-URI in der Anfrage ist ungültig.
|
||||||
|
invalid_request: Die Anfrage enthält einen nicht-unterstützten Parameter, ein Parameter fehlt oder sie ist anderweitig fehlerhaft.
|
||||||
|
invalid_resource_owner: Die angegebenen Zugangsdaten für den "Resource Owner" sind inkorrekt oder dieser Benutzer existiert nicht.
|
||||||
|
invalid_scope: Der angeforderte Scope ist inkorrekt, unbekannt oder fehlerhaft.
|
||||||
|
invalid_token:
|
||||||
|
expired: Der Access Token ist abgelaufen
|
||||||
|
revoked: Der Access Token wurde annuliert
|
||||||
|
unknown: Der Access Token ist nicht gültig/korrekt
|
||||||
|
resource_owner_authenticator_not_configured: 'Die Prozedur "Resource Owner find" ist fehlgeschlagen: Doorkeeper.configure.resource_owner_authenticator ist nicht konfiguriert.'
|
||||||
|
server_error: Der Autorisierungs-Server hat ein unerwartetes Problem festgestellt und konnte die Anfrage nicht beenden.
|
||||||
|
temporarily_unavailable: Der Autorisierungs-Server ist derzeit auf Grund von temporärer Überlastung oder Wartungsarbeiten am Server nicht in der Lage, die Anfrage zu bearbeiten .
|
||||||
|
unauthorized_client: Der Client ist nicht autorisiert, diese Anfrage mit dieser Methode auszuführen.
|
||||||
|
unsupported_grant_type: Der Autorisierungs-Typ wird nicht vom Autorisierungs-Server unterstützt.
|
||||||
|
unsupported_response_type: Der Autorisierungs-Server unterstützt diesen Antwort-Typ nicht.
|
||||||
|
flash:
|
||||||
|
applications:
|
||||||
|
create:
|
||||||
|
notice: Applikation erstellt.
|
||||||
|
destroy:
|
||||||
|
notice: Applikation gelöscht.
|
||||||
|
update:
|
||||||
|
notice: Applikation geupdated.
|
||||||
|
authorized_applications:
|
||||||
|
destroy:
|
||||||
|
notice: Applikation widerrufen.
|
||||||
|
layouts:
|
||||||
|
admin:
|
||||||
|
nav:
|
||||||
|
applications: Applikationen
|
||||||
|
oauth2_provider: OAuth2 Provider
|
||||||
|
application:
|
||||||
|
title: OAuth Autorisierung nötig
|
||||||
|
scopes:
|
||||||
|
follow: Nutzer folgen, blocken, entblocken und entfolgen
|
||||||
|
read: deine Daten lesen
|
||||||
|
write: Beiträge von deinem Konto aus veröffentlichen
|
|
@ -55,3 +55,5 @@ en:
|
||||||
stream_entries:
|
stream_entries:
|
||||||
favourited: favourited a post by
|
favourited: favourited a post by
|
||||||
is_now_following: is now following
|
is_now_following: is now following
|
||||||
|
will_paginate:
|
||||||
|
page_gap: "…"
|
||||||
|
|
27
config/locales/simple_form.de.yml
Normal file
27
config/locales/simple_form.de.yml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
de:
|
||||||
|
simple_form:
|
||||||
|
labels:
|
||||||
|
defaults:
|
||||||
|
avatar: Avatar
|
||||||
|
confirm_new_password: Neues Passwort bestätigen
|
||||||
|
confirm_password: Passwort bestätigen
|
||||||
|
current_password: Derzeitiges Passwort
|
||||||
|
display_name: Anzeigename
|
||||||
|
email: E-mail-Addresse
|
||||||
|
header: Kopfbild
|
||||||
|
locale: Sprache
|
||||||
|
new_password: Neues Passwort
|
||||||
|
note: Über mich
|
||||||
|
password: Passwort
|
||||||
|
username: Nutzername
|
||||||
|
notification_emails:
|
||||||
|
favourite: E-mail senden, wenn jemand meinen Beitrag favorisiert
|
||||||
|
follow: E-mail senden, wenn mir jemand folgt
|
||||||
|
mention: E-mail senden, wenn mich jemand erwähnt
|
||||||
|
reblog: E-mail senden, wenn jemand meinen Beitrag teilt
|
||||||
|
'no': 'Nein'
|
||||||
|
required:
|
||||||
|
mark: "*"
|
||||||
|
text: Pflichtfeld
|
||||||
|
'yes': 'Ja'
|
|
@ -1,8 +1,6 @@
|
||||||
---
|
---
|
||||||
en:
|
en:
|
||||||
simple_form:
|
simple_form:
|
||||||
error_notification:
|
|
||||||
default_message: 'Please review the problems below:'
|
|
||||||
labels:
|
labels:
|
||||||
defaults:
|
defaults:
|
||||||
avatar: Avatar
|
avatar: Avatar
|
||||||
|
|
Loading…
Reference in a new issue